Claimed vs Measured
This handbook is not about how to pick funds. It is about something more important: how to tell whether your backtest is lying to you. Every example comes from your own two projects — Fund_strategy_X and Fund_strategy_Pareto — using numbers from real runs.
Why you didn't see it yourself
One thing first: you didn't see it because of a lack of fund knowledge.
Of the places where these projects went wrong, not one was about funds. They were all about "measurement" — how to make judgments on a finite dataset without deceiving yourself. That is an independent craft, nearly unrelated to knowing funds. Professional quant teams routinely crash in exactly these places; academia has named these errors, written papers about them, and invented dedicated tests.
Worse, these errors look like success while they are happening. Backtest returns rise, champions refresh, the logs fill with "found a better strategy." Every feedback signal is positive. By the time live trading tells you the truth, a long time has passed.
The 11 lessons below each teach one judgment tool you can use independently. After finishing them, you should be able to take any backtest report and ask the questions that reveal it for what it is.
The information budget: how many hypotheses can you afford
Every strategy you try spends a little of the information in your data. Data is finite, so hypotheses cost money. The first step is always to compute your budget.
Three numbers to compute first
Plug in the real numbers from Fund_strategy_X:
| Quantity | Value | How obtained |
|---|---|---|
| Trading days / trades | 663 | looks like a big sample |
| Effective sample n_eff | ≈157 | after Newey-West correction; the rough 663÷8 = 83 is conservative |
| Funds in pool | 499 | looks like many choices |
| Effective independent assets ENB | 4.4 | mean pairwise correlation 0.25, PC1 explains 39% |
| Registered strategies | 958 | STRATEGY_REGISTRY entries |
How to read it: nominally you chose 1 of 499 funds over 663 days. In reality you had only ~157 independent pieces of information, betting on about 4 independent directions — and you tested 958 hypotheses with them.
Does the champion strategy pass? Put its t-statistic next to the threshold:
It is not even significant in-sample. Where the 5.81 came from: treating 663 overlapping trades as 663 independent samples, inflating the √n in the standard error's denominator by more than 2×. This is the most common kind of self-deception, and entirely unintentional.
"Every day is a fresh judgment" — why that fails
The most natural rebuttal: You make a choice every day, each has an outcome 8 days later — isn't that 663 independent judgments?
This claim can be tested directly — if each judgment were independent, adjacent trades' returns should be uncorrelated. Measured:
The correlation between adjacent trades is +0.79, not 0.
The trade bought on day T covers the price path T+1~T+9; the one bought on T+1 covers T+2~T+10 —
the two share 7 of 8 days. A 5% crash on day T+5 hits both.
These are not two independent judgments; they are the same price movement counted twice.
Behind 663 trades there are only ~671 days of price data; you cannot extract more independent information than those 671 days contain.
Correlation only approaches 0 beyond 6 trades apart — exactly the holding period length.
Of this champion's 663 "decisions," there are actually only 196 distinct positions; the longest ran 65 days unchanged. It is not making new decisions daily at all.
The fixes are in Lessons 6 and 11: spread the money across more funds (diluting single-fund path overlap), and make continuation not consume new quota (hold what you want to keep; spend each day's new quota elsewhere). Only when decisions truly become new does independent information truly increase.
Then ask: how many hypotheses have I tried? Does my t exceed √(2·ln N)?
What overfitting looks like — eight visible signs
Overfitting can be recognized without statistics. It has a very stable appearance. All eight signs below come from Fund_strategy_X, and each can be checked in five minutes.
- 01The strategy name is a string of numbers.
vol10_net33_win223_ret11_e85_ma129_ove54_qb3_vus3_netreg0020_dd5_n15w10r19e4_sharpreflt52_nm020— 13+ tuned parameters and no mechanism statement. The name itself is a fossil of fitting traces. - 02The top ten are bunched together. Top-10 cum_profit runs from ¥32,008 to ¥31,764, only 0.8% apart. This is not "found a good strategy" — it is "took the maximum of a field of noise."
- 03Even the median makes money. Of 355 strategies, the median makes ¥25,320, the champion ¥32,008. Any pick makes money — meaning it is beta being earned, not skill.
- 04Almost no strategy loses money. Even the 5th-percentile avg_ret is +0.148%. A healthy search should produce many failures.
- 05The return magnitude does not belong to this world. 1.64%/8 days ≈ 90%+ annualized. Whenever a backtest yields this magnitude, the right response is "where is the error," not "go live."
- 06The code is bloating out of control.
backtest.pyis 61,808 lines / 2.85 MB / 958 registered strategies. Runaway search leaves traces in file size. - 07The champion changes daily. 20 live trades used 10 different champion strategies — what gets deployed daily is "the freshest overfit."
- 08The system has no entry point for out-of-sample at all.
backtest.pyhas--start-date, but no--end-date. Architecturally it cannot reserve a validation set. This is the deadliest sign.
In-sample vs out-of-sample: the only honest test
Split the data in two: the training segment selects strategies; the validation segment is only reported on, never used in selection. This is the simplest and most powerful step in the whole methodology.
Split Fund_strategy_X at 2026-05-01 and run the same batch of strategies on both segments:
The key reading is the last row. The champion's excess over the equal-weight pool: +1.394% in-sample, −0.133% out-of-sample. All the alpha evaporated and turned negative. Note the benchmark itself also went from +0.187% to −0.187% (the market weakened) — so looking only at absolute returns would misread it as "bad market"; the excess shows the strategy's fund-picking skill never existed.
Why does this happen? Spread the champion's returns by quarter and it becomes obvious — all its returns come from a few bull-market quarters:
| Quarter | Trades | Avg per trade | Win rate |
|---|---|---|---|
| 2024 Q1 | 65 | −0.07% | 55% |
| 2024 Q3 | 65 | +1.85% | 42% |
| 2025 Q2 | 65 | +0.97% | 60% |
| 2025 Q3 | 66 | +5.06% | 76% |
| 2025 Q4 | 66 | −0.08% | 47% |
| 2026 Q2 | 65 | +4.20% | 74% |
| 2026 Q3 | 12 | −10.77% | 0% |
2026 Q3: twelve trades, zero win rate. This is not bad luck. The strategy's structure is "first filter the pool's most volatile funds, then pick the ones that rose longest" — the moment the market turns, it is guaranteed to be fully loaded with the most fragile assets. Tech/semiconductors surged in the sample period, so this structure was necessarily the in-sample champion.
Without a benchmark, there is no alpha
Both projects report a metric called oracle efficiency:
your return ÷ the return of perfectly knowing each day's best fund. It answers "how far from the upper bound,"
but cannot answer "is there any skill at all" — in a bull market even a pure-beta strategy has a decent efficiency.
What you need is a zero-skill baseline: buy all qualifying funds equal-weight every day. The difference is skill.
The words "those same trading days" are the key. Selective strategies and daily strategies trade on different days; comparing against the full-period pool mean credits it with timing it never expressed.
The excess of these two pools still needs out-of-sample testing to count — Lesson 3 already showed in-sample excess can evaporate entirely. But at least the dividing line now exists, and the question can be asked.
Metrics shape behavior: you get what you optimize
Fund_strategy_X's objective function is cum_profit, defined as:
This definition contains no risk at all. Overlapping positions are summed as if independent trades, so "putting all the money on one fund at the same time" goes entirely unpunished.
So the search's champion grew into this:
| Metric | Value | Meaning |
|---|---|---|
| Trades / funds used | 663 / 44 | highly concentrated |
| Largest position share | 20.1% | 1/5 of trades in one fund |
| Longest streak buying the same fund | 65 days | the same fund bought on 65 consecutive decision days |
| Max simultaneous trades in one fund | 6 | ¥18,000 all on one fund = the entire portfolio |
| Strategy's own max drawdown | −70.6% | the median strategy is also −70.6% |
Note the last row: the champion's own drawdown is −70.6%, yet drawdown was never looked at when choosing it. Live confirmation: the 8-day pool's 20 trades bought only 3 funds, 13 trades in the same one. This is not a portfolio; it is repeated bets on a single ticket.
More ironic still: both projects' oracle/engine.py already
contain a real portfolio engine — simulate_strategy() with cash, T+2 settlement, a max position count,
and per-fund exposure caps.
In both projects it was never called once.
The only free lunch: portfolio construction
Everything so far was bad news. This lesson is good news, and the only return source in this handbook that requires no forecasting skill.
When the signal is weak (such systems' information coefficients are typically 0.02~0.05), the risk reduction comes mainly from diversification, not from picking precision. Diversification is math, not judgment — it does not stop working when the market changes.
daily budget ÷ N. Total investment and peak capital use stay unchanged.This is "the same money spread over more funds," not "leveraging up to buy more" — only this way can multi-pick variants be compared with single-pick on the same risk axis.
Below are results actually run on the Pareto project:
| Portfolio width | Return/trade | Ann. vol | Max DD | Sharpe | Calmar | Funds used |
|---|---|---|---|---|---|---|
| Buy 1 (original design) | 0.463% | 10.99% | 17.49% | 0.790 | 0.611 | 142 |
| Buy 3 | 0.401% | 9.13% | 11.99% | 0.901 | 0.853 | 272 |
| Buy 8 | 0.337% | 7.71% | 10.96% | 0.949 | 0.850 | 380 |
| Buy 5 + ≤2 trades per fund | 0.318% | 7.04% | 10.17% | 0.950 | 0.853 | 411 |
Max drawdown −42%, Sharpe +20%, Calmar +45%. The cost is per-trade return falling from 0.463% to 0.318% — but risk fell more, so risk-adjusted it is a net gain. The QDII pool benefits more: max drawdown from 30.10% to 13.71% (−54%), Calmar +72%.
One side effect deserves its own paragraph. Lesson 5's pathology of "65 consecutive days buying the same fund" is eliminated outright by the single constraint "at most 2 simultaneous trades per fund" — and this constraint requires no judgment about the future at all.
Backtest vs live reconciliation: distinguishing two diseases
When live trading loses money, there are only two possibilities, with completely different remedies:
There is only one way to tell them apart: reconcile. Take every live trade, replay it with the backtest engine on the same day, same strategy, and compare the returns on both sides.
The backtest engine already "knew" these trades would lose 10% — it was simply never asked. It is honest — what went wrong was the strategy-selection process, not the computation. This conclusion fixes the direction of all subsequent repairs: do not audit the data pipeline; change the research methodology.
Three layers of validation: only one is clean
The Pareto project designed three validation layers. Understanding their differences is the core of the whole methodology.
| Layer | What it is | Peek level | Cost |
|---|---|---|---|
| L1 | Three objectives over the full history | Full peeking — selection was done on exactly this | Available immediately |
| L2 | Holds out each year's Jan/May/Sep from training | Partially clean — but see the trap below | Available immediately |
| L3 | Records the filing date; only counts data arriving after filing | Zero peeking — the data did not exist yet | Requires waiting months |
L3 is the most correct idea in the whole system: the true test set is the future, and this layer is continuous bookkeeping against the future. It cannot be faked — because when a strategy is filed, the data that will evaluate it does not exist yet.
The L2 trap: a fixed calendar smuggles in seasonality
Holding out the fixed months of January, May, and September looks reasonable — the rule is explicit and auditable. But the "out-of-sample" carved out this way is collinear with seasonality.
The QDII pool's measured results expose this:
Two consequences: first, the "holdout-month return > 0" threshold is passed by everyone on QDII — zero screening power; second, worse — it rewards strategies that happen to load more heavily on those three months.。
The fix is to replace the fixed calendar with random/rotating blocks (combinatorial purged cross-validation). Pareto already uses exactly this blocking mechanism for PBO — port it over.
PBO and DSR: scoring the "selection process" itself
These two metrics do not evaluate strategies; they evaluate the process by which you selected them. That is what makes them special.
PBO — probability of backtest overfitting
Slice time into many blocks and repeatedly "pick the best strategy on half the blocks, then see its rank on the other half." PBO = the probability that the picked champion ranks below the median on the other half.
DSR — deflated Sharpe ratio
Folds "how many hypotheses you tried" into the significance. The more you try, the less the same Sharpe is worth. DSR is a probability: the probability that this strategy's true Sharpe exceeds 0. Convention requires > 0.95.0.95。
| Diagnostic | 8-day pool | QDII pool | Reading |
|---|---|---|---|
| PBO | 0.475 | 0.557 | selection ≈ coin flip / worse than a coin flip |
| Strategies with DSR > 0.95 | 0 / 20 | 2 / 21 | the 8-day pool tops out at 0.769 |
| Trials counted | 391 | 364 | distinct candidate versions |
| L3 data accumulated | none | none | earliest filing date 2026-07-09 |
These three numbers together say: there is currently nothing statistically deployable.
That is not bad news — it is this architecture's most valuable output. Fund_strategy_X lacked this capability,
and lost 8.3% in one month (−¥8,411 / ¥101,290; 24 settled trades with an 8.3% win rate).
Knowing "not yet deployable" is itself enormous value.
The right move is not to turn them into hard gates (that would cut away low-risk valid anchors), but into a position-sizing function:
capital fraction = baseline × DSR × (1 − PBO) × min(1, L3 sample count / 30)Today this computes to nearly 0 — and that is exactly the right answer. It scales up automatically as L3 accumulates; it is the only mechanism where "time is on your side."
Search is not selection — the correct shape of unlimited search
If compute were free, you would of course want to search without limit. This lesson explains why that is entirely possible, and what conditions it requires.
The key: DSR and PBO do not punish "how much you searched," but "how many selections you made on the same data." These two things can be separated.
| Stage | Constraint | Why |
|---|---|---|
| Generating candidates | Fully unbounded — run as much as you like | search itself carries no statistical cost |
| Slots entering L3 tracking | Bounded (20~50 suggested), elimination rules fixed in advance | this is the true "number of trials" |
| Live selection | Look only at L3 | L3 data does not exist when candidates are filed |
Using training data to screen "which hypotheses are worth testing on new data" is entirely legitimate — that is the screening stage. Overfitting happens when you use the same data both to screen and to conclude. Push the conclusions to L3, and whether you searched 10 thousand or 1 million before has no effect on L3's validity.
Companion: turning logs from "things tried" into "hypotheses tested"
One more way to make unlimited search and meaningful statistics coexist: do inference at the "mechanism" level, not the "parameter variant" level.
Require every candidate to declare a mechanism_id from a controlled vocabulary — adding a new mechanism is a slow action requiring a written economic rationale. Then:
Within a family, variation can be unlimited (free, no cost); statistical inference happens at the family level (bounded, meaningful). One precondition: family representatives must not be picked by training performance, or within-family multiple testing returns — use equal weight within the family, or let L3 performance decide.
The four things every hypothesis should state clearly: economic mechanism / expected direction / expected magnitude / failure condition. No more than 2 parameters. Write it down and file it before running the data.
vol10_net33_win223_ret11_e85_ma129_ove54…
— 13+ parameters, zero mechanism statement.Good example: "Sector momentum continuation: sectors in the top 20% of 20-day gains outperform the equal-weight pool over the next 8 days. Mechanism = cash-flow inertia + fund subscription/redemption lag. Failure condition = reversal when market volatility enters its high range."
Holding period or quota: a decision that got hardcoded
The last lesson comes from an easily overlooked observation: what exactly is the "8-day holding period"?
It is the redemption-fee-free eligibility day, not a forced exit day. At maturity the position becomes eligible to be reclaimed, not required to be. If the strategy still wants this fund today, you do nothing at all — just keep holding it.
The holding period is a free variable; turnover is endogenous, not exogenously imposed.
But the current system deleted this decision. In the backtest, future_return is a fixed
8-day forward return — every candidate is a forced 8-day round trip.
Nowhere in the candidate space is there a "continue holding or switch" choice.
This explains the 65-day mystery
Back to Lesson 5's "65 consecutive days buying the same fund." We previously classified it as a concentration pathology. But viewed through the correct framework —
Conversely: if continuing a hold does not consume new quota, then each day's ¥4,000 naturally goes elsewhere — diversification appears for free, with no enforcement needed.
Now look again at the two worst live trades: 5.4055 → 4.0572 (−24.9%),
5.0748 → 3.9466 (−22.2%). Forced to sell into the hole on day 8.
With a "continue holding or switch" decision, that would have been optional.
| Stage | Fixed 8 days (current) | Variable holding |
|---|---|---|
| Evaluation core | sum of fixed forward returns | a true portfolio state machine |
| Objective 1 | avg return per trade | equity-curve annualized return |
| Objectives 2, 3 | volatility / drawdown | unchanged |
| Drawdown normalization denominator | daily budget × holding days | unchanged — it was always a "quota" |
The good news is the risk axis's structure survives entirely — because the denominator was defined as "quota" rather than "holding period" from the start. Only "avg return per trade" needs to become "annualized return" (per-trade returns stop being comparable under long holds).
Twelve questions before going live
Ask these, in order, of any backtest report handed to you. The ones it cannot answer are where the problems are.
- What is my effective sample size?Not the number of trades. Look at adjacent-trade autocorrelation first, then use Newey-West corrected standard errors.
- How many hypotheses have I tried in total?Counting all variants. Does t exceed √(2·ln N)?
- Relative to what benchmark? What is the excess?Absolute returns without a benchmark always look good in a bull market.
- What fraction of in-sample performance survives out-of-sample?Below 50% is suspicious; going negative means there was never anything.
- How many market regimes does the sample cover? Any bear markets?A sample with only rallies cannot test structural risk.
- Did the data used as "out-of-sample" exist when the selection was made?Only if it did not is it truly out-of-sample.
- Is the split rule collinear with seasonality?Fixed calendar months are a common trap.
- How many numbers are in the strategy name?More than 3 is a fitting trace.
- Does the conclusion survive ±10% parameter perturbation?What holds only at one point is noise.
- What does the objective function fail to punish?Whatever it doesn't, the optimizer will trade away for returns.
- Does this return magnitude exist in the real world?90% annualized does not.
- Do live and backtest reconcile?If not, it is an execution problem; if yes and still losing, a strategy problem.
Glossary
- In-sample / out-of-sample
- In-sample = the data segment used to select strategies; out-of-sample = data that took no part in selection. Only the latter's performance counts as evidence.
- Overfitting
- The model learned the noise in this dataset, not a repeatable pattern. The signature: excellent in-sample, collapse out-of-sample.
- Multiple testing
- The more hypotheses tried, the more likely "the best one" is merely lucky. The correction raises the significance threshold:
√(2·ln N). - Effective sample size
- Trades with overlapping holding periods are highly correlated and are not independent observations. The rough estimate is
trading days ÷ holding days(conservative); the rigorous route back-solves from Newey-West corrected standard errors. - Newey-West standard errors
- Standard errors robust to autocorrelation and heteroskedasticity. Mandatory with overlapping holding periods; the lag order is usually "holding days − 1". It does not change the mean, only widens the standard errors — i.e., it knocks the inflated t back to its true size.
- Effective number of independent assets (ENB)
- The number of independent choices a set of highly correlated assets actually offers. 500 funds with pairwise correlation 0.25 ≈ 4.4 independent directions.
- beta / alpha
- beta = the part you get for free by rising and falling with the market; alpha = the part above the benchmark — the only part that is skill.
- PBO (probability of backtest overfitting)
- The probability that your picked champion ranks below the median on the other half of the data. 0.5 = the selection process is a coin flip.
- DSR (deflated Sharpe ratio)
- After folding in the number of trials, the probability that "true Sharpe > 0". Convention requires > 0.95.0.95。
- Purge / Embargo
- When splitting train and validation, delete training samples whose outcomes fall inside the validation segment. Overlapping holding periods cause information leakage and must be purged.
- Pareto frontier / non-dominated
- Under multiple objectives, the options no other option dominates (worse-or-equal everywhere, strictly better somewhere). It presents trade-offs; it does not provide "the optimum".
- Maximum drawdown (MDD)
- The largest fall of the equity curve from a historical peak. Measures "how bad the worst moment feels."
- Calmar / Sharpe
- Calmar = return ÷ max drawdown; Sharpe = excess return ÷ volatility. Both are risk-adjusted returns.
- Observation alignment
- Label a NAV by "the day you could actually see it," not "the day it corresponds to." Domestic T→T+1, QDII T→T+2. Prevents look-ahead bias.
- Look-ahead bias
- The backtest used information not yet available at the time. The stealthiest and deadliest class of backtest error.
- Survivorship bias
- Counting only funds alive today, ignoring those liquidated along the way. Systematically overstates historical returns.
Calibrate expectations to the right magnitude
After all this, the most important adjustment may be expectations.
An honest goal: beat the equal-weight fund pool by 2~5%/year over the long run, with a significantly smaller max drawdown. That is already a solid result. Not 90% annualized.
Fund_strategy_X's root cause on that path was its objective function assuming from day one that "90% annualized is reachable" — so all its search headed toward the noisiest directions.
What you can reliably get, ranked by reliability
- Diversification — pure math, no forecasting needed. Measured to cut drawdown by 42%~54%.
- Not deploying overfit things — requires wiring PBO/DSR/L3 into position sizing.
- Zero fee rates — already yours; don't waste them with high turnover.
- Fund-picking alpha — fourth, and the least reliable.
If the goal is profit, "is 8-day rotation of domestic funds even the right vehicle" deserves to be asked on its own — a slower, more diversified, lower-turnover version, simply because longer horizons have better signal-to-noise and a smaller multiple-testing burden, is very likely better risk-adjusted.