Every number comes from the strategy's receipt (summary.json), written by the backtest
framework (poc/optlab/metrics/stats.py). A blank (--) means the receipt holds null: the number is unknown, not zero.
Amounts are rupees for the sizes in the rules (usually one lot per leg), after brokerage, taxes and exchange charges.
- Net P&L
- Total profit or loss of all closed trades after costs (gross P&L minus brokerage, STT, exchange and SEBI
fees, stamp duty and GST).
- ROI / yr on peak margin
- Net P&L divided by the peak margin, divided by the length of the backtest in years. The peak margin is the
largest SPAN + exposure margin needed on any one day for the trades open that day, so it is the capital the
strategy had to have available. A simple rate, not compounded:
100 x net / peak margin / years,
with years = (end - start + 1 days) / 365.2425. "ROI (period)" is the same without dividing by years.
- ROI minus repo
- ROI per year minus the average RBI repo rate over the same dates. The repo rate is roughly what the same money
earns at no risk, so a strategy is only worth the risk when this is clearly above zero.
- Sharpe (annual)
- Return per unit of risk. Each week's net P&L is divided by the peak margin and the week's repo rate is
subtracted; the Sharpe ratio is the mean of those weekly numbers divided by their standard deviation, times
sqrt(52):
mean / sd x sqrt(52). Weeks without a trade count as 0; weeks with a day the data could not
answer are left out. Each receipt states its exact method (shown on the strategy page as "Sharpe method").
Above 1 is good; below 0 means the strategy did worse than the repo rate.
- t-stat
- How sure we can be that the average trade is really positive and not luck:
mean(net per trade) / (sd / sqrt(n)) with n trades. Around 2 or more (or -2 or less) means the average is
unlikely to be noise (about 95% confidence); near 0 means the sample does not show an edge either way.
- P(loss)
- The chance that the whole backtest would have lost money, estimated by bootstrap: the list of trade P&Ls is
resampled 10,000 times (in blocks of consecutive trades, so losing streaks stay together) and P(loss) is the share
of resamples whose total is below zero. The 5th and 95th percentiles of those totals are shown as the bootstrap
range.
- Max drawdown
- The largest fall of cumulative net P&L from its previous high (starting from 0), in rupees and as a percent of
the peak margin. The red area under the P&L chart is the drawdown at each date.
- Win rate, best and worst trade, worst intraday MTM
- Win rate is the share of trades with net P&L above zero. Worst trade is the largest loss of one closed trade.
Worst intraday MTM is the lowest mark-to-market of any single open trade while it was open (can be worse than the
closing loss).
- Coverage and unknown days
- Eligible days are the days the rules could trade (for example, expiry days). Traded days had a trade.
Unknown days are eligible days the data could not answer: a missing data file, no quote in the entry window,
or a rule that could not be evaluated. Unknown days are left out of every statistic, not counted as zero-P&L
days; their reasons are listed on each strategy page. Many unknown days make every number above less
reliable.
- Verdict
- Set by the framework from the numbers above (poc/optlab/receipts.py):
insufficient data if fewer than 30 trades; promising if t-stat ≥ 2 and ROI per year is above the
repo rate; weak if t-stat ≥ 1 and net P&L is positive; losing if net P&L is negative and
t-stat ≤ -1; otherwise no edge.
- Status
- running: the backtest is still going (the bar shows days done out of days to run; trades and numbers
appear when it finishes). complete: finished. failed: stopped with an error (the reason is in the
caveats).
- Data mode and fill model
- minute runs use intraday option-chain snapshots; eod runs use end-of-day bhavcopy prices only.
The fill model says which price a trade was assumed to get: bid_ask (sell at the bid, buy at the ask),
mid, or close_haircut (the day's close adjusted against us).