//+------------------------------------------------------------------+
//|                  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]);
}
MQL5 EA for Multi Moving Average Crossover Strategy

原文地址: https://www.cveoy.top/t/topic/fUS2 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录