988 行
20 KiB
Text
988 行
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
|