forked from 1073821942/AiDataTaskRuner
988 lines
20 KiB
Text
988 lines
20 KiB
Text
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Institutional Hybrid EA v1.0 |
|
||
|
|
//| PART 1 - FOUNDATION |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
#property strict
|
||
|
|
|
||
|
|
#include <Trade/Trade.mqh>
|
||
|
|
|
||
|
|
CTrade trade;
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| INPUT PARAMETERS |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
input long MagicNumber = 20260601;
|
||
|
|
|
||
|
|
// Risk Management
|
||
|
|
input double RiskPercent = 1.0;
|
||
|
|
input double MaxDailyDrawdown = 5.0;
|
||
|
|
input int MaxConsecutiveLosses = 3;
|
||
|
|
|
||
|
|
// Fixed Lot Mode
|
||
|
|
input bool UseFixedLot = true;
|
||
|
|
input double FixedLotSize = 0.01;
|
||
|
|
|
||
|
|
// Trade Management
|
||
|
|
input int MaxOpenTrades = 5;
|
||
|
|
input int TradeCooldownMinutes = 2;
|
||
|
|
|
||
|
|
// Break Even Settings
|
||
|
|
input double BreakEvenTriggerR = 1.0;
|
||
|
|
input double BreakEvenBufferPoints = 50;
|
||
|
|
|
||
|
|
// Spread Filter
|
||
|
|
int MaxSpread = 300;
|
||
|
|
|
||
|
|
// ATR Settings
|
||
|
|
input int ATR_Period = 14;
|
||
|
|
double ATR_SL_Multiplier = 1.2;
|
||
|
|
double ATR_TP_Multiplier = 2.5;
|
||
|
|
input double ATR_Trail_Multiplier = 1.0;
|
||
|
|
|
||
|
|
// EMA Settings
|
||
|
|
input int FastEMA = 5;
|
||
|
|
input int SlowEMA = 20;
|
||
|
|
|
||
|
|
// RSI Settings
|
||
|
|
input int RSI_Period = 14;
|
||
|
|
input double RSI_Buy_Level = 50;
|
||
|
|
input double RSI_Sell_Level = 50;
|
||
|
|
|
||
|
|
// ADX Settings
|
||
|
|
input int ADX_Period = 14;
|
||
|
|
input double MinADX = 15.0;
|
||
|
|
|
||
|
|
// Session Filter
|
||
|
|
input bool TradeLondonSession = true;
|
||
|
|
input bool TradeNewYorkSession = true;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| GLOBAL VARIABLES |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
datetime LastTradeTime = 0;
|
||
|
|
|
||
|
|
datetime LastResetDay = 0;
|
||
|
|
|
||
|
|
datetime LastM15Bar = 0;
|
||
|
|
|
||
|
|
double DayStartBalance = 0.0;
|
||
|
|
|
||
|
|
int ConsecutiveLosses = 0;
|
||
|
|
|
||
|
|
bool TradingEnabled = true;
|
||
|
|
|
||
|
|
// Prevent duplicate entries on the same signal
|
||
|
|
bool BuySignalTriggered = false;
|
||
|
|
bool SellSignalTriggered = false;
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| INITIALIZATION |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
int OnInit()
|
||
|
|
{
|
||
|
|
// XAUUSD Optimization
|
||
|
|
if(XAUUSD_Mode)
|
||
|
|
{
|
||
|
|
ATR_SL_Multiplier = 1.5;
|
||
|
|
ATR_TP_Multiplier = 3.0;
|
||
|
|
MaxSpread = 500;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Trade Setup
|
||
|
|
trade.SetExpertMagicNumber(MagicNumber);
|
||
|
|
|
||
|
|
trade.SetDeviationInPoints(50);
|
||
|
|
|
||
|
|
// Account Information
|
||
|
|
DayStartBalance =
|
||
|
|
AccountInfoDouble(
|
||
|
|
ACCOUNT_BALANCE
|
||
|
|
);
|
||
|
|
|
||
|
|
Print(
|
||
|
|
"Min Lot = ",
|
||
|
|
SymbolInfoDouble(
|
||
|
|
_Symbol,
|
||
|
|
SYMBOL_VOLUME_MIN
|
||
|
|
)
|
||
|
|
);
|
||
|
|
|
||
|
|
Print(
|
||
|
|
"Leverage = ",
|
||
|
|
AccountInfoInteger(
|
||
|
|
ACCOUNT_LEVERAGE
|
||
|
|
)
|
||
|
|
);
|
||
|
|
|
||
|
|
LastResetDay =
|
||
|
|
TimeCurrent();
|
||
|
|
|
||
|
|
TradingEnabled = true;
|
||
|
|
|
||
|
|
Print(
|
||
|
|
"Institutional Hybrid EA v1.0 Started"
|
||
|
|
);
|
||
|
|
|
||
|
|
return(INIT_SUCCEEDED);
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| DEINITIALIZATION |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
void OnDeinit(const int reason)
|
||
|
|
{
|
||
|
|
Print("EA Shutdown");
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| SPREAD FILTER |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool CheckSpread()
|
||
|
|
{
|
||
|
|
long spread =
|
||
|
|
SymbolInfoInteger(
|
||
|
|
_Symbol,
|
||
|
|
SYMBOL_SPREAD
|
||
|
|
);
|
||
|
|
|
||
|
|
if(spread > MaxSpread)
|
||
|
|
return false;
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| SESSION FILTER |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool IsTradingSession()
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
|
||
|
|
MqlDateTime tm;
|
||
|
|
|
||
|
|
TimeToStruct(TimeCurrent(), tm);
|
||
|
|
|
||
|
|
int hour = tm.hour;
|
||
|
|
|
||
|
|
bool london =
|
||
|
|
(hour >= 8 && hour <= 17);
|
||
|
|
|
||
|
|
bool newyork =
|
||
|
|
(hour >= 13 && hour <= 22);
|
||
|
|
|
||
|
|
if(TradeLondonSession && london)
|
||
|
|
return true;
|
||
|
|
|
||
|
|
if(TradeNewYorkSession && newyork)
|
||
|
|
return true;
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| DAILY DRAWDOWN PROTECTION |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool CheckDailyDrawdown()
|
||
|
|
{
|
||
|
|
double equity =
|
||
|
|
AccountInfoDouble(
|
||
|
|
ACCOUNT_EQUITY
|
||
|
|
);
|
||
|
|
|
||
|
|
double drawdown =
|
||
|
|
((DayStartBalance - equity)
|
||
|
|
/
|
||
|
|
DayStartBalance) * 100.0;
|
||
|
|
|
||
|
|
if(drawdown >= MaxDailyDrawdown)
|
||
|
|
{
|
||
|
|
TradingEnabled = false;
|
||
|
|
|
||
|
|
Print(
|
||
|
|
"Maximum Daily Drawdown Hit"
|
||
|
|
);
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| COOLDOWN CHECK |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool CooldownPassed()
|
||
|
|
{
|
||
|
|
if(LastTradeTime == 0)
|
||
|
|
return true;
|
||
|
|
|
||
|
|
int secondsPassed =
|
||
|
|
(int)(TimeCurrent()
|
||
|
|
- LastTradeTime);
|
||
|
|
|
||
|
|
return
|
||
|
|
secondsPassed >=
|
||
|
|
TradeCooldownMinutes * 60;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| NEW M15 BAR DETECTION |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool NewM15Bar()
|
||
|
|
{
|
||
|
|
datetime currentBar =
|
||
|
|
iTime(
|
||
|
|
_Symbol,
|
||
|
|
PERIOD_M15,
|
||
|
|
0
|
||
|
|
);
|
||
|
|
|
||
|
|
if(currentBar != LastM15Bar)
|
||
|
|
{
|
||
|
|
LastM15Bar = currentBar;
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| ATR VALUE |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
double GetATR(
|
||
|
|
ENUM_TIMEFRAMES tf
|
||
|
|
)
|
||
|
|
{
|
||
|
|
// Create ATR Handle
|
||
|
|
int handle =
|
||
|
|
iATR(
|
||
|
|
_Symbol,
|
||
|
|
tf,
|
||
|
|
ATR_Period
|
||
|
|
);
|
||
|
|
|
||
|
|
// Validate Handle
|
||
|
|
if(handle == INVALID_HANDLE)
|
||
|
|
{
|
||
|
|
Print("ATR Handle Creation Failed");
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ATR Buffer
|
||
|
|
double buffer[];
|
||
|
|
|
||
|
|
// Copy ATR Data
|
||
|
|
if(CopyBuffer(
|
||
|
|
handle,
|
||
|
|
0,
|
||
|
|
0,
|
||
|
|
1,
|
||
|
|
buffer) < 1)
|
||
|
|
{
|
||
|
|
Print("ATR Buffer Failed");
|
||
|
|
|
||
|
|
IndicatorRelease(handle);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Release Indicator Handle
|
||
|
|
IndicatorRelease(handle);
|
||
|
|
|
||
|
|
// Return ATR Value
|
||
|
|
return buffer[0];
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| EMA VALUE |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
double GetEMA(
|
||
|
|
ENUM_TIMEFRAMES tf,
|
||
|
|
int period
|
||
|
|
)
|
||
|
|
{
|
||
|
|
int handle =
|
||
|
|
iMA(
|
||
|
|
_Symbol,
|
||
|
|
tf,
|
||
|
|
period,
|
||
|
|
0,
|
||
|
|
MODE_EMA,
|
||
|
|
PRICE_CLOSE
|
||
|
|
);
|
||
|
|
|
||
|
|
if(handle == INVALID_HANDLE)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
double buffer[];
|
||
|
|
|
||
|
|
if(CopyBuffer(
|
||
|
|
handle,
|
||
|
|
0,
|
||
|
|
0,
|
||
|
|
1,
|
||
|
|
buffer) < 1)
|
||
|
|
{
|
||
|
|
IndicatorRelease(handle);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
IndicatorRelease(handle);
|
||
|
|
|
||
|
|
return buffer[0];
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| RSI VALUE |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
double GetRSI(
|
||
|
|
ENUM_TIMEFRAMES tf
|
||
|
|
)
|
||
|
|
{
|
||
|
|
int handle =
|
||
|
|
iRSI(
|
||
|
|
_Symbol,
|
||
|
|
tf,
|
||
|
|
RSI_Period,
|
||
|
|
PRICE_CLOSE
|
||
|
|
);
|
||
|
|
|
||
|
|
if(handle == INVALID_HANDLE)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
double buffer[];
|
||
|
|
|
||
|
|
if(CopyBuffer(
|
||
|
|
handle,
|
||
|
|
0,
|
||
|
|
0,
|
||
|
|
1,
|
||
|
|
buffer) < 1)
|
||
|
|
{
|
||
|
|
IndicatorRelease(handle);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
IndicatorRelease(handle);
|
||
|
|
|
||
|
|
return buffer[0];
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| ADX VALUE |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
double GetADX(
|
||
|
|
ENUM_TIMEFRAMES tf
|
||
|
|
)
|
||
|
|
{
|
||
|
|
int handle =
|
||
|
|
iADX(
|
||
|
|
_Symbol,
|
||
|
|
tf,
|
||
|
|
ADX_Period
|
||
|
|
);
|
||
|
|
|
||
|
|
if(handle == INVALID_HANDLE)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
double buffer[];
|
||
|
|
|
||
|
|
if(CopyBuffer(
|
||
|
|
handle,
|
||
|
|
0,
|
||
|
|
0,
|
||
|
|
1,
|
||
|
|
buffer) < 1)
|
||
|
|
{
|
||
|
|
IndicatorRelease(handle);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
IndicatorRelease(handle);
|
||
|
|
|
||
|
|
return buffer[0];
|
||
|
|
}
|
||
|
|
|
||
|
|
// Liquidity Detection
|
||
|
|
|
||
|
|
input int LiquidityLookback = 20;
|
||
|
|
input double LiquidityTolerancePoints = 100;
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| TREND STRENGTH |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool StrongTrend()
|
||
|
|
{
|
||
|
|
return GetADX(PERIOD_H1) > MinADX;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| DYNAMIC LOT CALCULATION |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
double CalculateLotSize(double stopLossDistance)
|
||
|
|
{
|
||
|
|
double balance =
|
||
|
|
AccountInfoDouble(
|
||
|
|
ACCOUNT_BALANCE
|
||
|
|
);
|
||
|
|
|
||
|
|
double riskAmount =
|
||
|
|
balance * (RiskPercent / 100.0);
|
||
|
|
|
||
|
|
double tickValue =
|
||
|
|
SymbolInfoDouble(
|
||
|
|
_Symbol,
|
||
|
|
SYMBOL_TRADE_TICK_VALUE
|
||
|
|
);
|
||
|
|
|
||
|
|
if(tickValue <= 0 || stopLossDistance <= 0)
|
||
|
|
return 0.01;
|
||
|
|
|
||
|
|
double lot = 0.01;
|
||
|
|
|
||
|
|
|
||
|
|
// Safety limits
|
||
|
|
double minLot =
|
||
|
|
SymbolInfoDouble(
|
||
|
|
_Symbol,
|
||
|
|
SYMBOL_VOLUME_MIN
|
||
|
|
);
|
||
|
|
|
||
|
|
double maxLot =
|
||
|
|
SymbolInfoDouble(
|
||
|
|
_Symbol,
|
||
|
|
SYMBOL_VOLUME_MAX
|
||
|
|
);
|
||
|
|
|
||
|
|
double lotStep =
|
||
|
|
SymbolInfoDouble(
|
||
|
|
_Symbol,
|
||
|
|
SYMBOL_VOLUME_STEP
|
||
|
|
);
|
||
|
|
|
||
|
|
// HARD CAP
|
||
|
|
if(lot > 1.0)
|
||
|
|
lot = 1.0;
|
||
|
|
|
||
|
|
lot =
|
||
|
|
MathMax(minLot,
|
||
|
|
MathMin(maxLot, lot));
|
||
|
|
|
||
|
|
lot =
|
||
|
|
NormalizeDouble(
|
||
|
|
MathFloor(lot / lotStep)
|
||
|
|
* lotStep,
|
||
|
|
2
|
||
|
|
);
|
||
|
|
|
||
|
|
return lot;
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| POSITION COUNT |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
int CountOpenPositions()
|
||
|
|
{
|
||
|
|
int count = 0;
|
||
|
|
|
||
|
|
for(int i=0;
|
||
|
|
i<PositionsTotal();
|
||
|
|
i++)
|
||
|
|
{
|
||
|
|
ulong ticket =
|
||
|
|
PositionGetTicket(i);
|
||
|
|
|
||
|
|
if(ticket <= 0)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
if(PositionSelectByTicket(ticket))
|
||
|
|
{
|
||
|
|
if(PositionGetInteger(
|
||
|
|
POSITION_MAGIC)
|
||
|
|
== MagicNumber)
|
||
|
|
{
|
||
|
|
count++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| H4 MARKET BIAS |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool H4BullishBias()
|
||
|
|
{
|
||
|
|
double ema50 =
|
||
|
|
GetEMA(PERIOD_H4,50);
|
||
|
|
|
||
|
|
double ema200 =
|
||
|
|
GetEMA(PERIOD_H4,200);
|
||
|
|
|
||
|
|
return ema50 > ema200;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool H4BearishBias()
|
||
|
|
{
|
||
|
|
double ema50 =
|
||
|
|
GetEMA(PERIOD_H4,50);
|
||
|
|
|
||
|
|
double ema200 =
|
||
|
|
GetEMA(PERIOD_H4,200);
|
||
|
|
|
||
|
|
return ema50 < ema200;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| H1 CONFIRMATION |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool H1BullishConfirmation()
|
||
|
|
{
|
||
|
|
double ema50 =
|
||
|
|
GetEMA(PERIOD_H1,50);
|
||
|
|
|
||
|
|
double ema200 =
|
||
|
|
GetEMA(PERIOD_H1,200);
|
||
|
|
|
||
|
|
return ema50 > ema200;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool H1BearishConfirmation()
|
||
|
|
{
|
||
|
|
double ema50 =
|
||
|
|
GetEMA(PERIOD_H1,50);
|
||
|
|
|
||
|
|
double ema200 =
|
||
|
|
GetEMA(PERIOD_H1,200);
|
||
|
|
|
||
|
|
return ema50 < ema200;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| PRICE LOCATION FILTER |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool PriceAboveH1EMA()
|
||
|
|
{
|
||
|
|
double ema =
|
||
|
|
GetEMA(PERIOD_H1,50);
|
||
|
|
|
||
|
|
double bid =
|
||
|
|
SymbolInfoDouble(
|
||
|
|
_Symbol,
|
||
|
|
SYMBOL_BID
|
||
|
|
);
|
||
|
|
|
||
|
|
return bid > ema;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool PriceBelowH1EMA()
|
||
|
|
{
|
||
|
|
double ema =
|
||
|
|
GetEMA(PERIOD_H1,50);
|
||
|
|
|
||
|
|
double bid =
|
||
|
|
SymbolInfoDouble(
|
||
|
|
_Symbol,
|
||
|
|
SYMBOL_BID
|
||
|
|
);
|
||
|
|
|
||
|
|
return bid < ema;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| M15 MOMENTUM FILTERS |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool M15BullishMomentum()
|
||
|
|
{
|
||
|
|
double fastEMA =
|
||
|
|
GetEMA(
|
||
|
|
PERIOD_M15,
|
||
|
|
FastEMA
|
||
|
|
);
|
||
|
|
|
||
|
|
double slowEMA =
|
||
|
|
GetEMA(
|
||
|
|
PERIOD_M15,
|
||
|
|
SlowEMA
|
||
|
|
);
|
||
|
|
|
||
|
|
double rsi =
|
||
|
|
GetRSI(
|
||
|
|
PERIOD_M15
|
||
|
|
);
|
||
|
|
|
||
|
|
double adx =
|
||
|
|
GetADX(
|
||
|
|
PERIOD_M15
|
||
|
|
);
|
||
|
|
|
||
|
|
return
|
||
|
|
fastEMA > slowEMA &&
|
||
|
|
rsi > RSI_Buy_Level &&
|
||
|
|
adx > MinADX;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool M15BearishMomentum()
|
||
|
|
{
|
||
|
|
double fastEMA =
|
||
|
|
GetEMA(
|
||
|
|
PERIOD_M15,
|
||
|
|
FastEMA
|
||
|
|
);
|
||
|
|
|
||
|
|
double slowEMA =
|
||
|
|
GetEMA(
|
||
|
|
PERIOD_M15,
|
||
|
|
SlowEMA
|
||
|
|
);
|
||
|
|
|
||
|
|
double rsi =
|
||
|
|
GetRSI(
|
||
|
|
PERIOD_M15
|
||
|
|
);
|
||
|
|
|
||
|
|
double adx =
|
||
|
|
GetADX(
|
||
|
|
PERIOD_M15
|
||
|
|
);
|
||
|
|
|
||
|
|
return
|
||
|
|
fastEMA < slowEMA &&
|
||
|
|
rsi < RSI_Sell_Level &&
|
||
|
|
adx > MinADX;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| PULLBACK BUY |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool PullbackBuy()
|
||
|
|
{
|
||
|
|
double ema20 =
|
||
|
|
GetEMA(PERIOD_M15,20);
|
||
|
|
|
||
|
|
double close =
|
||
|
|
iClose(_Symbol,PERIOD_M15,1);
|
||
|
|
|
||
|
|
double atr =
|
||
|
|
GetATR(PERIOD_M15);
|
||
|
|
|
||
|
|
return
|
||
|
|
MathAbs(close - ema20)
|
||
|
|
<= atr * 0.5;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| PULLBACK SELL |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool PullbackSell()
|
||
|
|
{
|
||
|
|
double ema20 =
|
||
|
|
GetEMA(PERIOD_M15,20);
|
||
|
|
|
||
|
|
double close =
|
||
|
|
iClose(_Symbol,PERIOD_M15,1);
|
||
|
|
|
||
|
|
double atr =
|
||
|
|
GetATR(PERIOD_M15);
|
||
|
|
|
||
|
|
return
|
||
|
|
MathAbs(close - ema20)
|
||
|
|
<= atr * 0.5;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| BUY SIGNAL |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool BuySignal()
|
||
|
|
{
|
||
|
|
return
|
||
|
|
H4BullishBias() &&
|
||
|
|
H1BullishConfirmation() &&
|
||
|
|
PullbackBuy() &&
|
||
|
|
M15BullishMomentum();
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| SELL SIGNAL |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool SellSignal()
|
||
|
|
{
|
||
|
|
return
|
||
|
|
H4BearishBias() &&
|
||
|
|
H1BearishConfirmation() &&
|
||
|
|
PullbackSell() &&
|
||
|
|
M15BearishMomentum();
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| SIGNAL ENUM |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
enum TradeSignal
|
||
|
|
{
|
||
|
|
SIGNAL_NONE,
|
||
|
|
SIGNAL_BUY,
|
||
|
|
SIGNAL_SELL
|
||
|
|
};
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| GET SIGNAL |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
TradeSignal GetSignal()
|
||
|
|
{
|
||
|
|
if(BuySignal())
|
||
|
|
return SIGNAL_BUY;
|
||
|
|
|
||
|
|
if(SellSignal())
|
||
|
|
return SIGNAL_SELL;
|
||
|
|
|
||
|
|
return SIGNAL_NONE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| EQUAL HIGHS DETECTION |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool EqualHighs()
|
||
|
|
{
|
||
|
|
double point =
|
||
|
|
SymbolInfoDouble(
|
||
|
|
_Symbol,
|
||
|
|
SYMBOL_POINT
|
||
|
|
);
|
||
|
|
|
||
|
|
double tolerance =
|
||
|
|
LiquidityTolerancePoints * point;
|
||
|
|
|
||
|
|
for(int i=2; i<=LiquidityLookback; i++)
|
||
|
|
{
|
||
|
|
double high1 =
|
||
|
|
iHigh(
|
||
|
|
_Symbol,
|
||
|
|
PERIOD_M15,
|
||
|
|
i
|
||
|
|
);
|
||
|
|
|
||
|
|
double high2 =
|
||
|
|
iHigh(
|
||
|
|
_Symbol,
|
||
|
|
PERIOD_M15,
|
||
|
|
i+1
|
||
|
|
);
|
||
|
|
|
||
|
|
if(MathAbs(high1-high2) <= tolerance)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| EQUAL LOWS DETECTION |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool EqualLows()
|
||
|
|
{
|
||
|
|
double point =
|
||
|
|
SymbolInfoDouble(
|
||
|
|
_Symbol,
|
||
|
|
SYMBOL_POINT
|
||
|
|
);
|
||
|
|
|
||
|
|
double tolerance =
|
||
|
|
LiquidityTolerancePoints * point;
|
||
|
|
|
||
|
|
for(int i=2; i<=LiquidityLookback; i++)
|
||
|
|
{
|
||
|
|
double low1 =
|
||
|
|
iLow(
|
||
|
|
_Symbol,
|
||
|
|
PERIOD_M15,
|
||
|
|
i
|
||
|
|
);
|
||
|
|
|
||
|
|
double low2 =
|
||
|
|
iLow(
|
||
|
|
_Symbol,
|
||
|
|
PERIOD_M15,
|
||
|
|
i+1
|
||
|
|
);
|
||
|
|
|
||
|
|
if(MathAbs(low1-low2) <= tolerance)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| BULLISH LIQUIDITY SWEEP |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool LiquiditySweepBuy()
|
||
|
|
{
|
||
|
|
double prevLow =
|
||
|
|
iLow(_Symbol, PERIOD_M15, 2);
|
||
|
|
|
||
|
|
double currentLow =
|
||
|
|
iLow(_Symbol, PERIOD_M15, 1);
|
||
|
|
|
||
|
|
double currentClose =
|
||
|
|
iClose(_Symbol, PERIOD_M15, 1);
|
||
|
|
|
||
|
|
return currentLow < prevLow &&
|
||
|
|
currentClose > prevLow;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| BEARISH LIQUIDITY SWEEP |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
bool LiquiditySweepSell()
|
||
|
|
{
|
||
|
|
double prevHigh =
|
||
|
|
iHigh(_Symbol, PERIOD_M15, 2);
|
||
|
|
|
||
|
|
double currentHigh =
|
||
|
|
iHigh(_Symbol, PERIOD_M15, 1);
|
||
|
|
|
||
|
|
double currentClose =
|
||
|
|
iClose(_Symbol, PERIOD_M15, 1);
|
||
|
|
|
||
|
|
return currentHigh > prevHigh &&
|
||
|
|
currentClose < prevHigh;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| MARKET STRUCTURE (BOS + CHOCH) |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
input int StructureLookback = 5;
|
||
|
|
|
||
|
|
bool IsSwingHigh(int shift)
|
||
|
|
{
|
||
|
|
double center =
|
||
|
|
iHigh(_Symbol, PERIOD_M15, shift);
|
||
|
|
|
||
|
|
for(int i=1; i<=SwingStrength; i++)
|
||
|
|
{
|
||
|
|
if(center <= iHigh(_Symbol, PERIOD_M15, shift-i))
|
||
|
|
return false;
|
||
|
|
|
||
|
|
if(center <= iHigh(_Symbol, PERIOD_M15, shift+i))
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool IsSwingLow(int shift)
|
||
|
|
{
|
||
|
|
double center =
|
||
|
|
iLow(_Symbol, PERIOD_M15, shift);
|
||
|
|
|
||
|
|
for(int i=1; i<=SwingStrength; i++)
|
||
|
|
{
|
||
|
|
if(center >= iLow(_Symbol, PERIOD_M15, shift-i))
|
||
|
|
return false;
|
||
|
|
|
||
|
|
if(center >= iLow(_Symbol, PERIOD_M15, shift+i))
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
double GetLastSwingHigh()
|
||
|
|
{
|
||
|
|
for(int i=SwingStrength+1;
|
||
|
|
i<SwingLookback;
|
||
|
|
i++)
|
||
|
|
{
|
||
|
|
if(IsSwingHigh(i))
|
||
|
|
{
|
||
|
|
return iHigh(
|
||
|
|
_Symbol,
|
||
|
|
PERIOD_M15,
|
||
|
|
i
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
double GetLastSwingLow()
|
||
|
|
{
|
||
|
|
for(int i=SwingStrength+1;
|
||
|
|
i<SwingLookback;
|
||
|
|
i++)
|
||
|
|
{
|
||
|
|
if(IsSwingLow(i))
|
||
|
|
{
|
||
|
|
return iLow(
|
||
|
|
_Symbol,
|
||
|
|
PERIOD_M15,
|
||
|
|
i
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Bullish BOS |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
bool BullishBOS()
|
||
|
|
{
|
||
|
|
double currentClose =
|
||
|
|
iClose(
|
||
|
|
_Symbol,
|
||
|
|
PERIOD_M15,
|
||
|
|
1
|
||
|
|
);
|
||
|
|
|
||
|
|
double swingHigh =
|
||
|
|
GetLastSwingHigh();
|
||
|
|
|
||
|
|
// Fallback to lookback high if no swing high found
|
||
|
|
if(swingHigh <= 0)
|
||
|
|
{
|
||
|
|
swingHigh =
|
||
|
|
iHigh(
|
||
|
|
_Symbol,
|
||
|
|
PERIOD_M15,
|
||
|
|
2
|
||
|
|
);
|
||
|
|
|
||
|
|
for(int i = 3; i
|