metrics.economics¶
Turns a pass probability plus your own prices into an expected value per attempt, and the pass rate at which it turns positive.
economics
¶
Expected value of attempting a Combine: is the subscription worth paying?
A pass probability alone does not tell you whether to attempt an evaluation.
60% is excellent at $49/month and terrible if a pass is worth $200 to you. This
module turns a :class:~topstep_backtest.metrics.montecarlo.MonteCarloResult
plus the prices YOU actually pay into an expected value.
Every price is a required input. Nothing is baked in. Combine fees, reset
pricing and payout terms change, vary by promotion, and are exactly the class of
number this project refuses to hard-code uncalibrated
(docs/topstep-rules.md §9). Passing your own figures is not a chore here — it
is the only way the answer means anything.
The honest headline is breakeven_pass_value, not ev. ev requires you
to state what a funded account is worth to you, and that single assumption
dominates the result — it depends on your funded-phase performance, the payout
schedule, and the scaling plan, none of which this package models (Express
Funded is parked; see docs/ROADMAP.md). breakeven_pass_value inverts the
question into one you can answer without guessing: how much would a pass have
to be worth for this attempt to be worth making? If that number is
uncomfortable, no EV estimate will rescue it.
EvalEconomics
¶
Bases: Struct
What one evaluation attempt costs YOU. No defaults on the prices.
monthly_fee
instance-attribute
¶
The Combine subscription, per month. Billed for as long as the attempt runs, which is why a slow edge is expensive even when it eventually passes.
pass_value
instance-attribute
¶
What reaching a funded account is worth to you, in dollars.
There is no defensible default and this package will not invent one — it
depends on your funded-phase results and the payout schedule, neither of
which is modelled here. If you cannot state it, read
EvalEV.breakeven_pass_value instead and ignore ev entirely.
reset_fee
class-attribute
instance-attribute
¶
Cost to reset a blown account and continue within the same
subscription. None means you re-subscribe from scratch instead, and a
failed attempt costs a fresh monthly_fee.
trading_days_per_month
class-attribute
instance-attribute
¶
trading_days_per_month: int = BILLING_MONTH_DAYS
Sessions billed per monthly period — the SAME constant the Monte Carlo defaults its horizon to, so "one attempt" means one fee cycle on both sides of an EV calculation. Override it if your data says otherwise.
EvalEV
¶
Bases: Struct
Expected value of one attempt, and the number that needs no assumption.
expected_months
instance-attribute
¶
Billed months per attempt: days-to-pass for a winning path, the full
horizon for a losing one, divided by trading_days_per_month and rounded
UP — a subscription is not prorated by the day.
expected_cost
instance-attribute
¶
Subscription plus any reset fee, weighted by outcome.
ev
instance-attribute
¶
expected_gross - expected_cost. Only as meaningful as
pass_value, which you supplied and this package cannot check.
breakeven_pass_value
instance-attribute
¶
The pass_value at which ev becomes zero — how much a pass must
be worth to justify the attempt.
Requires no assumption about payouts and is therefore the figure to lead
with. None when the pass probability is zero: no finite value justifies
an attempt that cannot succeed, and reporting a number there would be
arithmetic dressed up as advice.
breakeven_pass_probability
instance-attribute
¶
The pass probability at which ev becomes zero, holding
pass_value fixed. Compare it against the Monte-Carlo figure to see how
much headroom the attempt has. None when pass_value is zero.
evaluate_ev
¶
evaluate_ev(mc: MonteCarloResult, *, economics: EvalEconomics) -> EvalEV
Combine a bootstrapped outcome distribution with your own prices.
Uses mc.pass_probability and mc.median_days_to_pass (median, not
mean: days-to-pass is right-skewed, and the mean is dragged by the paths
that scrape in at the horizon). A failing attempt is billed for the full
horizon, because you pay until you quit or blow up.
Every arithmetic step stays in Decimal; nothing here is estimated by
simulation, so nothing here needs floats.