The Math of Edge: Expectancy, Kelly & Position Sizing
Positive expectancy is the only thing that compounds — and Kelly tells you how much to bet, while isolated margin tells you which balance to bet it from.
Why math is not optional
An autonomous trading agent can have a genuinely profitable signal and lose money. Not because the signals are wrong — because the sizing is wrong. Position sizing is the mechanism that converts edge into returns. Get it wrong in the other direction and you blow up. Get it wrong on the conservative side and you leave returns on the table indefinitely. Get it catastrophically wrong and you execute a slow-motion account destruction while the signal keeps generating profitable ideas.
This lesson covers the math that connects a signal's historical statistics to the size of each position. It is not abstract theory. Every production trading agent has a position-sizing module and every one of them has the same failure modes: sizing off the wrong balance, using native float for money, skipping the decay calculation when positions stack.
Expectancy: the only thing that compounds
Before you can size positions, you need to know whether your edge is real. The test is expectancy.
Expectancy is the expected return per trade, expressed in R-multiples where 1R is the amount you risk per trade. The formula:
E = (winRate x avgWin) - (lossRate x avgLoss)
Where lossRate = 1 - winRate and both avgWin and avgLoss are measured in R.
Only positive expectancy compounds. A strategy with negative expectancy loses money regardless of how many trades it takes. A strategy with near-zero expectancy is effectively paying fees to break even. The threshold for committing an automated agent is a demonstrably positive expectancy over a statistically meaningful trade count — not "it worked last week."
Two cautions before you trust an expectancy number. First, measure the win rate and the average win and loss on out-of-sample data — a walk-forward window the strategy never saw while it was being tuned. In-sample backtest figures are almost always optimistic, and live edge routinely decays from the backtested number. Second, expectancy must be computed net of all costs: maker/taker fees on every round-trip, slippage, and the carrying cost of holding — the funding rate a perpetual charges or pays (typically every eight hours), the overnight swap on forex, or theta decay on options. A gross +0.35R edge that ignores a 0.10%/day funding drain on a multi-day hold can be barely positive, or negative, once netted.
R-multiples matter because they normalize for position size, letting you compare the quality of different strategies and setups on the same scale. A strategy with E = +0.35R is better than one with E = +0.20R regardless of the dollar amounts involved.
Kelly fraction: how much to bet
Positive expectancy tells you to trade. Kelly tells you how much.
The Kelly fraction is the theoretically optimal fraction of capital to risk per trade. Given win probability W and payoff ratio R (avgWin / avgLoss):
f* = W - (1 - W) / R
A few properties to internalize: Kelly is zero when expectancy is zero. Kelly goes negative when expectancy is negative — which means the formula is also a sanity check (negative Kelly = do not trade this setup). Kelly increases with both win rate and payoff ratio.
Full Kelly is almost never used in practice. The reason is estimation error. Your win rate and payoff ratio are measured from a finite sample. That measurement has error. When you plug a slightly-too-high win rate estimate into the Kelly formula, you get a fraction that is too aggressive for the actual (true, unknown) edge. The resulting bet size leads to drawdowns that the mathematical Kelly never predicted, because the mathematical Kelly assumed perfect knowledge of the parameters.
Position sizing: available balance, not total equity
This is where most production failures happen.
Your sizing formula produces a fraction of capital to risk. That fraction is applied to a balance. The question is: which balance?
Total equity is your account value including all open positions and their unrealized PnL. This number looks stable — it moves with the market but stays in the ballpark of your starting capital.
Available balance is the cash that is actually free to commit to a new position. Every open position has committed margin. On isolated margin accounts — which is the standard for perpetual futures — that margin is locked until the position closes. Unrealized profit does not free it. The available balance is total equity minus all committed margin.
If you size off total equity with three positions open, you compute a size that assumes you have your full capital to deploy. You do not. The exchange sees available balance and rejects the order.
The decay factor compounds this. As you open successive positions, each subsequent position should be smaller — both because you have less available balance and because you want to avoid overcommitting when you already have significant exposure. A geometric decay (multiply available by a decay factor for each open position) ensures the agent's aggregate risk stays proportional even as positions stack.
The decay formula: size = available x kellyFraction x decayFactor^openPositions. The first position gets decayFactor^0 = 1.0 (full rate). The second gets decayFactor^1. The third gets decayFactor^2. And so on.
Decimal arithmetic: never native float for money
One rule that production experience enforces immediately: use a Decimal library for all money calculations. Never native float.
The reason is representation error. Floating-point arithmetic cannot represent many decimal fractions exactly. 0.1 + 0.2 in JavaScript equals 0.30000000000000004, not 0.3. For a single calculation this is invisible. For a position-sizing calculation that runs thousands of times, the cumulative error compounds into a sizing discrepancy that causes balance errors at the exchange.
In Python, use the decimal module with Decimal("0.25"), not 0.25. In TypeScript, use a library like decimal.js. The comment // Decimal not float in a sizing function is not pedantry — it is a signal to every future maintainer that the precision here is intentional and load-bearing.
Build it: fractional Kelly sizing off available balance
You are going to implement the position-sizing function: fractional Kelly, applied to available balance, with geometric decay by open-position count, and a hard cap.
What comes next
You now have two of the three core modules: a signal engine that produces a conviction direction, and a position sizer that converts that conviction into a safe size. The third module is execution: submitting the order to the exchange, building the protective bracket, and confirming it is live before you move on. That is the next lesson — orders, slippage, and the confirm-or-halt rule.