MQL5 EA for Multi Moving Average Crossover Strategy
//+------------------------------------------------------------------+
//| MovingAverageCrossoverEA.mq5 |
//| Created by ChatGPT |
//+------------------------------------------------------------------+
#property copyright 'Created by ChatGPT'
#property link 'https://www.example.com'
#property version '1.000'
//---
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
CPositionInfo m_position; // trade position object
CTrade m_trade; // trading object
CSymbolInfo m_symbol; // symbol info object
//--- input parameters
input double Lots = 0.05; // Trading Volume (Lots)
input int FastMA = 6; // Fast Moving Average Period
input int FastMA02 = 8; // Fast Moving Average 02 Period
input int MiddleMA = 16; // Middle Moving Average Period
input int SlowMA = 30; // Slow Moving Average Period
input int SlowMA02 = 28; // Slow Moving Average 02 Period
input ulong m_magic=42828093; // Magic Number (Unique Identifier)
ulong m_slippage=10; // Slippage (in points)
//---
int handle_fastMA; // Fast Moving Average Indicator Handle
int handle_fastMA02; // Fast Moving Average 02 Indicator Handle
int handle_middleMA; // Middle Moving Average Indicator Handle
int handle_slowMA; // Slow Moving Average Indicator Handle
int handle_slowMA02; // Slow Moving Average 02 Indicator Handle
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
if(!m_symbol.Name(Symbol())) // Set the trading symbol name
return(INIT_FAILED);
RefreshRates();
string err_text='';
if(!CheckVolumeValue(Lots,err_text))
{
Print(err_text);
return(INIT_PARAMETERS_INCORRECT);
}
//---
m_trade.SetExpertMagicNumber(m_magic);
if(IsFillingTypeAllowed(SYMBOL_FILLING_FOK))
m_trade.SetTypeFilling(ORDER_FILLING_FOK);
else if(IsFillingTypeAllowed(SYMBOL_FILLING_IOC))
m_trade.SetTypeFilling(ORDER_FILLING_IOC);
else
m_trade.SetTypeFilling(ORDER_FILLING_RETURN);
m_trade.SetDeviationInPoints(m_slippage);
//--- Create Fast Moving Average Indicator Handle
handle_fastMA = iMA(m_symbol.Name(), PERIOD_M15, FastMA, 0, MODE_SMA, PRICE_CLOSE);
handle_fastMA02 = iMA(m_symbol.Name(), PERIOD_M15, FastMA02, 0, MODE_SMA, PRICE_CLOSE);
//--- Create Middle Moving Average Indicator Handle
handle_middleMA = iMA(m_symbol.Name(), PERIOD_M15, MiddleMA, 0, MODE_SMA, PRICE_CLOSE);
//--- Create Slow Moving Average Indicator Handle
handle_slowMA = iMA(m_symbol.Name(), PERIOD_M15, SlowMA, 0, MODE_SMA, PRICE_CLOSE);
handle_slowMA02 = iMA(m_symbol.Name(), PERIOD_M15, SlowMA02, 0, MODE_SMA, PRICE_CLOSE);
//--- Check if the indicator handle was created successfully
if(handle_fastMA == INVALID_HANDLE || handle_fastMA02 == INVALID_HANDLE || handle_middleMA == INVALID_HANDLE || handle_slowMA == INVALID_HANDLE || handle_slowMA02 == INVALID_HANDLE)
{
Print('Failed to create moving average indicators for the symbol ', m_symbol.Name());
return(INIT_FAILED);
}
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//--- Only trade when a new bar is generated
static datetime PrevBars=0;
datetime time_0=iTime(0);
if(time_0==PrevBars)
return;
PrevBars=time_0;
//--- Get the moving average values
double fastMA = iMAGet(0, handle_fastMA);
double fastMA02 = iMAGet(0, handle_fastMA02);
double middleMA = iMAGet(0, handle_middleMA);
double slowMA = iMAGet(0, handle_slowMA);
double slowMA02 = iMAGet(0, handle_slowMA02);
//--- Check if there is any open position
for(int i=PositionsTotal()-1;i>=0;i--)
{
if(m_position.SelectByIndex(i))
{
if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
{
if(m_position.PositionType()==POSITION_TYPE_BUY && fastMA < slowMA && fastMA < middleMA && fastMA < slowMA02)
{
//--- Close buy position (Sell Order)
m_trade.PositionClose(m_position.Ticket());
break;
}
else if(m_position.PositionType()==POSITION_TYPE_SELL && fastMA > slowMA && fastMA > middleMA && fastMA > fastMA02)
{
//--- Close sell position (Buy Order)
m_trade.PositionClose(m_position.Ticket());
break;
}
}
}
}
//--- If the fast moving average crosses above the slow moving average, open a buy trade
if(fastMA > slowMA && fastMA > middleMA && fastMA > slowMA02 && m_position.PositionType() != POSITION_TYPE_BUY)
{
m_trade.Buy(Lots, m_symbol.Name());
}
//--- If the fast moving average crosses below the slow moving average, open a sell trade
else if(fastMA < slowMA && fastMA < middleMA && fastMA < fastMA02 && m_position.PositionType() != POSITION_TYPE_SELL)
{
m_trade.Sell(Lots, m_symbol.Name());
}
}
//+------------------------------------------------------------------+
//| Refresh trading symbol market data |
//+------------------------------------------------------------------+
bool RefreshRates(void)
{
//--- Refresh market data
if(!m_symbol.RefreshRates())
{
Print('RefreshRates error');
return(false);
}
//--- Protect the return value from being 'zero'
if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
return(false);
return(true);
}
//+------------------------------------------------------------------+
//| Check the correctness of the trading volume |
//+------------------------------------------------------------------+
bool CheckVolumeValue(double volume, string &error_description)
{
//--- Minimum allowed trading volume
double min_volume = m_symbol.LotsMin();
if(volume < min_volume)
{
error_description = StringFormat('Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f', min_volume);
return(false);
}
//--- Maximum allowed trading volume
double max_volume = m_symbol.LotsMax();
if(volume > max_volume)
{
error_description = StringFormat('Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f', max_volume);
return(false);
}
//--- Get the minimum step change in trading volume
double volume_step = m_symbol.LotsStep();
int ratio = (int)MathRound(volume / volume_step);
if(MathAbs(ratio * volume_step - volume) > 0.0000001)
{
error_description = StringFormat('Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f',
volume_step,ratio * volume_step);
return(false);
}
error_description = 'Correct volume value';
return(true);
}
//+------------------------------------------------------------------+
//| Check if the specified order filling mode is allowed |
//+------------------------------------------------------------------+
bool IsFillingTypeAllowed(int fill_type)
{
int filling = m_symbol.TradeFillFlags();
return((filling & fill_type) == fill_type);
}
//+------------------------------------------------------------------+
//| Get the time of the specified bar |
//+------------------------------------------------------------------+
datetime iTime(const int index, string symbol=NULL, ENUM_TIMEFRAMES timeframe=PERIOD_CURRENT)
{
if(symbol == NULL)
symbol = m_symbol.Name();
if(timeframe == 0)
timeframe = Period();
datetime Time[1];
datetime time = 0;
int copied = CopyTime(symbol, timeframe, index, 1, Time);
if(copied > 0)
time = Time[0];
return(time);
}
//+------------------------------------------------------------------+
//| Get the value of the iMA indicator buffer |
//| The buffer numbers are as follows: |
//| 0 - MAIN_LINE, 1 - SIGNAL_LINE |
//+------------------------------------------------------------------+
double iMAGet(const int index, const int handle)
{
double MA[1];
if(CopyBuffer(handle, 0, index, 1, MA) < 0)
{
Print('Failed to copy data from the moving average indicator');
return(0.0);
}
return(MA[0]);
}
原文地址: https://www.cveoy.top/t/topic/fUS2 著作权归作者所有。请勿转载和采集!