What the Day Left Open

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

Domain
Python
Difficulty
medium
Seniority
junior
Asked in
Fidelity

Problem

A brokerage's position-keeping service replays the day's executed trades to reconstruct each account's holdings. Each trade names a ticker, a side of buy or sell, and a share count, where buys add to a position and sells subtract from it. Return the net shares held per ticker, dropping any ticker whose position was fully closed out by the close, and keeping the tickers that went net short.

Every fill moves a position. Reconstruct where the book settled by the close.

Example 1

Input:

trades = [{"side":"buy","shares":100,"ticker":"AAPL"},{"side":"sell","shares":40,"ticker":"AAPL"},{"side":"buy","shares":50,"ticker":"MSFT"}]

Output:

{"AAPL":60,"MSFT":50}

Example 2

Input:

trades = [{"side":"buy","shares":30,"ticker":"TSLA"},{"side":"sell","shares":30,"ticker":"TSLA"},{"side":"buy","shares":10,"ticker":"NVDA"}]

Output:

{"NVDA":10}

Worked solution and explanation

Why this problem exists in real interviews

This is a signed group-and-sum wearing a portfolio costume. The skill being probed is whether you can fold the side field into the sign of the quantity BEFORE you accumulate, and whether you understand that a fully closed position is not a zero you report, it is a key you drop. Anyone can tally shares per ticker. The two things that separate candidates are the sign convention (sells are negative) and the final filter (net zero disappears, net short stays). Get the filter backwards and you either leak closed-out tickers into the book or, worse, throw away the short positions the risk desk most wants to see.


Break down the requirements

Step 1: Normalize each trade to a signed quantity

A buy of 40 and a sell of 40 should cancel. The cleanest way is to make the quantity itself carry the direction: keep shares as-is for a buy, negate it for a sell. Now every trade is just a number to add, and the buy/sell distinction never has to be revisited downstream.

Step 2: Accumulate per ticker in one pass

Use a dict keyed by ticker and add the signed quantity with positions.get(ticker, 0) + qty. One pass, O(1) per trade. Reaching for collections.Counter or defaultdict(int) is equally fine; the point is that you never scan the list more than once.

Step 3: Drop the closed-out positions at the end

A ticker that nets to zero was fully closed during the day and must not appear in the result. Filter it out in a final dict comprehension: keep entries where net != 0. Do this AFTER accumulating, not during, because a position can cross zero mid-day and reopen. Negatives are real net-short positions and stay.


The solution

Signed accumulate, then filter zeros
def net_positions(trades):
    positions = {}
    for trade in trades:
        qty = trade['shares']
        if trade['side'] == 'sell':
            qty = -qty
        positions[trade['ticker']] = positions.get(trade['ticker'], 0) + qty
    return {ticker: net for ticker, net in positions.items() if net != 0}

Common follow-up questions