How to Calculate Win Rate in a Backtest (And Why the Same Signals Give Two Opposite Answers)

A backtest win rate is decided by three accounting choices — entry price, exit rule, and price adjustment method — not by the strategy alone. The same batch of A-share signals scored +0.56% under one convention and -0.28% under another, a sign flip caused entirely by the overnight gap.

Updated 2026-08-01

A win rate looks like a property of a strategy. It is mostly a property of your accounting. Before a hit rate means anything, someone has to decide where the trade starts, where it ends, and which price series it is measured against. Change any one of those three and the number moves — sometimes far enough to flip the sign of the average return sitting underneath it.

One batch of signals, two opposite answers

On 2026-07-30 our screener produced a batch of signals from that day's closing data. Every name in the batch opened lower the following morning. Measured one way, the batch made money. Measured another way, on exactly the same names and the same two sessions, it lost money.

Accounting conventionWhat it assumes about your fillAverage result, same batch
Next open to next closeYou could not act until the following session opened, and you accepted whatever the opening auction printed+0.56%
Signal-day close to blend of next-day high and closeYou entered at the closing price of the signal day and exited at an average of the next day's high and close-0.28%
Same signals, same window, 0.84 percentage points apart, opposite signs. The entire difference is the overnight gap.

One caveat about the first row, and it matters: buying at the next open and selling at the next close is a same-session round trip, which T+1 settlement does not permit in a cash account. That convention is a diagnostic — it isolates how much of the result survives once the overnight gap is removed — not a return you could have earned. The shortest executable version is buy on day T+1, sell no earlier than T+2. We keep the +0.56% figure because the comparison is the point, but it should never be quoted as a realised return.

The second convention charges the entry to the signal-day close. If the screen is computed on that day's closing data, that price was already gone by the time the signal existed, and the gap-down lands inside the trade. The first convention starts the clock after the gap has already happened, so the overnight move is charged to whoever held the stock into the morning — not to the strategy. Neither convention is fraudulent. They answer different questions, and a screener that publishes after the close owes readers both numbers, because only one of them contains the gap risk that a reader actually takes.

The three choices that inflate a win rate

ChoiceOptimistic versionWhy it distortsHonest default
Entry priceSignal-day close, session low, or full-day VWAPThe close is computed from the whole session and is only knowable once it can no longer be traded; the low and VWAP assume fills nobody was obliged to give youThe first price you could have transacted at after the signal became known
Exit priceThe highest price reached during the holding window, or any blend that contains the highNobody sells at the high on purpose. A blend quietly grants the rule a timing skill it never demonstratedA rule fixed before the test runs: close of day N, or an explicit stop and target checked bar by bar
Price adjustmentRaw quoted prices, or forward-adjusted prices re-pulled todayRaw prices book ex-dividend drops as losses; forward-adjusted history is rewritten every time a dividend happensOne stated method, with the series frozen alongside the backtest code

Market mechanics that decide what an entry price can be

Chinese A-share cash equities carry rules that quietly invalidate common backtest fills. If your engine was written against US equity assumptions, these are the ones that bite:

  • T+1 settlement: shares bought today cannot be sold until the next session. A backtest that enters and exits within one day is describing a trade the exchange would not permit in a cash account.
  • Daily price limit bands: most main-board names may move at most 10% from the previous close in a session, with 20% on the growth boards. A signal that fires as a name approaches its upper band may be unfillable at the price your test assumes.
  • One-word board (yizi ban, 一字板): the stock opens at the limit and never trades away from it. The book is one-sided, you queue, and most orders never fill. Booking a fill at the open here invents liquidity that did not exist.
  • Opening call auction: the open is set by an auction, not by continuous trading. Modelling the open as just another tradable tick overstates how precisely you can hit it.

Forward-adjusted history moves under your feet

Forward adjustment (qianfuquan, 前复权) anchors the series to the most recent price and recomputes everything earlier from that anchor. Every dividend and bonus issue rewrites the entire history. Pull the same two-year window six months apart and the numbers differ, which means a win rate computed in March cannot be reproduced in September by the same code against the same vendor. For older names with a long record of bonus issues, pushing the adjustment far enough back can produce negative prices. Backward adjustment (houfuquan, 后复权) anchors to the earliest listed price and never rewrites history, which makes it the safer research default. The trade-off is real: backward-adjusted current prices no longer match what a quote screen shows, so anything user-facing needs a translation layer.

Nominal hit rate versus reproduced hit rate

One model in our own stack carried a nominal 61.6% hit rate. That figure came from a tuned parameter set on a specific sample. Re-running the same logic across the full market on forward-adjusted data over 2.5 years produced 56.6%. Those five points are the distance between tuned-on-the-sample and run-on-everything. Applying our actual fee schedule plus the live take-profit and stop-loss thresholds pushed expectancy negative. Switching the benchmark from a broad index to CSI 500 and CSI 1000 turned out-of-sample excess to between -0.3% and -0.5%, which says the positive raw return was mid- and small-cap size exposure rather than selection. Boundary: this is one model of ours, not a claim about anyone else's. What generalizes is the order of testing — full universe, then costs, then a benchmark matched to the size profile of what the rule actually picks.

One boundary we owe the reader, since this article argues against forward-adjusted data: that reproduction was itself run on forward-adjusted prices, so by our own standard the exact figures are not strictly reproducible. We keep them because the conclusions — a gap of about five points, negative expectancy after costs, excess turning negative against a size-matched benchmark — hold at the order-of-magnitude level regardless of adjustment method. The decimals should not be re-quoted.

A rule can pass every statistical gate and still be measuring the index

A separate piece of work tested intraday signals on a single large-cap name using two years of 5-minute bars, in two directions, with a deflated-Sharpe penalty and adversarial validation as gates. The mean-reversion direction failed outright. The momentum direction passed every gate we had. Correlating that signal against the index over the same window returned +0.97: the rule was re-expressing the market trend in a more expensive way. Dropping 45 event-driven sessions did not repair the loss, and plain buy-and-hold over the identical window was positive. A hit rate can be measured correctly, survive multiple-testing corrections, and still tell you nothing about the rule that produced it.

Your data source is part of the result

Two people running identical code against different vendors will report different win rates, and neither is lying. In our own runs, concurrent pulls from the Eastmoney push2his endpoint hit rate limiting and bans; we finished the job against the Sina endpoint instead. akshare and tushare differ in coverage and in request-frequency ceilings. Record the source and the fetch date next to every hit rate you publish, because without them the number is not reproducible even by you.

Five questions to ask about any published win rate

  1. 1What is the entry price, and was it obtainable at the moment the signal became known?
  2. 2What is the exit rule, and does it contain a high, a low, or any blend the trader would have had to time?
  3. 3Which adjustment method was used, and on what date was the series pulled?
  4. 4What universe and what window, and was that same window used to choose the parameters?
  5. 5Against which benchmark is the excess measured, and does the benchmark match the size and sector profile of the names being selected?

What this does not settle

None of this says a high win rate is fake. It says the number is not portable between accounting conventions, and that a hit rate quoted without its convention carries roughly zero information. Win rate is also silent on payoff: a rule can win far more often than it loses and still bleed, if the losses are bigger than the wins. Expectancy is a separate measurement and has to be reported separately. This article covers measurement only. It describes no security, recommends no position, and the figures above are internal test results on our own models, published so the method can be checked rather than trusted.

Related notes