MACD趋势交易策略:自动交易代码实现

本文将介绍一种基于MACD指标和趋势线的交易策略,并提供MQL5代码实现,帮助您构建自己的自动交易系统。

一、交易函数

以下函数用于计算MACD指标、趋势线以及交易信号:

DIFF:=EMA(CLOSE,12) - EMA(CLOSE,26);
DEA:=EMA(DIFF,9);
MACD:=2*(DIFF-DEA/2);
AH:=HHV(MACD,13*1);
AL:=LLV(MACD,13*0.3);
STICKLINE(MACD>0 ,MACD,0,1,0),COLOR0000AA,LINETHICK1;
STICKLINE(MACD<0 ,MACD,0,1,0),COLOR008800,LINETHICK1;
趋势线:=EMA(MACD,34,1);
PARTLINE(趋势线,趋势线>REF(趋势线,1),RGB(255,0,0),趋势线<REF(趋势线,1),RGB(0,255,0)),LINETHICK1;
FILLRGN(趋势线,REF(趋势线,1),趋势线>REF(趋势线,1),RGB(255,0,0),趋势线<=REF(趋势线,1),RGB(0,255,0));

二、交易逻辑

该交易策略的逻辑如下:

  • 做多条件: 当MACD上穿零轴 (MACD > 0) 且趋势线 (EMA(MACD,34,1)) 为红色时,做多。
  • 做多持仓: 一直持有做多头寸,直到MACD在零轴上方出现回落,即当前MACD柱小于前一根MACD柱时,平仓。
  • 做空条件: 当MACD下穿零轴 (MACD < 0) 且趋势线 (EMA(MACD,34,1)) 为绿色时,做空。
  • 做空持仓: 一直持有做空头寸,直到MACD在零轴下方出现反弹,即当前MACD柱大于前一根MACD柱时,平仓。

三、MQL5代码实现

以下代码展示了如何在MQL5中实现上述MACD趋势交易策略:

//+------------------------------------------------------------------+
//|                  MACDTrendEA.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>  
#include <Indicators\Indicators.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;              // 交易手数
input ulong    m_magic=42828093;             // 魔术数字
ulong          m_slippage=10;                // 滑点

//--- indicator handles
int handle_MACD;
int handle_trendline;

//+------------------------------------------------------------------+
//|  Expert initialization function                                  |
//+------------------------------------------------------------------+
int OnInit()
{
    //---
    if(!m_symbol.Name(Symbol())) // 设置交易品种名称
        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 indicator handles
    handle_MACD = iMACD(m_symbol.Name(), PERIOD_CURRENT, 12, 26, 9);
    handle_trendline = iMA(m_symbol.Name(), PERIOD_CURRENT, 34, MODE_EMA, PRICE_CLOSE, handle_MACD, MODE_MAIN);

    //--- check if indicators are created successfully
    if(handle_MACD == INVALID_HANDLE || handle_trendline == INVALID_HANDLE)
    {
        Print("Failed to create 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()
{
    //--- trade only on new bar open
    static datetime PrevBars=0;
    datetime time_0=iTime(0);
    if(time_0==PrevBars)
        return;
    PrevBars=time_0;

    //--- get indicator values
    double MACD = iMACDGet(handle_MACD, 0, MODE_MAIN);
    double prevMACD = iMACDGet(handle_MACD, 1, MODE_MAIN);
    double trendline = iMAGet(handle_trendline, 0);
    double prevTrendline = iMAGet(handle_trendline, 1);

    //--- check if there is an 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 && (MACD < 0 || MACD < prevMACD || trendline < prevTrendline))
                {
                    //--- close long position
                    m_trade.PositionClose(m_position.Ticket());
                    break;
                }
                else if(m_position.PositionType()==POSITION_TYPE_SELL && (MACD > 0 || MACD > prevMACD || trendline > prevTrendline))
                {
                    //--- close short position
                    m_trade.PositionClose(m_position.Ticket());
                    break;
                }
            }
        }
    }

    //--- open long position
    if(MACD > 0 && prevMACD < 0 && trendline > prevTrendline && m_position.PositionType() != POSITION_TYPE_BUY)
    {
        m_trade.Buy(Lots, m_symbol.Name());
    }
    //--- open short position
    else if(MACD < 0 && prevMACD > 0 && trendline < prevTrendline && m_position.PositionType() != POSITION_TYPE_SELL)
    {
        m_trade.Sell(Lots, m_symbol.Name());
    }
}

//+------------------------------------------------------------------+
//|  Refresh symbol quotes                                           |
//+------------------------------------------------------------------+
bool RefreshRates(void)
{
    //--- refresh rates
    if(!m_symbol.RefreshRates())
    {
        Print("RefreshRates error");
        return(false);
    }

    //--- protect from zero values
    if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
        return(false);

    return(true);
}

//+------------------------------------------------------------------+
//|  Check volume value                                              |
//+------------------------------------------------------------------+
bool CheckVolumeValue(double volume, string &error_description)
{
    //--- minimal allowed 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);
    }

    //--- maximal allowed 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 minimal volume step
    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 filling mode is allowed                  | 
//+------------------------------------------------------------------+ 
bool IsFillingTypeAllowed(int fill_type)
{
    int filling = m_symbol.TradeFillFlags();
    return((filling & fill_type) == fill_type);
}

//+------------------------------------------------------------------+ 
//|  Get 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 value of iMA indicator buffer                                |
//|  Buffer numbers are:                                               |
//|   0 - MAIN_LINE, 1 - SIGNAL_LINE                                 |
//+------------------------------------------------------------------+
double iMAGet(const int handle, const int index)
{
    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]);
}

//+------------------------------------------------------------------+
//|  Get value of iMACD indicator buffer                               |
//|  Buffer numbers are:                                               |
//|   0 - MAIN_LINE, 1 - SIGNAL_LINE, 2 - MACD                       |
//+------------------------------------------------------------------+
double iMACDGet(const int handle, const int index, const int mode)
{
    double buffer[1];
    if(CopyBuffer(handle, mode, index, 1, buffer) < 0)
    {
        Print("Failed to copy data from the MACD indicator");
        return(0.0);
    }
    return(buffer[0]);
}

四、总结

本文介绍了一种基于MACD指标和趋势线的交易策略,并提供了MQL5代码实现。请注意,这只是一个简单的示例,您需要根据自己的风险偏好和交易风格进行调整和优化。

免责声明: 交易外汇和差价合约 (CFD) 涉及高风险,您的交易资金可能会损失。在决定交易外汇和差价合约之前,您应该仔细考虑您的投资目标、经验水平和风险承受能力。

MACD趋势交易策略:自动交易代码实现

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

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