Free lesson · Quant strategy development
06 / Carry, events, and liquidity provision
Open interactive lessonPractice calculationsExplore labs
Start with the idea
Carry, information surprises and liquidity provision can all produce recurring returns but expose a fund to different risks. Treating them as one generic technical score obscures who is paying the return and why losses may cluster.
Symbols, units & horizon
- Π_h: currency profit over horizon h
- carry_h: holding income in currency
- Δprice_h: currency price P&L at the stated position size
- funding_h,execution: currency expenses
- uₜ: standardised event surprise
- releaseₜ: announced value
- consensusₜ⁻: forecast available strictly before announcement
- σ̂_surprise: training SD in the announcement units
- q*ₜ: model reservation price, not an order size
- mₜ: quote midpoint
- γ: absolute risk aversion in inverse currency
- Iₜ: signed inventory units
- σₜ: absolute price volatility per square-root time, not return volatility here
- τ: remaining time in matching units
When and why to use this
Use separate return and risk accounting for each mechanism. Event surprise features need pre-release consensus; quoting rules need actual inventory and execution data.
Carry strategies seek return from holding a position if pricing conditions remain broadly unchanged. Event strategies seek a response to newly available information or predictable institutional flows. Liquidity provision earns a spread while bearing inventory and information risk. These are distinct mechanisms, even if a bot combines them.
Separate holding income from price changes
- Write holding-period P&L as cash income plus mark-to-market change minus funding and trading cash outflows. Take expectations term by term.
- If your definition of carry already subtracts funding, combine those terms before computing net return so funding is not counted twice.
Expected carry $20, price change −$5, funding $4, execution $3 yields expected net $8 over the defined horizon.
Define carry carefully so financing is not deducted twice. Examples include coupon and roll-down for bonds, forward discounts in currencies, and futures basis convergence. A high carry estimate may compensate for crash exposure, borrow scarcity, or a constraint that prevents the apparent arbitrage.
Normalise an announcement surprise
- Surprise is first-published release minus the consensus available immediately before it. Divide by the training-sample SD of comparable past surprises.
- Rearrange to . This standardisation compares magnitude, not whether a higher value is good or bad for an asset.
Release 3.2%, consensus 3.0%, surprise SD .1 percentage point gives u=2. Consistent percentage-point units prevent a 100-fold error.
For an event surprise, use consensus known immediately before release and the first published value, not a later revision. The response may depend on valuation, policy expectations and positioning. The headline’s timestamp and the bot’s executable quote are different observations.
Interpret the inventory reservation-price adjustment
- Write . Under this convention σ is absolute price volatility per square-root time, I is inventory units and γ is risk aversion per currency; the product is a price adjustment.
- For positive γ and τ, increasing a long inventory lowers q*. A desired shift δ=m−q* implies .
m=$100, γ=.01 per dollar, I=10 units, σ=$2/√day and τ=.25 day gives a $.10 adjustment and reservation price $99.90. Return volatility would require an additional price-scale conversion.
This stylised inventory adjustment lowers a liquidity provider’s reservation price when it is long inventory I. Risk aversion γ, variance and holding horizon τ must have compatible units. It is an illustration of inventory pressure, not a complete market-making algorithm; actual quotes also depend on fill intensity, tick size, fees, queue position and adverse selection.
Python implementation
Self-contained teaching example. Python 3.10+; dependencies and input conventions are shown in the code and notation. Run in your own Python environment.
def carry_pnl(holding_income, expected_price_pnl, funding, execution):
return holding_income+expected_price_pnl-funding-execution
def event_surprise(release, prior_consensus, training_surprise_sd):
if training_surprise_sd <= 0:
raise ValueError("Positive surprise SD required")
return (release-prior_consensus)/training_surprise_sd
def reservation_price(mid, risk_aversion, signed_inventory, absolute_price_vol, remaining_time):
return mid-risk_aversion*signed_inventory*absolute_price_vol**2*remaining_time
print(event_surprise(3.2,3.0,.1), reservation_price(100,.01,10,2,.5))Continue learning
Quant Strategy Development — all lessons- 01 / Start with a source of return
- 02 / The variables that actually enter the decision
- 03 / Test predictive information before a complex model
- 04 / Momentum and trend: information that persists
- 05 / Mean reversion and relative value
- 06 / Carry, events, and liquidity provision
- 07 / Convert a forecast into a trade decision
- 08 / Build a bot that preserves the experiment
- 09 / Decide whether the edge is real enough to continue
Quantitative finance and development glossary · Python resources and libraries · Research sources and limitations