指定
1) Core strategy logic (state machine)
States:
-
BEGINNING_00 (idle)
-
SETUP_00 → SETUP_01 → SETUP_02 → SETUP_03
-
SELL mirror required
Donchian touch triggers:
-
BUY_SETUP_00 triggers ONLY when price touches Donchian LOW
-
SELL_SETUP_00 triggers ONLY when price touches Donchian HIGH
-
Special case: if a candle touches BOTH Donchian high and low, use WAD trend on that candle to decide BUY vs SELL on that candle.
Restart-on-touch (important):
-
If there is no position at the close of candle n, and candle n touches Donchian, then the setup must restart to Setup_00 from candle n (even if previously in Setup_01/02/03).
-
This affects which candle is the “first setup candle” and therefore affects fixed cut-loss, retracement reference, and TP1 base.
Valid setup bar count rules:
-
setup candle t, t+1, t+2, t+3 are valid setup candles
-
t+4 is last chance for a pending stop order fill (same as Python logic)
Fixed stop loss rule (big requirement):
-
In SETUP_01, the cut loss (SL) must be fixed at the FIRST Setup01 candle.
-
Entry trigger level can trail each new setup candle.
-
Intrabar special case:
-
If price breaks the stop-loss side first (e.g., long breaks below stop level) then breaks the trigger level later in the same candle, then the SL is adjusted to the new extreme (and sizing adjusted if needed). Mirror for short.
-
Entry types (user selectable)
A) Normal stop entry:
-
Long: Buy Stop at setup candle High + 1 pip + spread (bid-stream model)
-
Short: Sell Stop at setup candle Low - 1 pip (bid-stream model)
B) Retracement entry:
-
Virtual breakout trigger starts retrace logic when breakout trigger is hit
-
Long: Buy Limit at % retracement from swing high toward swing ref
-
Short: Sell Limit at % retracement from swing low toward swing ref
-
CAP rule:
-
Long: if limit > breakout stop-entry price, cap it at breakout stop-entry
-
Short: if limit < breakout stop-entry price, cap it at breakout stop-entry
-
TP1 / TP2 exits
Two-position hedging mode:
-
At entry, open two separate positions:
-
TP1 leg = 50% volume, has server-side TP at TP1
-
Runner leg = 50% volume, no TP; TP2 logic activates only after TP1 is closed
-
-
Preferred over partial close
TP1:
-
Default TP1 = 1R, but in retracement mode TP1 is based on virtual breakout entry (not the retrace fill price)
TP2 method A — Stochastic trailing (this is the main area that still has issues):
Scanning start:
-
If TP1 hits on candle t, start scanning TP2 on candle t+1
Activation (whichever happens first after scanning starts):
-
Long: %K ≥ 80 OR %K crosses below %D
-
Short: %K ≤ 20 OR %K crosses above %D
Important: -
If TP1 hit and %K is already beyond threshold when scanning starts, activate immediately (no need to cross into it).
Trailing start:
-
If activation happens on candle a, trailing begins on candle a+1:
-
Long: stop = low(a) − 1 pip (applied from a+1 onward)
-
Short: stop = high(a) + 1 pip (applied from a+1 onward)
-
-
Tighten-only trailing (never loosens)
TP2 method B — PSAR trailing:
-
PSAR(t-1) trailing after TP1 closed
-
Freeze when PSAR flips to wrong side; resume when PSAR flips back
(PSAR seems okay)
Risk / sizing:
-
Position size is risk n% of capital m (both inputs)
-
For JPY pairs etc, sizing uses OrderCalcProfit-based calculation to avoid tick-value conversion issues
Execution model:
-
Bid-stream core logic
-
Spread adjustments applied where required (e.g., buy entries, sell SL/TP, etc.)
2) What’s currently wrong
Most state machine is correct now, but TP2 Stochastic trailing sometimes:
-
does not activate when it should
-
or trails using the wrong candle reference
-
or appears inconsistent (sometimes correct, sometimes wrong)
I suspect a combination of:
-
activation gating timing (TP1 close time vs when EA detects it)
-
bar indexing / shift
-
position selection context (PositionSelectByTicket affecting subsequent PositionGet* calls)
-
SL modify failures due to stops/freeze (needs explicit logging)