Skip to content

The risk model

The methodology, stated as equations rather than as advice. One idea does most of the work: name the dollars you accept losing and where the trade is wrong, and everything else follows from those two numbers.

A trade is conventionally described as entry, stop, target, size and leverage. That vocabulary conflates risk with position mechanics: a large leveraged position with a wide stop and a small one with a tight stop look similar in it, and are nothing alike in consequence. Anything working in those coordinates can place a position whose loss it never explicitly chose.

So the free parameter here is absolute risk in dollars — the most that can be lost if the invalidation is hit. Everything else is derived:

riskPerUnit = |entry − hard_invalidation_sl|
position_size = absolute_risk_usd / riskPerUnit
notional = position_size × entry
margin = notional / leverage

The practical effect is that a setup cannot be expressed without saying where it is wrong. There is no way to ask for a position without naming the invalidation, because the invalidation is what the size is solved from.

Every rounding decision goes the same way: toward less risk than was accepted, never more.

Size is floored to the venue’s precision, not rounded. Rounding up would place a position whose loss at the stop exceeds the number you agreed to, which is the one error this must never make.

A crossing order is sized against its worst permitted fill, not its requested price. Sizing against the request breaks the bound whenever the fill is worse than asked — the size was solved for one risk distance and the position carries another. A $500 setup with entry 100,000 and stop 98,000 sizes to 0.25; fill it at 100,010 and the stop now costs $502.50. Sizing against the slippage cap costs a slightly smaller position when the fill is good, which is the acceptable side of that trade.

Leverage is a margin-efficiency decision, not a risk decision — risk is already fixed by the first equation — so it is solved for rather than set. The solver starts from entry / (risk_distance × 1.2) and walks down until liquidation sits at least 20% of the risk distance beyond the stop.

The constraint that stops it is liquidation clearing the stop with room to spare. A position that would be liquidated before its own invalidation is not a position with high leverage; it is a position with a stop that will never be reached.

A venue holds one position per market and one leverage setting for it, so leverage is a property of the market rather than of a setup. Two setups on the same market share it.

Per account, and the agent is bound by them exactly as you are.

Cap What it bounds
max_portfolio_risk_usd Total open risk across every position.
max_individual_risk_pct One market’s share of that total, as a percentage.
min_rr Reward-to-risk floor, measured at the heuristic target.
loss_decay_minutes How long a realised loss keeps suppressing the cap.
max_drawdown_pct Fall of the time-weighted return from its high that triggers a hard lockout. Deposits and withdrawals never move it.
exec_timeout_seconds Execution ceilings an agent may ask to tighten, never to exceed.

A loss shrinks the cap, then decays out of it

Section titled “A loss shrinks the cap, then decays out of it”
penalty = cumulative_loss × max(0, 1 − minutes_elapsed / loss_decay_minutes)
effective_cap = max_portfolio_risk_usd − penalty

Linear, reaching exactly zero at loss_decay_minutes rather than trailing off asymptotically — an asymptote leaves a penalty that is never quite gone and a cap that never quite returns. A stop is hit, the realised loss suppresses the cap, fewer new trades fit under it, and the cap recovers on a clock. Set it to zero to disable.

This is the mechanism that makes revenge trading structurally harder rather than merely discouraged. The room to put on the next trade is smaller because the last one lost, and it comes back with time rather than with conviction.

A different mechanism from the decay. It measures the account’s time-weighted return against its high — the same series the returns curve draws, with deposits and withdrawals taken out — and past max_drawdown_pct sets a lockout.

The refusal comes back as a normal result with an explanation rather than as an error. An error invites a retry, and a lockout is the one state where retrying is precisely wrong.