Dburnstrategy/2026 core deriv v75
tolaburn 0abc73f689 Dburn
Signed-off-by: tolaburn <tolaburn@noreply.mql5.com>
2026-02-28 07:15:42 +00:00

576 lines
21 KiB
Text

//+------------------------------------------------------------------+
//| COMPLETE REVERSAL BOT - 127.8% + 61.8% STRATEGY |
//| Multi-Timeframe: 15M Setup | 5M Precision | 1H Trend Filter |
//| Indicators: Stoch RSI + CCI Dual Divergence |
//+------------------------------------------------------------------+
#property strict
// === INPUT PARAMETERS ===
input double FirstEntryLots = 0.03; // 127.8% entry size
input double SecondEntryLots = 0.02; // 61.8% add-on size
input int SLPips = 10; // Base SL in pips
input double MaxSpread = 3.0; // Max spread filter
input int MomentumThreshold = 70; // Min momentum score
input double Fib1278 = 1.278; // First entry fib level
input double Fib618 = 0.618; // Second entry fib level
enum EntryStyle {
STYLE_AGGRESSIVE, // Enter on touch/wick
STYLE_CONSERVATIVE // Enter on close confirmation
};
input EntryStyle EntryMode = STYLE_CONSERVATIVE;
enum TradePhase {
PHASE_NONE,
PHASE_1278_LONG,
PHASE_618_ADDON
};
// === GLOBAL VARIABLES ===
TradePhase currentPhase = PHASE_NONE;
struct SetupData {
double swingHigh;
double swingLow;
double fib1278Level;
double entry1278Price;
double newSwingHigh;
double pullbackLow;
bool swingEstablished;
};
SetupData activeSetup;
datetime last5MBar = 0;
//+------------------------------------------------------------------+
//| EXPERT INITIALIZATION |
//+------------------------------------------------------------------+
int OnInit()
{
if(StringFind(Symbol(), "Volatility") == -1)
{
Alert("This EA is designed for Synthetic Indices!");
return(INIT_FAILED);
}
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| MAIN TICK FUNCTION |
//+------------------------------------------------------------------+
void OnTick()
{
// Spread filter
if(SymbolInfoInteger(Symbol(), SYMBOL_SPREAD) > MaxSpread * 10) return;
// Time filter
MqlDateTime dt;
TimeToStruct(TimeCurrent(), dt);
if(dt.min < 5 || dt.min > 55) return;
// Check for new 5M bar
datetime current5MBar = iTime(Symbol(), PERIOD_M5, 0);
if(current5MBar != last5MBar)
{
last5MBar = current5MBar;
// Entry logic
if(PositionsTotal() == 0 || !HasOpenPosition("1278"))
{
switch(currentPhase)
{
case PHASE_NONE:
Check1278LongEntry();
break;
case PHASE_1278_LONG:
CheckForPullbackSetup();
break;
case PHASE_618_ADDON:
Check618AddonEntry();
break;
}
}
}
// Manage positions
if(PositionsTotal() > 0)
ManagePositions();
}
//+------------------------------------------------------------------+
//| 127.8% LONG ENTRY |
//+------------------------------------------------------------------+
void Check1278LongEntry()
{
// 15M Setup
int highestBar15M = iHighest(Symbol(), PERIOD_M15, MODE_HIGH, 30, 1);
int lowestBar15M = iLowest(Symbol(), PERIOD_M15, MODE_LOW, 30, 1);
activeSetup.swingHigh = iHigh(Symbol(), PERIOD_M15, highestBar15M);
activeSetup.swingLow = iLow(Symbol(), PERIOD_M15, lowestBar15M);
double range15M = activeSetup.swingHigh - activeSetup.swingLow;
activeSetup.fib1278Level = activeSetup.swingHigh - (range15M * Fib1278);
double low15M_0 = iLow(Symbol(), PERIOD_M15, 0);
double tolerance15M = 5 * SymbolInfoDouble(Symbol(), SYMBOL_POINT) * 10;
if(!(low15M_0 <= activeSetup.fib1278Level + tolerance15M)) return;
// 1H Trend filter
if(GetTrendDirection(PERIOD_H1) == -1) return;
// Divergence check
if(!BullishDivergenceOnTimeframe(PERIOD_M15)) return;
// Momentum score
if(CalculateMomentumScore() < MomentumThreshold) return;
// 5M Precision entry
if(Check5MPrecisionEntry())
{
Print("127.8% entry executed!");
}
}
//+------------------------------------------------------------------+
//| 5M PRECISION ENTRY WITH STYLE SWITCH |
//+------------------------------------------------------------------+
bool Check5MPrecisionEntry()
{
double low5M_0 = iLow(Symbol(), PERIOD_M5, 0);
double low5M_1 = iLow(Symbol(), PERIOD_M5, 1);
double close5M_0 = iClose(Symbol(), PERIOD_M5, 0);
double close5M_1 = iClose(Symbol(), PERIOD_M5, 1);
double open5M_0 = iOpen(Symbol(), PERIOD_M5, 0);
double high5M_0 = iHigh(Symbol(), PERIOD_M5, 0);
double high5M_1 = iHigh(Symbol(), PERIOD_M5, 1);
double tolerance5M = 3 * SymbolInfoDouble(Symbol(), SYMBOL_POINT) * 10;
if(!(low5M_0 <= activeSetup.fib1278Level + tolerance5M ||
low5M_1 <= activeSetup.fib1278Level + tolerance5M)) return false;
// AGGRESSIVE MODE
if(EntryMode == STYLE_AGGRESSIVE)
{
bool quickBounce = (low5M_0 <= activeSetup.fib1278Level + tolerance5M && close5M_0 > open5M_0);
bool longWick = ((MathMin(close5M_0, open5M_0) - low5M_0) > MathAbs(close5M_0 - open5M_0) * 1.5);
double stochMain[];
ArraySetAsSeries(stochMain, true);
int stochHandle = iStochastic(Symbol(), PERIOD_M5, 14, 3, 3, MODE_SMA, STO_LOWHIGH);
CopyBuffer(stochHandle, 0, 0, 2, stochMain);
bool stochTurning = (stochMain[0] > stochMain[1] && stochMain[1] < 30);
int aggSignals = (quickBounce ? 1 : 0) + (longWick ? 1 : 0) + (stochTurning ? 1 : 0);
if(aggSignals >= 2)
return Execute5MEntry("1278_5M_Aggressive", 8);
}
// CONSERVATIVE MODE
else
{
bool bullishClose = (close5M_0 > open5M_0);
bool abovePrevious = (close5M_0 > high5M_1);
double microResistance = iHigh(Symbol(), PERIOD_M5, iHighest(Symbol(), PERIOD_M5, MODE_HIGH, 3, 1));
bool brokeResistance = (close5M_0 > microResistance);
double stochMain[], stochSignal[];
ArraySetAsSeries(stochMain, true);
ArraySetAsSeries(stochSignal, true);
int stochHandle = iStochastic(Symbol(), PERIOD_M5, 14, 3, 3, MODE_SMA, STO_LOWHIGH);
CopyBuffer(stochHandle, 0, 0, 2, stochMain);
CopyBuffer(stochHandle, 1, 0, 2, stochSignal);
bool stochCross = (stochMain[0] > stochSignal[0] && stochMain[1] <= stochSignal[1]);
double cci[];
ArraySetAsSeries(cci, true);
int cciHandle = iCCI(Symbol(), PERIOD_M5, 20, PRICE_TYPICAL);
CopyBuffer(cciHandle, 0, 0, 2, cci);
bool cciCross = (cci[0] > cci[1] && cci[1] < -100);
int confSignals = (bullishClose ? 1 : 0) + (abovePrevious ? 1 : 0) +
(brokeResistance ? 1 : 0) + (stochCross ? 1 : 0) + (cciCross ? 1 : 0);
if(confSignals >= 3)
return Execute5MEntry("1278_5M_Conservative", 6);
}
return false;
}
//+------------------------------------------------------------------+
//| EXECUTE 5M ENTRY |
//+------------------------------------------------------------------+
bool Execute5MEntry(string comment, int slPips)
{
double entryPrice = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
double sl = NormalizeDouble(entryPrice - slPips * SymbolInfoDouble(Symbol(), SYMBOL_POINT) * 10, _Digits);
double tp = NormalizeDouble(activeSetup.swingHigh, _Digits);
double lots = (EntryMode == STYLE_AGGRESSIVE) ? FirstEntryLots * 0.9 : FirstEntryLots;
if(ExecuteTrade(ORDER_TYPE_BUY, lots, sl, tp, comment))
{
currentPhase = PHASE_1278_LONG;
activeSetup.entry1278Price = entryPrice;
activeSetup.swingEstablished = false;
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| CHECK FOR PULLBACK SETUP (AFTER 127.8% MOVES UP) |
//+------------------------------------------------------------------+
void CheckForPullbackSetup()
{
if(!HasOpenPosition("1278")) { ResetToPhaseNone(); return; }
double recentHigh = iHigh(Symbol(), PERIOD_M5, iHighest(Symbol(), PERIOD_M5, MODE_HIGH, 15, 0));
double moveUp = recentHigh - activeSetup.entry1278Price;
double minMove = 20 * SymbolInfoDouble(Symbol(), SYMBOL_POINT) * 10;
if(moveUp >= minMove)
{
activeSetup.newSwingHigh = recentHigh;
activeSetup.swingEstablished = true;
currentPhase = PHASE_618_ADDON;
Print("Swing established at ", recentHigh, " - waiting for 61.8% pullback");
}
}
//+------------------------------------------------------------------+
//| 61.8% ADD-ON ENTRY |
//+------------------------------------------------------------------+
void Check618AddonEntry()
{
if(!activeSetup.swingEstablished) return;
double upMove = activeSetup.newSwingHigh - activeSetup.entry1278Price;
double fib618Level = activeSetup.newSwingHigh - (upMove * Fib618);
double fib786Level = activeSetup.newSwingHigh - (upMove * 0.786);
double close15M = iClose(Symbol(), PERIOD_M15, 0);
double low15M = iLow(Symbol(), PERIOD_M15, 0);
double tolerance = 5 * SymbolInfoDouble(Symbol(), SYMBOL_POINT) * 10;
if(!(low15M <= fib618Level + tolerance && low15M >= fib786Level - tolerance)) return;
if(!Check5M_618Entry(fib618Level, fib786Level)) return;
double entryPrice = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
double sl = NormalizeDouble(activeSetup.entry1278Price - 5 * SymbolInfoDouble(Symbol(), SYMBOL_POINT) * 10, _Digits);
double tp = NormalizeDouble(activeSetup.newSwingHigh + (upMove * 0.5), _Digits);
if(ExecuteTrade(ORDER_TYPE_BUY, SecondEntryLots, sl, tp, "618_Addon"))
{
activeSetup.pullbackLow = low15M;
Print("61.8% add-on executed at ", entryPrice);
}
}
//+------------------------------------------------------------------+
//| 5M 61.8% ENTRY WITH STYLE |
//+------------------------------------------------------------------+
bool Check5M_618Entry(double fib618, double fib786)
{
double close5M_0 = iClose(Symbol(), PERIOD_M5, 0);
double close5M_1 = iClose(Symbol(), PERIOD_M5, 1);
double low5M_0 = iLow(Symbol(), PERIOD_M5, 0);
double low5M_1 = iLow(Symbol(), PERIOD_M5, 1);
double open5M_0 = iOpen(Symbol(), PERIOD_M5, 0);
double high5M_1 = iHigh(Symbol(), PERIOD_M5, 1);
double tolerance = 3 * SymbolInfoDouble(Symbol(), SYMBOL_POINT) * 10;
bool inZone = (low5M_0 <= fib618 + tolerance && low5M_0 >= fib786 - tolerance);
if(!inZone) return false;
if(EntryMode == STYLE_AGGRESSIVE)
{
bool doubleBottom = (MathAbs(low5M_0 - low5M_1) < tolerance * 2);
bool quickBounce = (low5M_0 <= fib618 && close5M_0 > open5M_0);
bool hammer = ((MathMin(close5M_0, open5M_0) - low5M_0) > MathAbs(close5M_0 - open5M_0) * 2);
int aggCount = (doubleBottom ? 1 : 0) + (quickBounce ? 1 : 0) + (hammer ? 1 : 0);
return (aggCount >= 2);
}
else
{
double low5M_2 = iLow(Symbol(), PERIOD_M5, 2);
bool higherLow = (low5M_0 > low5M_1 && low5M_1 > low5M_2);
bool closeStrong = (close5M_0 > high5M_1);
double microRes = iHigh(Symbol(), PERIOD_M5, iHighest(Symbol(), PERIOD_M5, MODE_HIGH, 5, 1));
bool brokeRes = (close5M_0 > microRes);
bool momentumOK = BullishDivergenceOnTimeframe(PERIOD_M5);
int confCount = (higherLow ? 1 : 0) + (closeStrong ? 1 : 0) + (brokeRes ? 1 : 0) + (momentumOK ? 1 : 0);
return (confCount >= 3);
}
}
//+------------------------------------------------------------------+
//| DIVERGENCE CHECKER (Stoch RSI + CCI) |
//+------------------------------------------------------------------+
bool BullishDivergenceOnTimeframe(ENUM_TIMEFRAMES tf)
{
double low1 = iLow(Symbol(), tf, 5);
double low2 = iLow(Symbol(), tf, 1);
if(low2 >= low1) return false;
double stochMain[];
ArraySetAsSeries(stochMain, true);
int stochHandle = iStochastic(Symbol(), tf, 14, 3, 3, MODE_SMA, STO_LOWHIGH);
if(CopyBuffer(stochHandle, 0, 0, 10, stochMain) < 10) return false;
double cci[];
ArraySetAsSeries(cci, true);
int cciHandle = iCCI(Symbol(), tf, 20, PRICE_TYPICAL);
if(CopyBuffer(cciHandle, 0, 0, 10, cci) < 10) return false;
return (stochMain[1] > stochMain[5] && cci[1] > cci[5]);
}
//+------------------------------------------------------------------+
//| MOMENTUM SCORE |
//+------------------------------------------------------------------+
int CalculateMomentumScore()
{
int score = 0;
double rsi = iRSI(Symbol(), PERIOD_M15, 14, PRICE_CLOSE, 0);
if(rsi < 30) score += (int)MathMin((30 - rsi) * 1.2, 25);
double open = iOpen(Symbol(), PERIOD_M15, 0);
double high = iHigh(Symbol(), PERIOD_M15, 0);
double low = iLow(Symbol(), PERIOD_M15, 0);
double close = iClose(Symbol(), PERIOD_M15, 0);
double body = MathAbs(close - open);
double lowerWick = MathMin(close, open) - low;
if(body > 0 && lowerWick / body > 2.0) score += 25;
double stochMain[];
ArraySetAsSeries(stochMain, true);
int stochHandle = iStochastic(Symbol(), PERIOD_M15, 14, 3, 3, MODE_SMA, STO_LOWHIGH);
CopyBuffer(stochHandle, 0, 0, 1, stochMain);
if(stochMain[0] < 15) score += 20;
double cci[];
ArraySetAsSeries(cci, true);
int cciHandle = iCCI(Symbol(), PERIOD_M15, 20, PRICE_TYPICAL);
CopyBuffer(cciHandle, 0, 0, 1, cci);
if(cci[0] < -150) score += 20;
else if(cci[0] < -100) score += 10;
double vwap = iMA(Symbol(), PERIOD_M15, 20, 0, MODE_SMA, PRICE_TYPICAL, 0);
double distance = MathAbs(close - vwap) / vwap * 100;
score += (int)MathMin(distance * 2, 10);
return score;
}
//+------------------------------------------------------------------+
//| TREND DIRECTION |
//+------------------------------------------------------------------+
int GetTrendDirection(ENUM_TIMEFRAMES tf)
{
double ma50 = iMA(Symbol(), tf, 50, 0, MODE_SMA, PRICE_CLOSE, 0);
double ma200 = iMA(Symbol(), tf, 200, 0, MODE_SMA, PRICE_CLOSE, 0);
double close = iClose(Symbol(), tf, 0);
if(close > ma50 && ma50 > ma200) return 1;
if(close < ma50 && ma50 < ma200) return -1;
return 0;
}
//+------------------------------------------------------------------+
//| POSITION MANAGEMENT |
//+------------------------------------------------------------------+
void ManagePositions()
{
bool has1278 = false, has618 = false;
double avgEntry = 0, totalLots = 0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket <= 0) continue;
if(PositionGetString(POSITION_SYMBOL) != Symbol()) continue;
string comment = PositionGetString(POSITION_COMMENT);
int posType = (int)PositionGetInteger(POSITION_TYPE);
double lots = PositionGetDouble(POSITION_VOLUME);
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
if(StringFind(comment, "1278") != -1) has1278 = true;
if(StringFind(comment, "618") != -1) has618 = true;
avgEntry += openPrice * lots;
totalLots += lots;
ManageSinglePosition(ticket, posType, openPrice);
}
if(totalLots > 0) avgEntry /= totalLots;
if(has1278 && has618)
ManageAveragedPosition(avgEntry, totalLots);
if(!has1278 && !has618 && currentPhase != PHASE_NONE)
ResetToPhaseNone();
}
//+------------------------------------------------------------------+
//| SINGLE POSITION MANAGEMENT |
//+------------------------------------------------------------------+
void ManageSinglePosition(ulong ticket, int posType, double openPrice)
{
double currentSL = PositionGetDouble(POSITION_SL);
double currentTP = PositionGetDouble(POSITION_TP);
double currentPrice = (posType == POSITION_TYPE_BUY) ?
SymbolInfoDouble(Symbol(), SYMBOL_BID) :
SymbolInfoDouble(Symbol(), SYMBOL_ASK);
double profitPips = MathAbs(currentPrice - openPrice) /
(SymbolInfoDouble(Symbol(), SYMBOL_POINT) * 10);
// Break even at 15 pips
if(profitPips >= 15 && currentSL == 0)
{
double newSL = openPrice + 2 * SymbolInfoDouble(Symbol(), SYMBOL_POINT) * 10;
ModifyPosition(ticket, NormalizeDouble(newSL, _Digits), currentTP);
}
}
//+------------------------------------------------------------------+
//| AVERAGED POSITION MANAGEMENT |
//+------------------------------------------------------------------+
void ManageAveragedPosition(double avgPrice, double totalLots)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket <= 0) continue;
if(PositionGetString(POSITION_SYMBOL) != Symbol()) continue;
int posType = (int)PositionGetInteger(POSITION_TYPE);
double currentSL = PositionGetDouble(POSITION_SL);
double currentTP = PositionGetDouble(POSITION_TP);
double currentPrice = SymbolInfoDouble(Symbol(), SYMBOL_BID);
double profitPips = MathAbs(currentPrice - avgPrice) /
(SymbolInfoDouble(Symbol(), SYMBOL_POINT) * 10);
// Breakeven both at +10 pips averaged
if(profitPips >= 10 && currentSL < avgPrice)
{
double newSL = avgPrice + 2 * SymbolInfoDouble(Symbol(), SYMBOL_POINT) * 10;
ModifyPosition(ticket, NormalizeDouble(newSL, _Digits), currentTP);
}
// Trail at structure when +40 pips
if(profitPips >= 40)
{
double newSL = GetStructureLevel(PERIOD_M15);
double buffer = 3 * SymbolInfoDouble(Symbol(), SYMBOL_POINT) * 10;
if(newSL > currentSL)
ModifyPosition(ticket, NormalizeDouble(newSL - buffer, _Digits), currentTP);
}
}
}
//+------------------------------------------------------------------+
//| GET STRUCTURE LEVEL |
//+------------------------------------------------------------------+
double GetStructureLevel(ENUM_TIMEFRAMES tf)
{
int lowest = iLowest(Symbol(), tf, MODE_LOW, 10, 1);
return iLow(Symbol(), tf, lowest);
}
//+------------------------------------------------------------------+
//| EXECUTE TRADE |
//+------------------------------------------------------------------+
bool ExecuteTrade(int direction, double lots, double sl, double tp, string comment)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
double price = (direction == ORDER_TYPE_SELL) ?
SymbolInfoDouble(Symbol(), SYMBOL_BID) :
SymbolInfoDouble(Symbol(), SYMBOL_ASK);
request.action = TRADE_ACTION_DEAL;
request.symbol = Symbol();
request.volume = lots;
request.type = direction;
request.price = price;
request.sl = sl;
request.tp = tp;
request.deviation = 10;
request.magic = 123456;
request.comment = comment;
if(!OrderSend(request, result))
{
Print("OrderSend failed: ", GetLastError());
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| MODIFY POSITION |
//+------------------------------------------------------------------+
bool ModifyPosition(ulong ticket, double sl, double tp)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_SLTP;
request.position = ticket;
request.symbol = Symbol();
request.sl = sl;
request.tp = tp;
return OrderSend(request, result);
}
//+------------------------------------------------------------------+
//| CHECK IF HAS OPEN POSITION |
//+------------------------------------------------------------------+
bool HasOpenPosition(string keyword)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket <= 0) continue;
if(PositionGetString(POSITION_SYMBOL) != Symbol()) continue;
string comment = PositionGetString(POSITION_COMMENT);
if(StringFind(comment, keyword) != -1) return true;
}
return false;
}
//+------------------------------------------------------------------+
//| RESET SETUP |
//+------------------------------------------------------------------+
void ResetToPhaseNone()
{
currentPhase = PHASE_NONE;
activeSetup.swingHigh = 0;
activeSetup.swingLow = 0;
activeSetup.fib1278Level = 0;
activeSetup.entry1278Price = 0;
activeSetup.newSwingHigh = 0;
activeSetup.swingEstablished = false;
Print("Setup reset - hunting for new 127.8% opportunity");
}
//+------------------------------------------------------------------+