last ...
This commit is contained in:
@@ -0,0 +1,418 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| SMC_OrderBlock_EA.mq5|
|
||||
//| Copyright 2023, MetaQuotes Software Corp. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2023, MetaQuotes Software Corp."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
#include <Trade/AccountInfo.mqh>
|
||||
#include <Trade/Trade.mqh>
|
||||
|
||||
//
|
||||
// Input parameters
|
||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_M15; // Timeframe for analysis
|
||||
input double RiskPercent = 1.0; // Risk per trade (1-2%)
|
||||
input int ATR_Period = 14; // ATR period for volatility
|
||||
input int OrderBlockLength = 20; // Bars for consolidation
|
||||
input int ConfirmationCandles = 3; // Candles to confirm breakout
|
||||
input double StopLossMultiplier = 1.5; // Stop loss buffer
|
||||
input double TakeProfitRatio = 2.0; // Risk:Reward ratio
|
||||
input int TrailingStopPips = 50; // Trailing stop in pips
|
||||
|
||||
//
|
||||
CTrade trade;
|
||||
CAccountInfo accountInfo;
|
||||
|
||||
//
|
||||
double Ask = 0;
|
||||
double Bid = 0;
|
||||
|
||||
//
|
||||
// Order Block structure
|
||||
struct OrderBlock
|
||||
{
|
||||
datetime startTime;
|
||||
double high;
|
||||
double low;
|
||||
};
|
||||
|
||||
//
|
||||
int atrHandler = INVALID_HANDLE;
|
||||
int maFastHandler = INVALID_HANDLE;
|
||||
int maSlowHandler = INVALID_HANDLE;
|
||||
|
||||
//
|
||||
double atrs[];
|
||||
double fastMAs[];
|
||||
double slowMAs[];
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
//
|
||||
trade.SetExpertMagicNumber(123456); // Unique magic number
|
||||
|
||||
//
|
||||
atrHandler = iATR(_Symbol, TimeFrame, ATR_Period);
|
||||
maFastHandler = iMA(_Symbol, TimeFrame, 20, 0, MODE_SMA, PRICE_CLOSE);
|
||||
maSlowHandler = iMA(_Symbol, TimeFrame, 50, 0, MODE_SMA, PRICE_CLOSE);
|
||||
|
||||
//
|
||||
bool isValid =
|
||||
atrHandler != INVALID_HANDLE &&
|
||||
maFastHandler != INVALID_HANDLE &&
|
||||
maSlowHandler != INVALID_HANDLE;
|
||||
if (!isValid)
|
||||
{
|
||||
return (INIT_FAILED);
|
||||
}
|
||||
|
||||
//
|
||||
return (INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//
|
||||
// Cleanup code if needed ...
|
||||
IndicatorRelease(atrHandler);
|
||||
IndicatorRelease(maFastHandler);
|
||||
IndicatorRelease(maSlowHandler);
|
||||
|
||||
//
|
||||
ZeroMemory(atrs);
|
||||
ZeroMemory(fastMAs);
|
||||
ZeroMemory(slowMAs);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
// Avoid multiple orders
|
||||
if (CheckOpenOrders())
|
||||
return;
|
||||
|
||||
//
|
||||
CopyBuffer(atrHandler, MAIN_LINE, 0, 200, atrs);
|
||||
|
||||
//
|
||||
CopyBuffer(maFastHandler, MAIN_LINE, 0, 2, fastMAs);
|
||||
CopyBuffer(maSlowHandler, MAIN_LINE, 0, 2, slowMAs);
|
||||
|
||||
//
|
||||
Ask = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits); // Get the Ask Price
|
||||
Bid = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits); // Get the Bid Price
|
||||
|
||||
//
|
||||
// Check for trend and execute trades
|
||||
if (IsUptrend())
|
||||
{
|
||||
OrderBlock block = FindBullishOrderBlock();
|
||||
if (block.startTime != 0 && IsPriceInBlock(block))
|
||||
{
|
||||
if (ConfirmBullishEntry())
|
||||
ExecuteTrade(block, ORDER_TYPE_BUY);
|
||||
}
|
||||
}
|
||||
else if (IsDowntrend())
|
||||
{
|
||||
OrderBlock block = FindBearishOrderBlock();
|
||||
if (block.startTime != 0 && IsPriceInBlock(block))
|
||||
{
|
||||
if (ConfirmBearishEntry())
|
||||
ExecuteTrade(block, ORDER_TYPE_SELL);
|
||||
}
|
||||
}
|
||||
|
||||
// Manage trailing stops
|
||||
TrailStop();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if price is within the order block |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IsPriceInBlock(OrderBlock &block)
|
||||
{
|
||||
double currentPrice = (Ask + Bid) / 2; // Mid-price
|
||||
return (currentPrice >= block.low && currentPrice <= block.high);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Detect uptrend using moving averages |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IsUptrend()
|
||||
{
|
||||
//
|
||||
double maFast = fastMAs[0];
|
||||
double maSlow = slowMAs[0];
|
||||
|
||||
//
|
||||
return (maFast > maSlow);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Detect downtrend using moving averages |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IsDowntrend()
|
||||
{
|
||||
//
|
||||
double maFast = fastMAs[0];
|
||||
double maSlow = slowMAs[0];
|
||||
|
||||
//
|
||||
return (maFast < maSlow);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find bullish order blocks |
|
||||
//+------------------------------------------------------------------+
|
||||
OrderBlock FindBullishOrderBlock()
|
||||
{
|
||||
//
|
||||
OrderBlock block;
|
||||
block.startTime = 0;
|
||||
|
||||
//
|
||||
for (int i = 1; i < 100; i++)
|
||||
{
|
||||
double prevHigh = iHigh(NULL, TimeFrame, i);
|
||||
double prevLow = iLow(NULL, TimeFrame, i);
|
||||
double prevClose = iClose(NULL, TimeFrame, i);
|
||||
double prevOpen = iOpen(NULL, TimeFrame, i);
|
||||
|
||||
double atr = atrs[i];
|
||||
if (prevClose - prevOpen > 1.5 * atr)
|
||||
{ // Strong bullish candle
|
||||
double consolidationHigh = prevHigh;
|
||||
double consolidationLow = prevLow;
|
||||
bool isConsolidation = true;
|
||||
|
||||
for (int j = 1; j <= OrderBlockLength; j++)
|
||||
{
|
||||
double newHigh = iHigh(NULL, TimeFrame, i - j);
|
||||
double newLow = iLow(NULL, TimeFrame, i - j);
|
||||
consolidationHigh = MathMax(consolidationHigh, newHigh);
|
||||
consolidationLow = MathMin(consolidationLow, newLow);
|
||||
|
||||
if ((consolidationHigh - consolidationLow) > 0.5 * atr)
|
||||
{
|
||||
isConsolidation = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isConsolidation)
|
||||
{
|
||||
block.high = consolidationHigh;
|
||||
block.low = consolidationLow;
|
||||
block.startTime = iTime(NULL, TimeFrame, i);
|
||||
return block;
|
||||
}
|
||||
}
|
||||
}
|
||||
return block;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find bearish order blocks |
|
||||
//+------------------------------------------------------------------+
|
||||
OrderBlock FindBearishOrderBlock()
|
||||
{
|
||||
//
|
||||
OrderBlock block;
|
||||
block.startTime = 0;
|
||||
|
||||
//
|
||||
for (int i = 1; i < 100; i++)
|
||||
{
|
||||
double prevHigh = iHigh(NULL, TimeFrame, i);
|
||||
double prevLow = iLow(NULL, TimeFrame, i);
|
||||
double prevClose = iClose(NULL, TimeFrame, i);
|
||||
double prevOpen = iOpen(NULL, TimeFrame, i);
|
||||
|
||||
double atr = atrs[i];
|
||||
if (prevOpen - prevClose > 1.5 * atr)
|
||||
{ // Strong bearish candle
|
||||
double consolidationHigh = prevHigh;
|
||||
double consolidationLow = prevLow;
|
||||
bool isConsolidation = true;
|
||||
|
||||
for (int j = 1; j <= OrderBlockLength; j++)
|
||||
{
|
||||
double newHigh = iHigh(NULL, TimeFrame, i - j);
|
||||
double newLow = iLow(NULL, TimeFrame, i - j);
|
||||
consolidationHigh = MathMax(consolidationHigh, newHigh);
|
||||
consolidationLow = MathMin(consolidationLow, newLow);
|
||||
|
||||
if ((consolidationHigh - consolidationLow) > 0.5 * atr)
|
||||
{
|
||||
isConsolidation = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isConsolidation)
|
||||
{
|
||||
block.high = consolidationHigh;
|
||||
block.low = consolidationLow;
|
||||
block.startTime = iTime(NULL, TimeFrame, i);
|
||||
return block;
|
||||
}
|
||||
}
|
||||
}
|
||||
return block;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Confirm bullish entry with candle pattern |
|
||||
//+------------------------------------------------------------------+
|
||||
bool ConfirmBullishEntry()
|
||||
{
|
||||
//
|
||||
int shift = iBarShift(NULL, TimeFrame, TimeCurrent());
|
||||
double prevLow = iLow(NULL, TimeFrame, shift + 1);
|
||||
double currentClose = iClose(NULL, TimeFrame, shift);
|
||||
return (currentClose > prevLow && iOpen(NULL, TimeFrame, shift) < currentClose);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Confirm bearish entry with candle pattern |
|
||||
//+------------------------------------------------------------------+
|
||||
bool ConfirmBearishEntry()
|
||||
{
|
||||
//
|
||||
int shift = iBarShift(NULL, TimeFrame, TimeCurrent());
|
||||
double prevHigh = iHigh(NULL, TimeFrame, shift + 1);
|
||||
double currentClose = iClose(NULL, TimeFrame, shift);
|
||||
return (currentClose < prevHigh && iOpen(NULL, TimeFrame, shift) > currentClose);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Execute trade with risk management |
|
||||
//+------------------------------------------------------------------+
|
||||
void ExecuteTrade(OrderBlock &block, ENUM_ORDER_TYPE orderType)
|
||||
{
|
||||
//
|
||||
double atr = atrs[0];
|
||||
double stopLoss, takeProfit, lotSize;
|
||||
double entryPrice = (orderType == ORDER_TYPE_BUY) ? Ask : Bid;
|
||||
|
||||
// Calculate stop loss and take profit
|
||||
if (orderType == ORDER_TYPE_BUY)
|
||||
{
|
||||
stopLoss = block.low - StopLossMultiplier * atr;
|
||||
takeProfit = entryPrice + (entryPrice - stopLoss) * TakeProfitRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
stopLoss = block.high + StopLossMultiplier * atr;
|
||||
takeProfit = entryPrice - (stopLoss - entryPrice) * TakeProfitRatio;
|
||||
}
|
||||
|
||||
// Calculate lot size based on risk
|
||||
lotSize = CalculateLotSize(stopLoss, entryPrice, orderType);
|
||||
if (lotSize <= 0)
|
||||
return;
|
||||
|
||||
// Place order
|
||||
if (orderType == ORDER_TYPE_BUY)
|
||||
{
|
||||
trade.Buy(lotSize, _Symbol, entryPrice, stopLoss, takeProfit, "SMC Bullish Order Block");
|
||||
}
|
||||
else
|
||||
{
|
||||
trade.Sell(lotSize, _Symbol, entryPrice, stopLoss, takeProfit, "SMC Bearish Order Block");
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate lot size based on risk per trade |
|
||||
//+------------------------------------------------------------------+
|
||||
double CalculateLotSize(double stopLoss, double entryPrice, ENUM_ORDER_TYPE orderType)
|
||||
{
|
||||
double riskAmount = AccountBalance() * RiskPercent / 100;
|
||||
double stopLossPips = MathAbs((entryPrice - stopLoss) / SymbolInfoDouble(_Symbol, SYMBOL_POINT));
|
||||
|
||||
if (stopLossPips == 0)
|
||||
return 0;
|
||||
|
||||
double pipValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
|
||||
double lotSize = riskAmount / (stopLossPips * pipValue);
|
||||
lotSize = NormalizeDouble(lotSize, 2); // Adjust to symbol's lot precision
|
||||
|
||||
return MathMax(lotSize, SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for existing open orders |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckOpenOrders()
|
||||
{
|
||||
for (int i = 0; i < PositionsTotal(); i++)
|
||||
{
|
||||
if (PositionGetSymbol(i) == _Symbol)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Trailing stop logic |
|
||||
//+------------------------------------------------------------------+
|
||||
void TrailStop()
|
||||
{
|
||||
for (int i = 0; i < PositionsTotal(); i++)
|
||||
{
|
||||
if (PositionGetSymbol(i) != _Symbol)
|
||||
continue;
|
||||
|
||||
ulong ticket = PositionGetInteger(POSITION_TICKET);
|
||||
ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
double currentPrice = (type == POSITION_TYPE_BUY) ? Bid : Ask;
|
||||
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
double stopLoss = PositionGetDouble(POSITION_SL);
|
||||
double trailingStopPrice = (type == POSITION_TYPE_BUY)
|
||||
? currentPrice - TrailingStopPips * SymbolInfoDouble(_Symbol, SYMBOL_POINT)
|
||||
: currentPrice + TrailingStopPips * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
|
||||
|
||||
// Update stop loss if price moves favorably
|
||||
if ((type == POSITION_TYPE_BUY && trailingStopPrice > stopLoss) ||
|
||||
(type == POSITION_TYPE_SELL && trailingStopPrice < stopLoss))
|
||||
{
|
||||
trade.PositionModify(ticket, trailingStopPrice, PositionGetDouble(POSITION_TP));
|
||||
}
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate Account Balance |
|
||||
//+------------------------------------------------------------------+
|
||||
double AccountBalance()
|
||||
{
|
||||
return accountInfo.Balance();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Reference in New Issue
Block a user