05. Legend situation (-62%)
The Elegant Idea of Multi-Timeframe
After hitting an all-time high return of 37,970% with v2.3, I decided to focus on improving the win rate as my next goal. The returns were great, but the win rate was only 55%. That means 45 out of every 100 trades were losers. Psychologically, that's a tough number to stomach.
The idea was intuitive. Instead of relying on a single 5-minute candle prediction, why not aggregate opinions from multiple timeframes? If 15-minute, 30-minute, and 1-hour models all say "bullish," we could filter out false signals -- right?
# v2.5: Trade decision based on signal agreement
horizons = {
3: {'name': '15min', 'down': -0.01, 'up': 0.01},
6: {'name': '30min', 'down': -0.015, 'up': 0.015},
12: {'name': '1hour', 'down': -0.02, 'up': 0.02},
}
# Only trade when all 3 timeframes agree
if agreement_level == 3: # Full agreement
confidence_boost = 0.30 # +30% confidence boost
elif agreement_level == 2: # Partial agreement
confidence_boost = 0.10
else: # Disagreement
should_trade = False # Skip trade
I trained an independent ensemble (LSTM + XGBoost + LightGBM) for each timeframe. Nine models total. 40 minutes of training. A pretty heavy system, but the results were impressive.
68.51% Win Rate, 6.96% MDD -- The Numbers Looked Perfect
| Metric | v2.4 | v2.5 | Change |
|---|---|---|---|
| Win Rate | 54.87% | 68.51% | +13.64% |
| MDD | 50.15% | 6.96% | -43.19% |
| Total Trades | 9,539 | 235 | -97.5% |
| Total Return | 36,250% | 5.61% | --- |
The win rate jumped by 13.64%, and the maximum drawdown dropped from 50% to 7%. Out of 235 trades, 68.51% were profitable. Peak stability. I was quite satisfied with this model.
But that 5.61% total return nagged at me. I rationalized it to myself -- trade frequency dropped by 97.5%, so of course the returns would be lower. "If the win rate is high, I can just increase leverage." That's what I thought at the time.
Why Win Rate Alone Doesn't Guarantee Profits: The Expected Return Formula
Let's step back and look at what the win rate metric actually tells us about profitability from a mathematical perspective. In trading, expected return isn't simply the win rate -- it's defined as:
$$E[R] = WR \cdot \bar{W} - (1 - WR) \cdot \bar{L}$$
Where $WR$ is the win rate, $\bar{W}$ is the average win size, and $\bar{L}$ is the average loss size. The message is clear: no matter how high your win rate is, if each loss is much larger than each win, you lose money.
Think of it like a bet: if you play rock-paper-scissors 10 rounds and win 7, but you earn $1 per win and pay $5 per loss, you end up in the red. It's not the win rate that matters -- it's the "payout structure per round" that really counts.
Plugging in v2.5's numbers:
- Win rate 68.51%, average gain +0.48%
- $E[R] = 0.685 \times 0.48\% - 0.315 \times |\bar{L}|$
The win rate looks great on paper, but generating only 5.61% over 235 trades means the average win and average loss sizes were roughly similar. A truly good system needs not just a high win rate but also a high Profit Factor:
$$PF = \frac{\sum \text{Wins}}{\sum |\text{Losses}|}$$
A PF of 1.0 means break-even, and 2.0+ is solid. Think of PF as a business's revenue-to-cost ratio. A PF of 1.0 is like selling at cost with zero margin, while 2.0+ means healthy profits. v2.5's PF was barely 1.1. Meanwhile, v2.7 (which I'd implement later) achieved a PF of 5.01. Even with a similar ~70% win rate, the quality of trades was completely different.
v2.6: Adding Risk Management Made It Collapse
In v2.6, I added a production-grade risk management layer. Circuit Breakers (pause after consecutive losses), Trailing Stops, ATR-based dynamic stop-losses, and more. I expected these safeguards to make a good model even better.
Backtest results with v2.6 risk management applied to the v2.5 model:
Return: -62.83% Trades: 990, Win Rate: 32.2% Stop-losses triggered: 668 (67.6%)
I was shocked. The "stable" model with a 68% win rate had turned into -62% the moment risk management was applied. 668 out of 990 trades hit the stop-loss. Where did my trusted 68.51% win rate go?
The Trap of Fake Signal Consensus
Digging into the root cause, I discovered a fatal flaw in v2.5's design.
All three timeframe models were using the exact same 5-minute candle data.
Whether it was the 15-minute model, the 30-minute model, or the 1-hour model, the input features were the same 42 indicators derived from 5-minute candles. Only the prediction horizon differed (3, 6, or 12 bars). This wasn't "asking three independent experts for their opinion" -- it was "asking the same person three times."
Fake Independence Through the Lens of Information Theory
Let's express this problem more precisely in information-theoretic terms. Let $S_1$ (15min), $S_2$ (30min), and $S_3$ (1hour) denote the signals from the three models. If these signals were truly independent, the probability of all three reaching the same conclusion would be:
$$P(\text{agree}) = P(S_1 = S_2 = S_3) = P(S_1) \cdot P(S_2) \cdot P(S_3)$$
If each model predicts "LONG" with 60% accuracy, the probability of all three simultaneously calling LONG under the independence assumption is $0.6^3 = 0.216$, or about 21.6%. That would be genuine filtering -- selecting only about 1/5 of all trading opportunities as high-quality signals.
Imagine getting independent diagnoses from three doctors who all say "surgery needed." That's pretty trustworthy. But if all three are reading the same single lab report? Then it's really just one opinion.
But in v2.5, the actual signal agreement rate was 94%. The gap between the theoretical 21.6% (under independence) and the observed 94% was enormous. The tool to quantify this gap is Mutual Information:
$$I(X; Y) = \sum_{x, y} p(x, y) \log \frac{p(x, y)}{p(x) \cdot p(y)}$$
When $I(X; Y) = 0$, $X$ and $Y$ are completely independent; higher values mean the two variables share more information. Since all three models in v2.5 used the same 42 features as input, the mutual information between models was extremely high. They were essentially reading the same information three times, leaving almost no room for differing "opinions."
If three students study from the same textbook and take the same exam, their answers will be nearly identical. High mutual information means too much "shared textbook material." You need different sources to get different perspectives.
This is what information theory calls redundancy. When information sources are independent, their combined entropy increases additively:
$$H(S_1, S_2, S_3) = H(S_1) + H(S_2) + H(S_3) \quad \text{(when independent)}$$
But for correlated sources, the joint entropy is far less than the sum of individual entropies:
$$H(S_1, S_2, S_3) \ll H(S_1) + H(S_2) + H(S_3) \quad \text{(when correlated)}$$
The total information provided by three models was nearly the same as a single model. The filter simply wasn't working.
v2.5's "independent" timeframes:
- 15min model: 42 features from 5min candles -> horizon=3 prediction
- 30min model: 42 features from 5min candles -> horizon=6 prediction
- 1hour model: 42 features from 5min candles -> horizon=12 prediction
-> Same features, so nearly identical predictions -> 94% agreement
What truly independent timeframes would look like:
- 15min model: Independent features resampled from 15min candles
- 1hour model: Independent features resampled from 1hour candles
-> Different information sources -> Meaningful consensus
The 235 trades weren't "carefully curated high-quality signals" -- they were just signals that happened to cross the 70% confidence threshold.
6 Structural Flaws
As I dug deeper into v2.5, the structural flaws hiding behind that 68% win rate became clear.
- Fake signal consensus -- Same features, different horizons. 94% agreement makes the filter meaningless
- SHORT bias -- 709 out of 990 trades (71.6%) were SHORT. A combination of target imbalance and a fixed 0.5 threshold
- Slow features -- RSI-14 (70-minute lag), MA20 (100-minute lag). Unsuitable for 5-minute scalping
- Target-strategy mismatch -- Training target was "direction after N bars," but in live trading, whichever TP/SL gets hit first determines the outcome
- No NO_TRADE class -- Forced to pick a direction even in sideways markets. Attempted trades on every candle
- Fixed 0.5 threshold -- Entered trades even at 51% probability. Many low-conviction trades included
Among these, #4 -- the target-strategy mismatch -- was the most critical. The model was learning a different problem than what it actually needed to solve. No wonder accuracy didn't translate into profits. This problem would be fixed with v2.7's Triple-Barrier approach.
Quality vs Quantity: The Math of the Trade-off
The real lesson of v2.5 was that "win rate and return are metrics on entirely different dimensions."
| v2.3 (Return-focused) | v2.5 (Win Rate-focused) | |
|---|---|---|
| Trades | 9,539 | 235 |
| Win Rate | 55.10% | 68.51% |
| Return | 37,970% | 5.61% |
| MDD | 40.41% | 6.96% |
v2.3 made 9,539 trades at a 55% win rate and generated 37,970% returns. v2.5 made 235 trades at a 68% win rate and generated 5.61% returns. One won by volume, the other by selectivity. But v2.5's "selectivity" was a house of cards built on a fake filter.
Framing this trade-off mathematically, total return decomposes as:
$$R_{total} = N \cdot E[R] = N \cdot \left[WR \cdot \bar{W} - (1 - WR) \cdot \bar{L}\right]$$
Where $N$ is the number of trades. Plugging in v2.3 and v2.5:
- v2.3: $N = 9539$, a small $E[R]$ but $N$ is so large that the compounding effect dominates
- v2.5: $N = 235$, $E[R]$ is slightly higher but $N$ is 97.5% smaller, so total returns are negligible
The key insight is that $N$ and $E[R]$ aren't independent. Tightening the filter raises $E[R]$ but reduces $N$. Finding the sweet spot in this relationship is the challenge -- and v2.5 sacrificed 97.5% of $N$ while its improvement in $E[R]$ was based on a fake filter. The worst of both worlds.
Think of it like fishing. The pickier you are about your bait, the bigger each catch might be -- but if you only land one or two fish after a full day, dinner's going to be sparse. The balance between your bait selection criteria (filter) and how many times you cast (trade frequency) determines your total catch (returns).
The question that haunted me most was this:
Can I raise the win rate while simultaneously maintaining sufficient trade frequency?
Answering this question required more than tweaking model architectures or features. Something more fundamental had to change. I needed to redefine "what to predict" itself. And I found the answer in v2.7's Triple-Barrier.
Looking Back
v2.5 was the model with the best-looking numbers I'd ever built. 68% win rate, 7% MDD. Perfect numbers for a slide deck. But the moment I applied real-world risk management, it produced a devastating -62%.
The lesson this experience taught me is clear.
Backtest win rate doesn't guarantee live profitability. Especially when that win rate was achieved without information independence.
Multi-timeframe as a concept is a great idea. The problem was in the implementation. Reading the same data three times isn't independent information. From an information-theoretic perspective, if the joint entropy $H(S_1, S_2, S_3)$ of three models is nearly the same as a single model's entropy $H(S_1)$, then running three models just triples the cost without adding any information.
Truly independent timeframe features -- actually resampling 15-minute candles, 1-hour candles, 4-hour candles independently -- that's what makes for meaningful consensus. That problem was finally solved in v2.7. In v2.7, I built 67 independent features across 5-minute (27), 15-minute (12), 1-hour (14), and 4-hour (14) candles, and 12 out of the top 20 XGBoost features by importance (60%) were multi-timeframe features. That's the power of true information independence.
Sometimes the most dangerous thing is a "plausible number." I got intoxicated by that 68% win rate and didn't question what foundation it stood on. I learned that the better the numbers look, the harder I should scrutinize them. Profit Factor, the expected return formula, mutual information -- to avoid the trap of any single metric, you need to look through multiple lenses simultaneously.