The Trade Signal

An easy Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.

Domain
Python
Difficulty
easy
Seniority
L4
Asked in
Amazon

Problem

An asset's daily closing prices, one per day in order, hide a best single trade: one buy and a later sell with the largest positive gain. Return that gain with the buy and sell day indexes, earliest buy and then earliest sell when gains tie.

Buy low, sell high. Identify the ideal moment.

Example 1

Input:

prices = [7,1,5,3,6,4]

Output:

[5,1,4]

Example 2

Input:

prices = [7,6,4,3,1]

Output:

[0,-1,-1]

Worked solution and explanation

What this really is

Strip the trading costume and this is 'the biggest jump up from the lowest point behind you,' with one twist that changes everything: you report WHERE the jump happened, not just how big it was. The well-known max-profit answer remembers only the lowest price so far and hands back a number. That number is right and the answer is still wrong, because the buy day is gone. The real test is whether you carry the low's price AND its day through one pass, and whether you replace your best window only on a strict improvement so the earliest tradeable pair survives a tie. Forget the day and you can quote the gain but not the trade. Use >= and you quietly report a later window than the one asked for.


Building it up

Step 1: Start from the no-trade signal

Begin with best = (0, -1, -1). That tuple is the no-trade answer, and because any real trade must beat a gain of 0, a flat or falling series never replaces it. Break-even is handled without a special branch.

Step 2: Keep the low and its day together

Walk with enumerate(prices) so each price arrives with its day. When the price is the first one or strictly below low_price, it becomes the new low along with low_day, and there is nothing to sell on that same day, so move on.

Step 3: Commit a window only on strict improvement

Otherwise price - low_price is today's best possible gain. Only when it strictly beats best[0] does the window become (gain, low_day, day). An equal gain found later is a later trade, so it loses.

One pass, carrying the low and its day
def best_trade(prices: list[int]) -> list[int]:
    best = (0, -1, -1)
    low_price = None
    low_day = -1
    for day, price in enumerate(prices):
        if low_price is None or price < low_price:
            low_price = price
            low_day = day
            continue
        gain = price - low_price
        if gain > best[0]:
            best = (gain, low_day, day)
    gain, buy_day, sell_day = best
    return [gain, buy_day, sell_day]
Gain-only shortcut
Tracks min(low, price) and max(best, price - low). Gets 5 on the first example and has no idea the buy was day 1.
Gain with its days
Moves low_day with low_price and stores the whole window as one tuple, so the gain, buy day and sell day can never drift apart.

Common follow-up questions