Markets I: The Ecosystem and Exchange-Traded Markets · Markets
7P&L and the Accounting of a Position
At 16:05 the trader tells her desk head she made forty thousand dollars. At 17:30 the risk report says thirty-one. The next morning the finance department books twenty-seven. Nobody is lying and nobody has made a mistake: the three numbers use the same six trades and three different answers to the questions “at what price is the position worth what?” and “what did the day cost?”. A trading firm lives and pays its people on this number. This chapter defines it, shows which part of it is arithmetic and which part is convention, and builds the component that computes it.
7.1 Positions and exposure
Definition 7.1 (Position)
A position in an instrument is the signed quantity held: positive (long) if owned, negative (short) if owed. It changes only through fills, corporate actions and transfers; it is the sum of the signed quantities of all of them since inception.
Definition 7.2 (Notional, gross and net exposure)
The notional of a position marked at price is (times the contract multiplier, for a derivative). For a book, the gross exposure is and the net exposure is .
Example 7.3 (A long–short book)
Long $300 million and short $200 million on $100 million of equity: gross $500 million, or the equity, the measure of how much can go wrong; net $100 million, or , the measure of how much market direction is being taken. Limits are set on both, and on each position separately.
7.2 Marking to market
Definition 7.4 (Mark-to-market)
To mark to market a position is to value it at a current market price, the mark, instead of at what was paid for it. The profit and loss of a book over a period is the change in its marked value plus the net cash it produced.
Proposition 7.5 (The P&L identity)
Start flat. After fills with sides (buy ), quantities , prices and fees , the position is , the cash is , and the profit and loss at mark is
It depends on the fills only through : on no accounting convention, and not on the order of the fills.
Proof. The book holds cash and units worth each; it started with nothing. ∎
This is the exact part. Everything is an integer if prices are in ticks or ledger units (Section 1.6), and a P&L system that cannot reproduce it to the unit has lost a trade. The split of that number is where conventions enter.
Definition 7.6 (Average cost, realised and unrealised P&L)
Under the average cost convention an open position carries the quantity-weighted average price of the fills that built it. A fill that reduces the position by units at price realises (plus for a long, minus for a short) and leaves unchanged; a fill that increases it updates ; a fill that flips it closes the old position entirely and opens the remainder at . The realised P&L is the sum of these amounts; the unrealised P&L is .
Example 7.7 (Six fills)
The trader of the opening paragraph buys 20 000 at 49.30 and 20 000 at 49.55 (), sells 10 000 at 50.10 (realising ), buys 10 000 at 49.70 (), sells 25 000 at 50.28 (realising ), and buys 15 000 at 50.20 (). She ends long 30 000 with $26 406 realised. Under first in, first out the same sales are matched to the oldest purchases and realise $28 750. Marked at 50.00 the unrealised parts are $4 594 and $2 250: both conventions total $31 000, as Proposition 7.5 says they must. The split matters for tax and for performance statistics (“win rate”); it never changes what the firm is worth.
Method 7.8 (Choosing a mark)
- The last trade is the most recent information and the worst mark: it is at the bid or at the ask, at someone else’s size, possibly minutes old.
- The mid of a tight, two-sided quote is the usual intraday mark for liquid instruments.
- The side against you — bid for longs, ask for shorts — values the position at what closing it would fetch for a small size; for a large position subtract an estimate of impact as well.
- The official close (closing auction price or settlement price) is what finance, clearing houses and fund administrators use: it is public, unique and auditable.
Decide once, in writing, which mark serves which report. A trader allowed to choose the mark can choose the P&L.
Example 7.9 (Forty, thirty-one, twenty-seven)
The trader’s screen marks at the last print, 50.30: cash plus gives $40 000. The risk system marks at the closing mid, 50.00: $31 000. The $9 000 between them is shares 30 cents of mark. Finance uses the official close, also 50.00, and subtracts $3 400 of fees and $600 of financing: $27 000 (Figure 7.2).
7.3 What a position costs and earns while it is held
Definition 7.10 (Carry)
The carry of a position is the P&L it produces if prices do not move: income received (dividends, coupons, interest on short proceeds) less costs paid (financing of longs, borrow fees on shorts, dividends owed on shorts).
A complete daily P&L therefore has five lines besides price moves: commissions and exchange fees on the day’s fills; financing accrued (Section 6.8); borrow fees; dividends and coupons, booked on the ex-date (Chapter 8); and, for positions in a foreign currency, the move of the exchange rate.
Proposition 7.11 (Currency translation)
A position of units of a foreign asset moves from price to in its own currency while the exchange rate (base currency per unit of foreign currency) moves from to . Its P&L in base currency is
Proof. Expand . ∎
Example 7.12 (A good stock in a bad currency)
A dollar-based fund holds 10 000 shares of a euro stock that rises from 40 to 41 while the euro falls from 1.10 to 1.08 dollars. Price: . Currency: . Cross: . Total . A fund that wants the first number and not the second sells € 400 000 forward; the hedge covers the opening value , never the cross term, and must be resized as the stock moves.
7.4 P&L explain: a first look
Definition 7.13 (P&L attribution)
A P&L attribution, or explain, is a decomposition of a period’s P&L into named causes whose sum equals the total, with any remainder reported as unexplained.
Method 7.14 (The daily explain of a cash book)
With the position at the previous close , and today’s close:
- Carried position: .
- New trades: — each fill measured from its own price to the close.
- Fees, financing, dividends, currency: each its own line.
- Unexplained: total less the sum of the above. For a cash book it should be zero to the cent; anything else is a missing trade, a wrong mark or an unprocessed corporate action.
The identity behind the method is Proposition 7.5 applied between two closes: the first two lines sum to . Line 2 is where a trading desk’s skill shows: a market maker’s new-trade P&L is its spread capture and its adverse selection (Proposition 1.12); its carried-position P&L should be small and is pure risk. For derivatives the first line is itself split by risk factor, which is the subject of One Quant Book 6.
7.5 Tutorial: three numbers, one day
Goal. Replay the six fills, reproduce $40 000, $31 000 and $27 000, and check that the accounting convention does not matter. End state: Figures 7.1 and 7.2.
The keeper’s core, as it is written for the systems side of the firm. Quantity, cash and fees are integers; only the reported split is floating point.
void on_fill(Side side, std::int64_t qty, std::int64_t price, std::int64_t fee = 0) { if (qty <= 0 || price <= 0 || fee < 0) throw std::invalid_argument("bad fill"); const std::int64_t signed_qty = static_cast<int>(side) * qty; cash -= signed_qty * price; fees += fee; const bool adding = quantity == 0 || ((quantity > 0) == (signed_qty > 0)); if (adding) { const std::int64_t open = std::llabs(quantity); avg_cost = (static_cast<double>(open) * avg_cost + static_cast<double>(qty * price)) / static_cast<double>(open + qty); quantity += signed_qty; return; } const std::int64_t closing = qty < std::llabs(quantity) ? qty : std::llabs(quantity); const double direction = quantity > 0 ? 1.0 : -1.0; realised += direction * static_cast<double>(closing) * (static_cast<double>(price) - avg_cost); quantity += signed_qty; if (qty > closing) avg_cost = static_cast<double>(price); // flipped else if (quantity == 0) avg_cost = 0.0; } double unrealised(std::int64_t mark) const { return static_cast<double>(quantity) * (static_cast<double>(mark) - avg_cost); } std::int64_t total(std::int64_t mark) const { return cash + quantity * mark - fees; }Listing 7.1. Average-cost position keeping in C++: add, reduce, flip; and the exact total. code/firm/pnl/cpp/firm_pnl.hpp Replay and mark three ways.
def replay(fills=FILLS) -> Position: p = Position() for _, side, qty, price, _ in fills: p.on_fill(side, qty, units(price)) return p def three_numbers() -> dict[str, float]: p = replay() return { "trader": p.total(units(LAST_TRADE)) / U, # marks at the last print, gross "risk": p.total(units(CLOSING_MID)) / U, # marks at the closing mid, gross "finance": p.total(units(OFFICIAL_CLOSE)) / U - FEES - FINANCING, # official close, net }Listing 7.2. The same position object, three marks and two cost lines. code/markets-1/07-pnl-and-positions/python/pnl_day.py - Run the tests:
make test-code CH=markets-1/07-pnl-and-positions. They assert the three numbers, and that first-in-first-out gives the same total with a different split ($28 750 realised against $26 406). - Stress the identity. The build’s tests replay five thousand random fills and require the split to agree with the exact total.
What to change next. Mark the long at the bid, 49.99: what is the fourth number? Then add a dividend of 20 cents going ex during the day and decide in which line of the explain it belongs.
7.6 Build: the position and P&L keeper
Purpose. The component every strategy, risk check and report of the miniature firm asks: what do we hold, and what is it worth? It is the first piece built in all three languages, because it runs both inside the low-latency process (One Quant Book 13) and in the research and reporting stack.
Interface. Position.on_fill(side, quantity, price, fee), unrealised(mark), total(mark); Book.on_fill(symbol, …), total(marks), gross_exposure(marks), net_exposure(marks). Prices, cash and fees are integers in ledger units.
Rules. total is computed from quantity, cash and fees only, and is exact. The realised and unrealised split follows Definition 7.6. Non-positive quantities or prices and negative fees are rejected. No allocation and no exception on the fill path in the C++ and Rust versions other than for rejected input.
Acceptance tests. code/firm/pnl/tests/, cpp/ and rust/: round trip; average cost and partial close; flip; five thousand random fills with split equal to total; rejections. The three implementations must agree on the same fill file.
Stretch. Add first-in-first-out lots behind the same interface and a switch per account; post each day’s explain lines to the ledger of Chapter 1.
Sources and further reading
- L. Harris, Trading and Exchanges, Oxford University Press, 2003, chapter 21 (performance evaluation).
- R. Grinold and R. Kahn, Active Portfolio Management, 2nd ed., McGraw-Hill, 2000, chapter 17 (performance analysis).
- International Accounting Standards Board, IFRS 13 Fair Value Measurement — the accounting standard behind the choice of marks.
7.7 Exercises
Exercise 7.1 ★
A book is long 40 000 shares at $25, long 10 000 at $120 and short 30 000 at $50, on equity of $2 million. Give its gross and net exposure in dollars and as multiples of equity.
Solution
Solution of Exercise 7.1.
Gross million, equity; net million, .
Exercise 7.2 ★
Starting flat: buy 500 at 20.00, buy 300 at 20.40, sell 600 at 20.50. Give the average cost after each fill, the realised P&L, and the unrealised P&L at a mark of 20.30.
Solution
Solution of Exercise 7.2.
After the first buy ; after the second . The sale realises and leaves 200 shares at . Unrealised at 20.30: .
Exercise 7.3 ★
For the fills of the previous exercise compute the cash, and check Proposition 7.5 at the mark 20.30.
Solution
Solution of Exercise 7.3.
Cash ; .
Exercise 7.4 ★★
Starting flat: sell 1 000 at 80.00, sell 1 000 at 81.00, buy 3 000 at 79.50. Track the position, the average cost and the realised P&L through the flip, and give the total at a mark of 79.80.
Solution
Solution of Exercise 7.4.
Short 1 000 at 80.00; short 2 000 at . The purchase of 3 000 closes the 2 000, realising , and opens a long of 1 000 at 79.50. At 79.80 the unrealised is $300 and the total $2 300.
Exercise 7.5 ★★
A sterling-based fund holds 50 000 shares of a US stock. Over a month the stock goes from $200 to $190 and the dollar from 0.80 to 0.84 pounds. Compute the price, currency and cross terms and the total in pounds.
Solution
Solution of Exercise 7.5.
Price: . Currency: . Cross: . Total : the two large terms cancel and the cross term is the result.
Exercise 7.6 ★★
Yesterday’s close was 30.00 with a position of shares. Today the desk buys 8 000 at 29.60 and sells 5 000 at 29.90; the close is 29.70; fees are $260, the borrow fee accrued is $120 and the short proceeds earned $65 of interest. Produce the explain and the closing position.
Solution
Solution of Exercise 7.6.
Carried: . New trades: . Fees ; borrow ; interest on proceeds . Total . Closing position .
Exercise 7.7 ★★★
Coding. Implement first-in-first-out for positions that may be short as well as long (the chapter’s fifo handles a long-only day). Test it on the fills of exercise 7.4 and report the realised P&L; compare with average cost.
Solution
Solution of Exercise 7.7.
Keep a queue of signed lots; a fill of opposite sign consumes lots from the front, realising with the sign of the lot, and any remainder becomes a new lot. On exercise 4’s fills: , the same as average cost. The two conventions agree whenever a position is closed entirely, since then every lot is consumed; they differ only on partial closes.
Exercise 7.8 ★★★
Find the flaw. A desk reports a win rate of 78% “on closed trades” and a positive realised P&L for eleven consecutive months; its total P&L over the period is negative. Explain how both can be true, which convention makes it easy, and which single report would have revealed it in the first month.
Solution
Solution of Exercise 7.8.
The desk closes its winners and keeps its losers open: each closed trade is a gain, realised P&L is positive every month, and the losses accumulate in the unrealised line, which the report omits. Lot-level accounting with a free choice of which lot to close makes this easiest, but any convention permits it. Proposition 7.5 is immune: the total P&L marked at an independent price, reported daily, shows the loss from the first month. Realised P&L and win rate are descriptions of when a trader chose to close, not of how much was made.
7.8 Problem: Three Numbers, One Day
Problem 7.1
Weekend problem — reconciling a desk’s P&L
You are the desk’s new quant. On your first morning three P&L figures for yesterday are on the head of desk’s table and he wants one. The desk trades one stock. It started the day long 12 000 shares; the previous close was 84.00. Yesterday’s fills, in order: sell 7 000 at 84.60; sell 9 000 at 84.90; buy 6 000 at 84.20; buy 10 000 at 83.70. The last trade of the day printed at 83.55, the closing quote was 83.70 bid, 83.80 ask, and the closing auction price was 83.76. Fees were 0.12 cent a share; financing and borrow cost $310.
Part I — Position and cash.
- Give the position after each fill and at the close.
- Give the cash produced by the day’s fills.
- Compute the fees.
- At which moments was the desk short, and how many shares?
Part II — Three marks.
- Give the day’s gross P&L marked at the last trade.
- At the closing mid.
- At the closing auction price.
- At the price that would be obtained by closing the position against the quote.
- Which mark would you use for the trader’s bonus, and why?
Part III — Explain (use the auction price).
- Compute the carried-position line.
- Compute the new-trades line, fill by fill.
- Add fees and financing and give the net total.
- Check that the unexplained is zero.
- The trader says “I made money trading and lost it on the overnight position”. Is that what the explain says?
Part IV — Realised and unrealised.
- The opening 12 000 shares have an average cost of 82.50. Track the average cost and the realised P&L through the four fills.
- Give the unrealised P&L at the auction price.
- Realised plus unrealised is not the day’s P&L. What is it, and what must be subtracted to recover the day’s figure?
- The clearing broker’s statement shows a closing position of 13 000 shares. List three possible causes in order of likelihood and what you would check first.
- State the named result: the single net P&L for the day that you give the head of desk, and its three largest components.
- In one sentence, state the policy that would have prevented three numbers from reaching his table.
Solution
Solution of Problem 7.1.
1. . 2. . 3. . 4. Between the second and third fills, short 4 000. 5. The position is again 12 000 shares, so the gross P&L is . At 83.55: $8 700. 6. Mid 83.75: $11 100. 7. Auction 83.76: $11 220. 8. A long is closed at the bid, 83.70: $10 500. 9. The auction price: it is public, unique and cannot be influenced by the trader’s own last small print; the $2 520 between the highest and lowest of these marks is otherwise hers to choose. 10. . 11. ; ; ; : . 12. . 13. Gross : nothing is unexplained. 14. Yes, but look closer: nearly all the trading gain comes from the two sales made above the close, that is, from having been less long while the price fell. Both lines are one decision — the view that the stock would fall — and the second purchase gave part of it back. 15. Sell 7 000: realised , long 5 000 at 82.50. Sell 9 000: closes 5 000 (, total 26 700) and opens short 4 000 at 84.90. Buy 6 000: closes 4 000 (, total 29 500) and opens long 2 000 at 84.20. Buy 10 000: long 12 000 at . 16. . 17. is the P&L since the position was opened. Subtract the unrealised P&L carried in yesterday, : $11 220. 18. A fill of 1 000 shares missing from the desk’s records (a late or manually booked execution, or a fill for another desk’s account allocated here) — check the broker’s execution list against the fill log by execution identifier. Then a corporate action or transfer processed by the broker and not by the desk. Last, an error at the broker. 19. $10 872, net, at the official close: from the day’s trades, on the carried position, of fees and financing. 20. One written marking policy — official close for the daily P&L, net of all costs — with every other figure labelled as an estimate.
7.9 Interview questions
Interview question 7.1 ★ trader, developer, researcher
What is the difference between realised and unrealised P&L? Does the choice between first-in-first-out and average cost change how much money you made?
Solution
Solution of Interview question 7.1.
Realised is the gain on the part of the position that has been closed, measured against a cost convention; unrealised is the marked gain on what is still open. The convention moves money between the two and between tax years; it cannot change the total, which is cash plus position times mark and does not know in which order anything was bought.
What the interviewer is looking for: the invariant stated as a formula.
Interview question 7.2 ★ developer
Why should a P&L system not store prices and cash as floating-point numbers? What do you use instead?
Solution
Solution of Interview question 7.2.
Binary floating point cannot represent most decimal prices exactly; sums of many fills accumulate errors that depend on the order of addition, so two systems disagree by a cent and reconciliations break. Use integers in a fixed minor unit (ticks, or ten-thousandths of the currency) for prices and cash, a decimal type in reporting layers, and floating point only for derived statistics such as an average cost.
What the interviewer is looking for: order-dependence and reconciliation, not just “rounding”.
Interview question 7.3 ★★ trader, researcher
You are long 10 000 shares, the last trade is 50.30 and the market is 49.99 bid, 50.01 ask. What is your position worth? What if the position were two million shares?
Solution
Solution of Interview question 7.3.
At the mid, $500 000; to liquidate, the bid: $499 900. The last trade is irrelevant: it is stale and away from the market. For two million shares no screen price applies: the value is the mid less the expected cost of selling that size, a square-root impact of some tens of basis points at least, and a prudent mark carries that reserve.
What the interviewer is looking for: ignoring the last print, and size-dependent valuation.
Interview question 7.4 ★★ developer, trader
Your strategy believes it is flat; the broker’s end-of-day file says it is long 400 shares. Walk through how you find out which is right, and what the system should have done the moment they diverged.
Solution
Solution of Interview question 7.4.
The broker’s record is the legal one. Compare execution by execution, by identifier, the broker’s list with the strategy’s fill log and the drop copy: a fill missing on our side (lost acknowledgement, a partial fill after a cancel request, a fill during a reconnect) is the usual cause. The system should build its position from the drop copy, reconcile it continuously against its own belief, and on divergence stop quoting and alert: a strategy trading on a wrong position hedges the wrong way.
What the interviewer is looking for: drop copy as the source of truth and “stop trading” as the reflex.
Interview question 7.5 ★★ researcher, bank
What is a P&L explain, and what does a persistent unexplained amount tell you?
Solution
Solution of Interview question 7.5.
A decomposition of the P&L into causes — carried positions by risk factor, new trades, carry, fees, currency — that sums to the total. Unexplained P&L that is small and random is noise from approximations; a persistent or growing one means the risk model does not describe the book (a missing risk factor, wrong marks or stale parameters) or that trades are missing or misbooked. Either way the desk does not know what it is exposed to.
What the interviewer is looking for: unexplained as a control signal, not an accounting nuisance.
Interview question 7.6 ★★★ developer
Design the data model of a position keeper that must handle fills arriving out of order, busted (cancelled) trades and price corrections. What is stored, and what is derived?
Solution
Solution of Interview question 7.6.
Store the immutable event log: every fill, bust and correction as its own event with the execution identifier, exchange timestamp, receive timestamp and a reference to the event it amends. Derive everything else: quantity, cash and fees are sums over the log, independent of order by Proposition 7.5, so late and out-of-order fills need no special case for the total. Order-dependent quantities (average cost, realised P&L) are recomputed by replaying the log in exchange-time order from the last checkpoint before the amended event. A bust is a negating event, never a deletion, so that every published figure can be reproduced as of any time.
What the interviewer is looking for: event sourcing, and the observation that the exact total is order-free.