回测基本一致
This commit is contained in:
+52
-14
@@ -204,16 +204,41 @@ Anything that depends on the **path inside a bar**: trailing-stop triggers, the
|
||||
target is touched, exact fill timing on volatile bars. The divergence **scales with
|
||||
path-sensitivity × volatility**:
|
||||
|
||||
| Strategy character | Typical Python vs MT5 gap |
|
||||
|--------------------|---------------------------|
|
||||
| Strategy character | Typical Python vs MT5 gap (bar-level engine) |
|
||||
|--------------------|-------------------------------------------|
|
||||
| Clean directional, few exits | small and consistent: Python reads somewhat higher |
|
||||
| Tight trailing / martingale grid in calm years | small |
|
||||
| Tight trailing / break-even in calm years | **NOT small** — see failure mode below |
|
||||
| Tight trailing / martingale grid **in crash years** | **large** — Python's 4 points miss the finer exits MT5 takes, over-crediting big moves |
|
||||
|
||||
A concrete illustration: a trailing strategy might match MT5 within a few currency units in calm,
|
||||
choppy years, yet the Python figure can be several times the MT5 figure across a violent crash year —
|
||||
because MT5's finer path triggers exits at prices the 4-point model skips. The bias is almost always
|
||||
**Python optimistic**, and almost always concentrated in the most volatile episodes.
|
||||
#### The break-even / trailing failure mode (measured, not theoretical)
|
||||
|
||||
A common assumption is that "calm years → small gap" applies to trailing/BE strategies. **It does
|
||||
not.** A break-even + trailing-stop strategy with bar-level simulation can show a **−40% to −50%
|
||||
net-profit gap even in a calm 3-week window**, while trade count matches MT5 exactly. The mechanism:
|
||||
|
||||
- A bar-level engine updates the BE / trailing SL using the bar's high (or low), then checks the SL
|
||||
on the **same bar's opposite extreme**. If price briefly crossed the BE threshold, the SL is moved
|
||||
to break-even, and the same bar's low (for a long) can trigger that just-moved SL at break-even —
|
||||
booking a **micro-profit** that MT5's tick path would have booked as a small loss (the SL-trigger
|
||||
tick and the BE-trigger tick are separate in MT5, and price can continue past BE to a real loss
|
||||
before the SL fills).
|
||||
- This inflates both the win rate and the gross profit simultaneously. The bias is **always Python
|
||||
optimistic**, and concentrates in the SL/BE exit reason (mean PnL per SL-exit trades reads
|
||||
positive in Python where MT5 reads negative).
|
||||
|
||||
**Fix: M1 tick-level exit simulation.** Load M1 bars and, inside each M5 (or higher) bar, walk the
|
||||
5 M1 sub-bars as 4 synthetic ticks each in direction-aware order (see §2). This separates the
|
||||
BE-update tick from the SL-trigger tick onto different M1 bars, restoring the realistic worst case.
|
||||
Measured impact on a break-even scalper:
|
||||
|
||||
| Mode | Net gap vs MT5 | PF gap vs MT5 | Trade-count gap |
|
||||
|------|----------------|---------------|------------------|
|
||||
| Bar-level (4 sub-ticks) | **−48.5%** | −30.0% | 0% |
|
||||
| M1 tick-level (4 sub-ticks × 5 M1 bars) | **−5.6%** | −7.8% | 0% |
|
||||
|
||||
Trade count is unaffected by the choice (signals still fire on the higher timeframe); only the exit
|
||||
path fidelity changes. Use M1 tick-level simulation for any strategy that moves its SL during a
|
||||
trade (BE, trailing, basket trailing).
|
||||
|
||||
### The practical policy (this is the whole point of the two-tier design)
|
||||
1. **Use Python for fast ranking and A/B** — the *relative order* of setups is preserved, which is all
|
||||
@@ -234,16 +259,29 @@ because MT5's finer path triggers exits at prices the 4-point model skips. The b
|
||||
|
||||
1. Pick **one known preset** of your EA and a short period (a few months).
|
||||
2. Run it in MT5 (1-minute-OHLC model is fine to start) and save the report.
|
||||
3. Run your Python engine on the **same data, same preset**.
|
||||
4. Reconcile **trade by trade**, then in aggregate. Target gates for a clean-directional setup:
|
||||
- Net difference ≤ ~2%, trade-count difference ≤ ~5%, Profit Factor essentially identical,
|
||||
equity-drawdown difference ≤ ~3%.
|
||||
3. Run your Python engine on the **same data, same preset**. **If your EA moves its SL during a trade
|
||||
(break-even, trailing, basket trailing), you MUST pass M1 bars and run tick-level exit simulation
|
||||
(§7) — the bar-level engine is not trustworthy for that class of EA.**
|
||||
4. Reconcile **trade by trade**, then in aggregate. Target gates depend on the EA class and engine mode:
|
||||
|
||||
| EA class / engine mode | Net gap | PF gap | Trade-count gap | Equity-DD gap |
|
||||
|------------------------|---------|--------|------------------|----------------|
|
||||
| Clean-directional, bar-level | ≤ ~2% | essentially identical | ≤ ~5% | ≤ ~3% |
|
||||
| BE / trailing, **bar-level** | **unattainable** — see §7 failure mode (~−40% to −50% net gap) |
|
||||
| BE / trailing, **M1 tick-level** | ≤ ~10% | ≤ ~10% | ≤ ~5% | ≤ ~10% |
|
||||
|
||||
The bar-level gate (≤ ~2%) applies only to setups that don't move the SL intra-trade. For BE/trailing
|
||||
EAs the tick-level gate is wider (≤ ~10%) because residual spread/tick-path differences remain —
|
||||
accept it and **MT5-verify every finalist** rather than chase sub-2% on a tick-sensitive EA.
|
||||
|
||||
5. Only when this passes is the engine trustworthy enough to optimize on. Record the comparison as the
|
||||
engine's **baseline fidelity document** and freeze the engine (doc 04).
|
||||
engine's **baseline fidelity document** (engine mode + measured gap + the window used) and freeze the
|
||||
engine (doc 04).
|
||||
|
||||
> If you can't reconcile, the usual culprits are: signal edge-detection (re-entry every bar), timeframe
|
||||
> mapping/look-ahead, lot-mode mismatch, spread/swap applied on the wrong side or day, or sub-tick
|
||||
> ordering. Walk those five before suspecting anything exotic.
|
||||
> mapping/look-ahead, lot-mode mismatch, spread/swap applied on the wrong side or day, sub-tick
|
||||
> ordering, **or running a BE/trailing EA on the bar-level engine (use M1 tick-level instead)**. Walk
|
||||
> those six before suspecting anything exotic.
|
||||
|
||||
Next: [`04-isolation-rules.md`](04-isolation-rules.md) — the discipline that keeps a validated engine
|
||||
validated.
|
||||
|
||||
Reference in New Issue
Block a user