EA1/EA1.mq5

191 lines
7.2 KiB
MQL5
Raw Permalink Normal View History

2026-03-09 13:22:39 +07:00
//+------------------------------------------------------------------+
//| EA1.mq5 |
//| SMA 12/26 Crossover Strategy |
//| Timeframe: M15 |
//| TP: 1000 pips | SL: 500 pips |
//+------------------------------------------------------------------+
#property copyright "EA1"
#property version "1.00"
#property strict
#include <Trade\Trade.mqh>
//--- Input Parameters
input int FastPeriod = 12; // Fast SMA Period
input int SlowPeriod = 26; // Slow SMA Period
input double LotSize = 0.1; // Trade Lot Size
input int TakeProfitPips = 1000; // Take Profit in Pips
input int StopLossPips = 500; // Stop Loss in Pips
input double PipSize = 0.0001; // Pip Size (0.0001 for FX, 0.01 for JPY pairs)
input int MagicNumber = 112600; // Magic Number
//--- Global Variables
CTrade trade;
int fastHandle;
int slowHandle;
datetime lastBarTime = 0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Validate inputs
if(FastPeriod >= SlowPeriod)
{
Print("ERROR: FastPeriod must be less than SlowPeriod.");
return INIT_PARAMETERS_INCORRECT;
}
// Create SMA indicator handles on M15 timeframe
fastHandle = iMA(_Symbol, PERIOD_M15, FastPeriod, 0, MODE_SMA, PRICE_CLOSE);
slowHandle = iMA(_Symbol, PERIOD_M15, SlowPeriod, 0, MODE_SMA, PRICE_CLOSE);
if(fastHandle == INVALID_HANDLE || slowHandle == INVALID_HANDLE)
{
Print("ERROR: Failed to create MA indicator handles.");
return INIT_FAILED;
}
trade.SetExpertMagicNumber(MagicNumber);
trade.SetDeviationInPoints(10);
Print("EA1 initialized | Symbol: ", _Symbol,
" | FastSMA: ", FastPeriod,
" | SlowSMA: ", SlowPeriod,
" | TP: ", TakeProfitPips, " pips",
" | SL: ", StopLossPips, " pips");
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(fastHandle != INVALID_HANDLE) IndicatorRelease(fastHandle);
if(slowHandle != INVALID_HANDLE) IndicatorRelease(slowHandle);
Print("EA1 deinitialized.");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Only process logic on a new M15 bar
datetime currentBarTime = iTime(_Symbol, PERIOD_M15, 0);
if(currentBarTime == lastBarTime)
return;
lastBarTime = currentBarTime;
// Get crossover signal from closed bars [1] and [2]
int signal = CheckCrossover();
if(signal == 0)
return;
// Close any opposite open position before opening a new trade
CloseOppositePosition(signal);
// Avoid opening a duplicate position in the same direction
if(HasOpenPosition(signal))
return;
// Calculate SL and TP in price
double tpDistance = TakeProfitPips * PipSize;
double slDistance = StopLossPips * PipSize;
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
if(signal == 1) // BUY signal — SMA12 crossed above SMA26
{
double sl = NormalizeDouble(ask - slDistance, _Digits);
double tp = NormalizeDouble(ask + tpDistance, _Digits);
if(trade.Buy(LotSize, _Symbol, ask, sl, tp, "SMA CrossUp"))
Print("BUY opened | Ask: ", ask, " | SL: ", sl, " | TP: ", tp);
else
Print("BUY failed | Error: ", GetLastError());
}
else if(signal == -1) // SELL signal — SMA12 crossed below SMA26
{
double sl = NormalizeDouble(bid + slDistance, _Digits);
double tp = NormalizeDouble(bid - tpDistance, _Digits);
if(trade.Sell(LotSize, _Symbol, bid, sl, tp, "SMA CrossDown"))
Print("SELL opened | Bid: ", bid, " | SL: ", sl, " | TP: ", tp);
else
Print("SELL failed | Error: ", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Check for SMA crossover on the last two closed bars |
//| Returns: 1 = Bullish cross (SMA12 crosses ABOVE SMA26) |
//| -1 = Bearish cross (SMA12 crosses BELOW SMA26) |
//| 0 = No crossover |
//+------------------------------------------------------------------+
int CheckCrossover()
{
double fastCurrent[1], fastPrev[1];
double slowCurrent[1], slowPrev[1];
// Copy values for bar [1] (last closed bar) and bar [2] (bar before that)
if(CopyBuffer(fastHandle, 0, 1, 1, fastCurrent) < 1) return 0;
if(CopyBuffer(fastHandle, 0, 2, 1, fastPrev) < 1) return 0;
if(CopyBuffer(slowHandle, 0, 1, 1, slowCurrent) < 1) return 0;
if(CopyBuffer(slowHandle, 0, 2, 1, slowPrev) < 1) return 0;
bool bullishCross = (fastPrev[0] <= slowPrev[0]) && (fastCurrent[0] > slowCurrent[0]);
bool bearishCross = (fastPrev[0] >= slowPrev[0]) && (fastCurrent[0] < slowCurrent[0]);
if(bullishCross) return 1;
if(bearishCross) return -1;
return 0;
}
//+------------------------------------------------------------------+
//| Close any open position opposite to the new signal |
//+------------------------------------------------------------------+
void CloseOppositePosition(int signal)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
long posType = PositionGetInteger(POSITION_TYPE);
// Close BUY position on a SELL signal, or SELL position on a BUY signal
if((signal == -1 && posType == POSITION_TYPE_BUY) ||
(signal == 1 && posType == POSITION_TYPE_SELL))
{
if(trade.PositionClose(ticket))
Print("Position closed | Ticket: ", ticket);
else
Print("Close failed | Ticket: ", ticket, " | Error: ", GetLastError());
}
}
}
//+------------------------------------------------------------------+
//| Check if there is already an open position in the signal direction|
//+------------------------------------------------------------------+
bool HasOpenPosition(int signal)
{
for(int i = 0; i < PositionsTotal(); i++)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
long posType = PositionGetInteger(POSITION_TYPE);
if(signal == 1 && posType == POSITION_TYPE_BUY) return true;
if(signal == -1 && posType == POSITION_TYPE_SELL) return true;
}
return false;
}
//+------------------------------------------------------------------+