Files
MQL5Data/Documents/BKP/x-pv.qween.ea.mq5
T
2025-03-26 05:25:00 +03:30

232 lines
7.5 KiB
Plaintext

//+------------------------------------------------------------------+
//| SaherElm IT Center MQL5 Expert Advisor |
//| |
//| Name: X121 XPV EA |
//| Description: Multi-Timeframe Peak & Vale Breakout Strategy |
//| Maintainer: Hadi Khazaee Asl |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://saherelm.ir"
#property version "1.00"
#property strict
//
#include "../Helpers/x-saherelm.x121.xpv.helper.mq5"
// Input Parameters
input double RiskPercent = 1.0; // Risk per trade in percentage
input int StopLossPips = 50; // Stop Loss in pips
input int TakeProfitPips = 100; // Take Profit in pips
input bool UseTrailingStop = true; // Enable trailing stop
input int TrailingStopPips = 30; // Trailing stop distance in pips
input int MagicNumber = 123456; // Unique identifier for trades
input bool DebugMode = true; // Enable debug messages
//
// Global Variables ...
X121XPVInputs mXPVInputs;
XCX121XPVHelper *mXPVHelper;
//+------------------------------------------------------------------+
//| Expert Initialization Function |
//+------------------------------------------------------------------+
int OnInit()
{
//
// Attach the X121 XPV indicator ...
mXPVInputs.Default();
mXPVHelper = new XCX121XPVHelper();
bool isInited = mXPVHelper.Init(
_Symbol,
_Period,
mXPVInputs //
);
if (!isInited)
{
return INIT_FAILED;
}
//
Print("X121 XPV EA Initialized.");
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert Deinitialization Function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//
mXPVInputs.Clean();
ZeroMemory(mXPVHelper);
Print("X121 XPV EA Deinitialized.");
}
//+------------------------------------------------------------------+
//| Expert Tick Function |
//+------------------------------------------------------------------+
void OnTick()
{
//
// Check if there are open positions for this symbol
if (PositionSelect(_Symbol))
{
ManageOpenPosition();
return;
}
//
X121XPVConditions pvConditions;
bool isRetrieved = mXPVHelper.GetConditions(
pvConditions,
1 //
);
if (!isRetrieved)
{
return;
}
//
// Get indicator values
double peak = pvConditions.peaksBuffer[0];
double vale = pvConditions.valesBuffer[0];
double peakGoldenZone = pvConditions.peaksGoldenBuffer[0];
double valeGoldenZone = pvConditions.valesGoldenBuffer[0];
//
// Validate indicator values
if (peak == EMPTY_VALUE || vale == EMPTY_VALUE || peakGoldenZone == EMPTY_VALUE || valeGoldenZone == EMPTY_VALUE)
{
//
if (DebugMode)
Print("Invalid indicator values. Skipping...");
return;
}
//
// Entry Conditions
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
//
// Long Entry
if (bid > peak && bid > peakGoldenZone)
{
OpenTrade(ORDER_TYPE_BUY, peak, valeGoldenZone);
}
//
// Short Entry
if (ask < vale && ask < valeGoldenZone)
{
OpenTrade(ORDER_TYPE_SELL, vale, peakGoldenZone);
}
}
//+------------------------------------------------------------------+
//| Open a Trade |
//+------------------------------------------------------------------+
void OpenTrade(int orderType, double entryLevel, double targetLevel)
{
//
double lotSize = CalculateLotSize(entryLevel, targetLevel);
double sl = (orderType == ORDER_TYPE_BUY) ? entryLevel - StopLossPips * Point() : entryLevel + StopLossPips * Point();
double tp = (orderType == ORDER_TYPE_BUY) ? entryLevel + TakeProfitPips * Point() : entryLevel - TakeProfitPips * Point();
//
// Prepare trade request
MqlTradeRequest request = {};
MqlTradeResult result = {};
//
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = lotSize;
request.type = (ENUM_ORDER_TYPE)orderType;
request.price = (orderType == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID);
request.sl = sl;
request.tp = tp;
request.deviation = 10;
request.magic = MagicNumber;
//
// Send trade request
if (!OrderSend(request, result))
{
Print("Trade failed: ", result.retcode);
}
else
{
Print("Trade opened successfully.");
}
}
//+------------------------------------------------------------------+
//| Manage Open Position |
//+------------------------------------------------------------------+
void ManageOpenPosition()
{
ulong ticket = PositionGetInteger(POSITION_TICKET);
double currentPrice = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_BID) : SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double sl = PositionGetDouble(POSITION_SL);
double tp = PositionGetDouble(POSITION_TP);
// Trailing Stop Logic
if (UseTrailingStop)
{
double newSL = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
? currentPrice - TrailingStopPips * Point()
: currentPrice + TrailingStopPips * Point();
if ((PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && newSL > sl) ||
(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && newSL < sl))
{
ModifyPosition(ticket, newSL, tp);
}
}
}
//+------------------------------------------------------------------+
//| Modify Position |
//+------------------------------------------------------------------+
void ModifyPosition(ulong ticket, double newSL, double newTP)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_SLTP;
request.position = ticket;
request.sl = newSL;
request.tp = newTP;
if (!OrderSend(request, result))
{
Print("Failed to modify position: ", result.retcode);
}
else
{
Print("Position modified successfully.");
}
}
//+------------------------------------------------------------------+
//| Calculate Lot Size |
//+------------------------------------------------------------------+
double CalculateLotSize(double entryLevel, double targetLevel)
{
double riskAmount = AccountInfoDouble(ACCOUNT_BALANCE) * RiskPercent / 100;
double stopLossDistance = MathAbs(entryLevel - targetLevel) / Point();
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double lotSize = riskAmount / (stopLossDistance * tickValue);
// Normalize lot size
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double stepLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
lotSize = MathFloor(lotSize / stepLot) * stepLot;
lotSize = MathMax(minLot, MathMin(maxLot, lotSize));
return lotSize;
}