Last active
November 23, 2025 09:28
-
-
Save Elvmeen/303b4cc58209739c544c753d55460b5d to your computer and use it in GitHub Desktop.
Version 6.7
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //+------------------------------------------------------------------+ | |
| //| Proportional Trailing EA (Corrected) | | |
| //| SL reaches breakeven at 50% progress, continues trailing after | | |
| //+------------------------------------------------------------------+ | |
| #property strict | |
| #include <Trade\Trade.mqh> | |
| input double TrailStepPercent = 2.0; // Update every X% of progress | |
| input int CheckIntervalMS = 1000; // Milliseconds between checks | |
| input bool ShowDebugInfo = true; // Show trailing logs | |
| CTrade trade; | |
| datetime lastCheck = 0; | |
| struct TradeMemory { | |
| ulong ticket; | |
| double initialSL; | |
| }; | |
| TradeMemory mem[200]; | |
| double GetInitialSL(ulong ticket, double currentSL) | |
| { | |
| for(int i = 0; i < 200; i++) | |
| { | |
| if(mem[i].ticket == ticket) | |
| return mem[i].initialSL; | |
| if(mem[i].ticket == 0) | |
| { | |
| mem[i].ticket = ticket; | |
| mem[i].initialSL = currentSL; | |
| return currentSL; | |
| } | |
| } | |
| return currentSL; | |
| } | |
| void OnTick() | |
| { | |
| if((TimeCurrent() - lastCheck) < CheckIntervalMS / 1000.0) return; | |
| lastCheck = TimeCurrent(); | |
| int total = PositionsTotal(); | |
| for(int i = 0; i < total; i++) | |
| { | |
| ulong ticket = PositionGetTicket(i); | |
| if(!PositionSelectByTicket(ticket)) continue; | |
| string sym = PositionGetString(POSITION_SYMBOL); | |
| double entry = PositionGetDouble(POSITION_PRICE_OPEN); | |
| double currentSL = PositionGetDouble(POSITION_SL); | |
| double tp = PositionGetDouble(POSITION_TP); | |
| long type = PositionGetInteger(POSITION_TYPE); | |
| if(currentSL == 0 || tp == 0) continue; | |
| double initialSL = GetInitialSL(ticket, currentSL); | |
| double point = SymbolInfoDouble(sym, SYMBOL_POINT); | |
| if(type == POSITION_TYPE_BUY) | |
| { | |
| double price = SymbolInfoDouble(sym, SYMBOL_BID); | |
| double progress = (price - entry) / (tp - entry); | |
| if(progress <= 0) continue; | |
| double step = TrailStepPercent / 100.0; | |
| double stepsCompleted = MathFloor(progress / step); | |
| double effectiveProgress = stepsCompleted * step; | |
| double newSL; | |
| if(effectiveProgress <= 0.5) | |
| { | |
| // Phase 1: Move from initialSL to breakeven (entry) | |
| // At 50% progress, SL should be at entry | |
| newSL = initialSL + (entry - initialSL) * (effectiveProgress * 2.0); | |
| } | |
| else | |
| { | |
| // Phase 2: Continue from breakeven toward midpoint | |
| // At 100% progress, SL should be at entry + 50% of (TP - entry) | |
| double beyondBreakeven = effectiveProgress - 0.5; | |
| double profitDistance = (tp - entry) * 0.5; | |
| newSL = entry + (profitDistance * beyondBreakeven * 2.0); | |
| } | |
| // Safety buffer | |
| int stopsLevel = (int)SymbolInfoInteger(sym, SYMBOL_TRADE_STOPS_LEVEL); | |
| double minDistance = MathMax(stopsLevel * point, point * 5); | |
| double maxAllowedSL = price - minDistance; | |
| if(newSL > maxAllowedSL) newSL = maxAllowedSL; | |
| if(newSL > currentSL) | |
| { | |
| if(trade.PositionModify(ticket, newSL, tp)) | |
| { | |
| if(ShowDebugInfo) | |
| { | |
| string status = (newSL >= entry) ? "β BREAKEVEN+" : "π‘ Trailing to BE"; | |
| Print("BUY ", sym, " | Progress: ", DoubleToString(progress * 100, 1), "%", | |
| " | New SL: ", DoubleToString(newSL, _Digits), | |
| " | Entry: ", DoubleToString(entry, _Digits), | |
| " | ", status); | |
| } | |
| } | |
| } | |
| } | |
| else if(type == POSITION_TYPE_SELL) | |
| { | |
| double price = SymbolInfoDouble(sym, SYMBOL_ASK); | |
| double progress = (entry - price) / (entry - tp); | |
| if(progress <= 0) continue; | |
| double step = TrailStepPercent / 100.0; | |
| double stepsCompleted = MathFloor(progress / step); | |
| double effectiveProgress = stepsCompleted * step; | |
| double newSL; | |
| if(effectiveProgress <= 0.5) | |
| { | |
| newSL = initialSL - (initialSL - entry) * (effectiveProgress * 2.0); | |
| } | |
| else | |
| { | |
| double beyondBreakeven = effectiveProgress - 0.5; | |
| double profitDistance = (entry - tp) * 0.5; | |
| newSL = entry - (profitDistance * beyondBreakeven * 2.0); | |
| } | |
| int stopsLevel = (int)SymbolInfoInteger(sym, SYMBOL_TRADE_STOPS_LEVEL); | |
| double minDistance = MathMax(stopsLevel * point, point * 5); | |
| double minAllowedSL = price + minDistance; | |
| if(newSL < minAllowedSL) newSL = minAllowedSL; | |
| if(newSL < currentSL) | |
| { | |
| if(trade.PositionModify(ticket, newSL, tp)) | |
| { | |
| if(ShowDebugInfo) | |
| { | |
| string status = (newSL <= entry) ? "β BREAKEVEN+" : "π‘ Trailing to BE"; | |
| Print("SELL ", sym, " | Progress: ", DoubleToString(progress * 100, 1), "%", | |
| " | New SL: ", DoubleToString(newSL, _Digits), | |
| " | Entry: ", DoubleToString(entry, _Digits), | |
| " | ", status); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| int OnInit() | |
| { | |
| for(int i = 0; i < 200; i++) | |
| { | |
| mem[i].ticket = 0; | |
| mem[i].initialSL = 0; | |
| } | |
| Print("========================================"); | |
| Print("π Proportional Trailing EA (CORRECTED)"); | |
| Print("========================================"); | |
| Print("βοΈ Phase 1 (0-50%): SL moves to breakeven"); | |
| Print("βοΈ Phase 2 (50-100%): SL locks profit"); | |
| Print("βοΈ At 50% progress β SL = Breakeven (GUARANTEED)"); | |
| Print("βοΈ At 100% progress β SL locks 50% of profit"); | |
| Print("βοΈ Trail Step: ", TrailStepPercent, "%"); | |
| Print("========================================"); | |
| return(INIT_SUCCEEDED); | |
| } | |
| void OnDeinit(const int reason) | |
| { | |
| Print("β EA Stopped"); | |
| } | |
| //+------------------------------------------------------------------+ |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Logical Bug;