English Русский Español Deutsch 日本語 Português
preview
构建蜡烛图趋势约束模型(第8部分):EA开发(II)

构建蜡烛图趋势约束模型(第8部分):EA开发(II)

MetaTrader 5测试者 |
294 0
Clemence Benjamin
Clemence Benjamin

内容:

  1. 引言
  2. 创建一个EA:
  3. 测试器
  4. 结论


    引言

    在我们之前的文章中,我们探讨了使用Trend Constraint V1.09指标创建EA,并辅以手动执行的Trend Constraint R-R脚本用于绘制风险和收益矩形。虽然这种设置提供了富有洞察力的交易信号并增强了可视化效果,但它需要手动干预,而这一过程是可以简化的。鉴于交易环境的快节奏特性,对更高效解决方案的需求变得显而易见。许多交易者寻求能够自主运行的集成系统,以减少持续监督和手动执行的需要。

    本文是本系列的下一步,将指导您开发一个独立的EA,它不仅整合了Trend Constraint V1.09的趋势分析能力,还将风险收益功能直接集成到EA中。我们的目标是利用MetaTrader 5平台上的MQL5为交易者提供一个一体化解决方案,通过增强自动化和无缝操作来跟上市场的需求。

    为了实现这一目标,我们将回顾在第一部份第一部份,和第三部份中涵盖的基础阶段,并借鉴EA执行交易任务所需的逻辑。现在,我们将结合所有这些部分及其逻辑来编写EA。

    以下是指标在MQL5中实现信号生成条件的总结:

    买入(多头)条件:

    1. 日K线必须是看涨的。
    2. 在一个看涨的日K线图内的较低时间框架上,我们需要信号的汇聚。具体来说,内置指标(如相对强弱指数RSI)应显示超卖状态,且快速移动平均线必须向上穿过慢速移动平均线。

    卖出(空头)条件:

    1. 日K线图必须是看跌的。
    2. 在一个看跌的日K线图内的较低时间框架上,我们需要信号的汇聚。具体来说,内置指标(如相对强弱指数RSI)应显示超买状态,且快速移动平均线必须向下穿过慢速移动平均线。


    创建一个EA

    我们使用MetaEditor应用程序编写我们的MQL5 EA。最重要的是要牢记基本原则。以下是我们EA的总体结构。

    大多数EA程序的架构总结:

    • 初始化(OnInit):设置必要的指标和变量。
    • 主循环(OnTick):处理传入的tick,以评估市场条件并做出交易决策。
    • 交易管理(OnTrade):处理与交易相关的事件。
    • 测试(OnTester及相关函数):为在策略测试器中优化和评估EA的性能提供结构。
    • 用户交互(OnChartEvent):可选,但允许通过图表事件与EA进行交互。

    我相信下面的流程图草图将有助于澄清我们期望的结果,使其更容易理解。

    趋势约束EA

    EA各部分及其相互关联的简略流程图

    这种结构确保了我们的EA组织良好,并能够有效地处理实施交易策略所需的各种任务。我将开发过程分为几个子部分,但高级开发人员可以跳过阶段(i)和(ii),直接进入子部分(iii)。

    (i) 在MetaEditor中加载默认EA(模版)

    (ii) 自定义模版

    (iii) 将趋势约束EA的逻辑编写到准备好的模板中


    (i)启动EA模板

    在MetaEditor中,按下Ctrl + N启动一个新文件,并选择“Expert Advisor (Template)”(EA模板),如下图所示:

    启动EA模板

    启动一个新的EA模板

    请注意,由于我之前在电脑上进行过项目开发,因此在启动新项目时,作者详情和链接已经自动填充。您可以根据自己的需求进行自定义。


    (ii) 自定义模版

    本文的写作目的不仅是为了展示我的编程能力,还希望对那些刚刚开始理解开发过程的初学者产生影响,以便他们能够在未来应用所学到的技能。在这一点上,我们正在查看模板,这可能对初学者来说似乎没有太多意义。开始在框架模板中编写代码之前,我将提取并简要解释所需最重要的函数。然后,我们将继续填充细节,编写符合我们需求的EA代码。这种方法至关重要,因为它将使您能够轻松地启动其他项目,这些项目与我们现在关注的内容不同。

    框架模板为我们后续构建EA逻辑提供了基础。

    以下是MetaEditor生成的模板代码:

    //+------------------------------------------------------------------+
    //|                                      Trend Constraint Expert.mq5 |
    //|                                Copyright 2024, Clemence Benjamin |
    //|             https://www.mql5.com/en/users/billionaire2024/seller |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2024, Clemence Benjamin"
    #property link      "https://www.mql5.com/en/users/billionaire2024/seller"
    #property version   "1.00"
    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //---
       
    //---
       return(INIT_SUCCEEDED);
      }
    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
    //---
       
      }
    //+------------------------------------------------------------------+
    //| Expert tick function                                             |
    //+------------------------------------------------------------------+
    void OnTick()
      {
    //---
       
      }
    //+------------------------------------------------------------------+
    //| Trade function                                                   |
    //+------------------------------------------------------------------+
    void OnTrade()
      {
    //---
       
      }
    //+------------------------------------------------------------------+
    //| Tester function                                                  |
    //+------------------------------------------------------------------+
    double OnTester()
      {
    //---
       double ret=0.0;
    //---
    
    //---
       return(ret);
      }
    //+------------------------------------------------------------------+
    //| TesterInit function                                              |
    //+------------------------------------------------------------------+
    void OnTesterInit()
      {
    //---
       
      }
    //+------------------------------------------------------------------+
    //| TesterPass function                                              |
    //+------------------------------------------------------------------+
    void OnTesterPass()
      {
    //---
       
      }
    //+------------------------------------------------------------------+
    //| TesterDeinit function                                            |
    //+------------------------------------------------------------------+
    void OnTesterDeinit()
      {
    //---
       
      }
    //+------------------------------------------------------------------+
    //| ChartEvent function                                              |
    //+------------------------------------------------------------------+
    void OnChartEvent(const int id,
                      const long &lparam,
                      const double &dparam,
                      const string &sparam)
      {
    //---
       
      }
    //+------------------------------------------------------------------+
    

     从模板中,让我们来讨论对我们EA来说至关重要的关键函数:

    • OnInit() 函数:当EA初始化时,该函数仅运行一次,用于设置运行所需的指标、变量或其他资源。正确的初始化确保了在EA开始处理市场数据之前,所有必要的资源都已准备就绪。对于您的“趋势约束EA”,相对强弱指数(RSI)指标和其他关键变量通常会在这里初始化。

    • OnDeinit() 函数:当EA被反初始化时,例如从图表中移除或关闭终端时,会调用此函数。它用于清理资源,例如释放指标句柄或关闭文件,以防止内存泄漏或其他问题。

    • OnTick() 函数:这是主函数,每次EA所附加的交易品种接收到新的tick(价格更新)时都会触发。在您的“趋势约束EA”中,它将包含检查市场条件(如D1趋势和RSI水平)以及做出交易决策(如开仓或平仓)的逻辑。

    • OnTrade() 函数:当发生交易事件时(例如下单、修改或平仓),此函数会被调用,它对于监控交易状态和对变化做出反应至关重要。例如,您可以使用它来跟踪交易何时开启,并相应地调整EA的行为。

    • OnTester() 函数:在策略测试期间使用此函数返回一个双精度值,作为优化的自定义标准。它允许您定义一个自定义指标(如利润因子或回撤)来评估在策略测试器中测试EA的性能。

    • OnTesterInit()、OnTesterPass() 和 OnTesterDeinit() 函数:这些函数专门用于策略测试和优化,管理策略测试器中的测试开始、正在进行的测试轮次以及测试结束。它们通过初始化资源、收集数据以及在测试后清理,为测试过程提供了更大的控制权。

    • OnChartEvent() 函数:此函数用于处理图表事件,例如鼠标点击或按键操作,从而在EA运行时与之交互。如果您的EA包含用户交互功能(例如通过图表事件更改参数或触发操作),则此函数至关重要。

    通过了解这些函数,我们可以看到如何在它们内部构建逻辑。然而,模板提供的函数可能不足以满足我们正在开发的EA的复杂性。可能需要额外的函数,并且我们需要证明并解释它们的加入,以满足我们“趋势约束EA”的特定需求。

    未包含在EA模板中但对我们的项目必要的额外函数:

    • 指标函数(例如 iRSI):用于计算相对强弱指数(RSI)等对您的交易策略至关重要的指标。
    • 交易函数(CTrade 类):用于管理订单和仓位,例如下达买入/卖出订单、设置止损以及修改仓位。
    因此,我们已经概述了我们希望EA在特定、合适的函数中使用的逻辑。这是我计划在EA中包含的函数的框架布局,并且我在代码注释中解释了每个函数在此开发中的必要性。
    //+------------------------------------------------------------------+
    //|                               Trend Constraint Expert Advisor.mq5|
    //|                                 Copyright 2024, Clemence Benjamin|
    //|              https://www.mql5.com/en/users/billionaire2024/seller|
    //+------------------------------------------------------------------+
    
    
    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
       // Initialization code here
       rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);
       if (rsi_handle == INVALID_HANDLE)
         {
          Print("Failed to create RSI indicator handle");
          return(INIT_FAILED);
         }
    
       // Any other initialization tasks
       
       return(INIT_SUCCEEDED);
      }
    
    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
       // Cleanup code here
       IndicatorRelease(rsi_handle);  // Release RSI indicator handle
       // Any other deinitialization tasks
      }
    
    //+------------------------------------------------------------------+
    //| Expert tick function                                             |
    //+------------------------------------------------------------------+
    void OnTick()
      {
       // Main trading logic goes here
       
       // Determine market conditions (e.g., daily trend, RSI levels)
       
       // Check for trade conditions and execute orders if necessary
    
       // Implement trailing stop logic if necessary
      }
    
    //+------------------------------------------------------------------+
    //| Trade event function                                             |
    //+------------------------------------------------------------------+
    void OnTrade()
      {
       // Handle trade events (e.g., order placement, modification, closure)
      }
    
    //+------------------------------------------------------------------+
    //| Tester function                                                  |
    //+------------------------------------------------------------------+
    double OnTester()
      {
       double ret = 0.0;
       // Custom optimization criteria (if any) go here
       return(ret);
      }
    
    //+------------------------------------------------------------------+
    //| TesterInit function                                              |
    //+------------------------------------------------------------------+
    void OnTesterInit()
      {
       // Initialization for testing (if needed)
      }
    
    //+------------------------------------------------------------------+
    //| TesterPass function                                              |
    //+------------------------------------------------------------------+
    void OnTesterPass()
      {
       // Actions after each optimization pass (if needed)
      }
    
    //+------------------------------------------------------------------+
    //| TesterDeinit function                                            |
    //+------------------------------------------------------------------+
    void OnTesterDeinit()
      {
       // Cleanup after testing (if needed)
      }
    
    //+------------------------------------------------------------------+
    //| Chart event function                                             |
    //+------------------------------------------------------------------+
    void OnChartEvent(const int id,
                      const long &lparam,
                      const double &dparam,
                      const string &sparam)
      {
       // Handle chart events (e.g., mouse clicks, key presses) here
      }
    
    //+------------------------------------------------------------------+
    


    (iii) 编写趋势约束EA逻辑。 

    现在,我们可以继续编写构成EA的每个函数的逻辑。让我们逐步构建我们的程序:

    包含交易库:

    我们首先包含交易库,这是必要的,因为该库中的CTrade类提供了执行交易操作(如开仓、修改仓位和平仓)所需的函数。通过包含这个库,我们使EA能够与市场交互并以编程方式管理交易。

    #include <Trade\Trade.mqh>  // Include the trade library
    

    定义输入参数:

    接下来,我们定义输入参数,用户可以根据自己的交易偏好进行调整。这些参数包括RSI周期、超买和超卖水平、手数、止损、获利和跟踪止损。通过编写这些输入行,我们确保EA可以根据不同的市场条件进行定制。程序将使用这些值来决定何时进入和退出交易。

    // Input parameters
    input int    RSI_Period = 14;            // RSI period
    input double RSI_Overbought = 70.0;      // RSI overbought level
    input double RSI_Oversold = 30.0;        // RSI oversold level
    input double Lots = 0.1;                 // Lot size
    input double StopLoss = 100;             // Stop Loss in points
    input double TakeProfit = 200;           // Take Profit in points
    input double TrailingStop = 50;          // Trailing Stop in points
    

    声明全局变量:

    然后,我们声明全局变量,例如RSI_value和RSI_handle,它们将分别存储RSI值和句柄,以及CTrade类的一个实例。通过声明这些变量,我们确保EA可以在不同函数之间保持状态,允许程序在其运行过程中根据需要访问和修改这些值。

    // Global variables
    double rsi_value;
    int rsi_handle;
    CTrade trade;  // Declare an instance of the CTrade class
    

    初始化EA:

    在OnInit函数中,我们使用iRSI函数创建RSI指标句柄。这一步至关重要,因为程序需要这个句柄来在每个tick中获取RSI值。如果无法创建句柄,我们已经编写程序使其返回INIT_FAILED,以防止EA在缺少这个关键组件的情况下运行。这确保了程序只有在完全具备分析市场数据的能力时才会运行。

    int OnInit()
      {
       // Create an RSI indicator handle
       rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);
       if (rsi_handle == INVALID_HANDLE)
         {
          Print("Failed to create RSI indicator handle");
          return(INIT_FAILED);
         }
    
       return(INIT_SUCCEEDED);
      }
    

    反初始化EA:

    为了有效管理资源,我们实现了OnDeinit函数,在EA从图表中移除时释放RSI指标句柄。通过编写这段清理代码,我们防止了内存泄漏,并确保资源被正确释放。程序将在反初始化时自动执行这段清理代码,以保持最佳性能。

    void OnDeinit(const int reason)
      {
       // Release the RSI indicator handle
       IndicatorRelease(rsi_handle);
      }
    

    实现核心交易逻辑:

    核心交易逻辑位于OnTick函数中,它将在市场的每个tick到来时执行。首先,我们编写代码通过比较日K线的开盘价和收盘价来确定当前的日线趋势。这种分析使程序能够判断市场是看涨还是看跌,这对于做出明智的交易决策至关重要。

    void OnTick()
      {
       // Determine current daily trend (bullish or bearish)
       double daily_open = iOpen(_Symbol, PERIOD_D1, 0);
       double daily_close = iClose(_Symbol, PERIOD_D1, 0);
    
       bool is_bullish = daily_close > daily_open;
       bool is_bearish = daily_close < daily_open;
    

    获取RSI值:

    然后,我们使用CopyBuffer和之前创建的RSI句柄来获取RSI值。通过编写这段代码,我们确保程序能够判断市场是否处于超买或超卖状态。程序将在决策过程中使用这个RSI值,以确定是否满足进入交易的条件。

       // Get the RSI value for the current bar
       double rsi_values[];
       if (CopyBuffer(rsi_handle, 0, 0, 1, rsi_values) <= 0)
         {
          Print("Failed to get RSI value");
          return;
         }
       rsi_value = rsi_values[0];
    

    在趋势变化时平仓:

    我们还加入了逻辑,如果市场趋势发生变化,EA将关闭所有未平仓头寸。例如,如果趋势从看涨变为看跌,EA将关闭所有未平仓的多头头寸,反之亦然。通过编写这一保护机制,我们确保程序与当前的市场情绪保持一致,这对于最小化风险至关重要。

       // Close open positions if the trend changes
       for (int i = PositionsTotal() - 1; i >= 0; i--)
         {
          if (PositionSelect(PositionGetSymbol(i)))  // Corrected usage
            {
             int position_type = PositionGetInteger(POSITION_TYPE);
             ulong ticket = PositionGetInteger(POSITION_TICKET);  // Get the position ticket
    
             if ((position_type == POSITION_TYPE_BUY && is_bearish) ||
                 (position_type == POSITION_TYPE_SELL && is_bullish))
               {
                trade.PositionClose(ticket);  // Use the ulong variable directly
               }
            }
         }
    

    检查买入和卖出条件:

    对于买入和卖出条件,我们编写逻辑来检查看涨趋势与超卖RSI的组合用于买入订单,以及看跌趋势与超买RSI的组合用于做空订单。通过编程这些条件,我们确保EA只有在趋势和动量指标达成一致时才会进入交易。程序将监控这些条件并相应地执行交易,确保交易纪律。

       // Check for buy condition (bullish trend + RSI oversold)
       if (is_bullish && rsi_value < RSI_Oversold)
         {
          // No open positions? Place a buy order
          if (PositionsTotal() == 0)
            {
             double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
             double sl = price - StopLoss * _Point;
             double tp = price + TakeProfit * _Point;
    
             // Open a buy order
             trade.Buy(Lots, _Symbol, price, sl, tp, "TrendConstraintExpert Buy");
            }
         }
    
       // Check for sell condition (bearish trend + RSI overbought)
       if (is_bearish && rsi_value > RSI_Overbought)
         {
          // No open positions? Place a sell order
          if (PositionsTotal() == 0)
            {
             double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
             double sl = price + StopLoss * _Point;
             double tp = price - TakeProfit * _Point;
    
             // Open a sell order
             trade.Sell(Lots, _Symbol, price, sl, tp, "TrendConstraintExpert Sell");
            }
         }
    

    实现一种追踪止损机制:

    最后,我们实现了一个跟踪止损机制,以在市场朝着有利方向移动时保护利润。通过编写跟踪止损逻辑,我们确保EA能够动态调整止损,锁定利润,同时允许交易在市场保持有利的情况下继续进行。程序将自动管理跟踪止损,确保其对市场走势做出响应,以最大化收益并最小化损失。

       // Apply trailing stop
       for (int i = PositionsTotal() - 1; i >= 0; i--)
         {
          if (PositionSelect(PositionGetSymbol(i)))  // Corrected usage
            {
             double price = PositionGetDouble(POSITION_PRICE_OPEN);
             double stopLoss = PositionGetDouble(POSITION_SL);
             double current_price;
    
             if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
               {
                current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
                if (current_price - price > TrailingStop * _Point)
                  {
                   if (stopLoss < current_price - TrailingStop * _Point)
                     {
                      trade.PositionModify(PositionGetInteger(POSITION_TICKET), current_price - TrailingStop * _Point, PositionGetDouble(POSITION_TP));
                     }
                  }
               }
             else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
               {
                current_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
                if (price - current_price > TrailingStop * _Point)
                  {
                   if (stopLoss > current_price + TrailingStop * _Point || stopLoss == 0)
                     {
                      trade.PositionModify(PositionGetInteger(POSITION_TICKET), current_price + TrailingStop * _Point, PositionGetDouble(POSITION_TP));
                     }
                  }
               }
            }
         }
      }

    我们最终的程序,包括标题和其他属性:

    //+------------------------------------------------------------------+
    //|                                      Trend Constraint Expert.mq5 |
    //|                                Copyright 2024, Clemence Benjamin |
    //|             https://www.mql5.com/en/users/billionaire2024/seller |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2024, Clemence Benjamin"
    #property link      "https://www.mql5.com/en/users/billionaire2024/seller"
    #property version   "1.00"
    #property description "A System that seeks to Long D1 Bullish sentiment and short D1 Bearish sentiment"
    #property strict
    
    
    #include <Trade\Trade.mqh>  // Include the trade library
    
    // Input parameters
    input int    RSI_Period = 14;            // RSI period
    input double RSI_Overbought = 70.0;      // RSI overbought level
    input double RSI_Oversold = 30.0;        // RSI oversold level
    input double Lots = 0.1;                 // Lot size
    input double StopLoss = 100;             // Stop Loss in points
    input double TakeProfit = 200;           // Take Profit in points
    input double TrailingStop = 50;          // Trailing Stop in points
    
    // Global variables
    double rsi_value;
    int rsi_handle;
    CTrade trade;  // Declare an instance of the CTrade class
    
    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
       // Create an RSI indicator handle
       rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);
       if (rsi_handle == INVALID_HANDLE)
         {
          Print("Failed to create RSI indicator handle");
          return(INIT_FAILED);
         }
    
       return(INIT_SUCCEEDED);
      }
    
    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
       // Release the RSI indicator handle
       IndicatorRelease(rsi_handle);
      }
    
    //+------------------------------------------------------------------+
    //| Expert tick function                                             |
    //+------------------------------------------------------------------+
    void OnTick()
      {
       // Determine current daily trend (bullish or bearish)
       double daily_open = iOpen(_Symbol, PERIOD_D1, 0);
       double daily_close = iClose(_Symbol, PERIOD_D1, 0);
    
       bool is_bullish = daily_close > daily_open;
       bool is_bearish = daily_close < daily_open;
    
       // Get the RSI value for the current bar
       double rsi_values[];
       if (CopyBuffer(rsi_handle, 0, 0, 1, rsi_values) <= 0)
         {
          Print("Failed to get RSI value");
          return;
         }
       rsi_value = rsi_values[0];
    
       // Close open positions if the trend changes
       for (int i = PositionsTotal() - 1; i >= 0; i--)
         {
          if (PositionSelect(PositionGetSymbol(i)))  // Corrected usage
            {
             int position_type = PositionGetInteger(POSITION_TYPE);
             ulong ticket = PositionGetInteger(POSITION_TICKET);  // Get the position ticket
    
             if ((position_type == POSITION_TYPE_BUY && is_bearish) ||
                 (position_type == POSITION_TYPE_SELL && is_bullish))
               {
                trade.PositionClose(ticket);  // Use the ulong variable directly
               }
            }
         }
    
       // Check for buy condition (bullish trend + RSI oversold)
       if (is_bullish && rsi_value < RSI_Oversold)
         {
          // No open positions? Place a buy order
          if (PositionsTotal() == 0)
            {
             double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
             double sl = price - StopLoss * _Point;
             double tp = price + TakeProfit * _Point;
    
             // Open a buy order
             trade.Buy(Lots, _Symbol, price, sl, tp, "TrendConstraintExpert Buy");
            }
         }
    
       // Check for sell condition (bearish trend + RSI overbought)
       if (is_bearish && rsi_value > RSI_Overbought)
         {
          // No open positions? Place a sell order
          if (PositionsTotal() == 0)
            {
             double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
             double sl = price + StopLoss * _Point;
             double tp = price - TakeProfit * _Point;
    
             // Open a sell order
             trade.Sell(Lots, _Symbol, price, sl, tp, "TrendConstraintExpert Sell");
            }
         }
    
       // Apply trailing stop
       for (int i = PositionsTotal() - 1; i >= 0; i--)
         {
          if (PositionSelect(PositionGetSymbol(i)))  // Corrected usage
            {
             double price = PositionGetDouble(POSITION_PRICE_OPEN);
             double stopLoss = PositionGetDouble(POSITION_SL);
             double current_price;
    
             if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
               {
                current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
                if (current_price - price > TrailingStop * _Point)
                  {
                   if (stopLoss < current_price - TrailingStop * _Point)
                     {
                      trade.PositionModify(PositionGetInteger(POSITION_TICKET), current_price - TrailingStop * _Point, PositionGetDouble(POSITION_TP));
                     }
                  }
               }
             else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
               {
                current_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
                if (price - current_price > TrailingStop * _Point)
                  {
                   if (stopLoss > current_price + TrailingStop * _Point || stopLoss == 0)
                     {
                      trade.PositionModify(PositionGetInteger(POSITION_TICKET), current_price + TrailingStop * _Point, PositionGetDouble(POSITION_TP));
                     }
                  }
               }
            }
         }
      }
    //+------------------------------------------------------------------+
    //HAPPY DEVELOPING!

    达到这一阶段后,我们可以继续对我们的程序进行测试。我在下面附上了我的测试经验。


    测试器

    为了在MetaTrader 5的策略测试器中测试“趋势约束EA”,我们将首先使用历史数据设置一个回测,以评估EA的性能。这一过程将使我们能够在各种市场条件下模拟其交易策略,从而帮助分析盈利能力、风险管理以及整体有效性。我们需要选择我们期望的时间框架(在本例中为M1时间框架)、输入参数和交易环境,并观察EA是否严格遵循趋势跟踪逻辑和RSI条件。这次测试对于在考虑实盘交易之前对EA进行微调至关重要。我是一个Boom 500指数的粉丝,我喜欢在这个美丽的货币对上测试EA。

    策略测试器

    策略测试器的设置:趋势约束EA

    测试表现

    在策略测试器中的测试表现

    测试结果

    测试结果 01/2023-12/2023



    结论

    我很高兴,我们已经完成了这次精彩的类似教学的讨论。我们的目标是创建一个独立的EA,它不需要安装任何特定的指标。我希望这次讨论能够启发你理解EA开发的结构,并为你提供一个坚实的起点。我们专注于最基本的概念,以确保基础易于掌握。通过输入各种因素来定制EA的能力,允许你尝试不同的值,以找到最具盈利性的设置。

    我们已经成功开发了一个基于我们最初想法的可运行的EA,并且我们可以在测试器中观察订单的执行情况。然而,仍有很大的改进空间。趋势约束EA需要进一步完善,特别是在其入场条件方面,以提高与当前日线趋势一致的盈利能力。这一次,我们没有包含一个“Magic数字”,在真实模拟账户上测试时,我意识到EA影响了已经存在的其他订单。

    与我们之前依赖于安装指标的开发相比,这次开发的一个优势是我们现在有了一个可移植的独立文件来运行。这并不意味着我们之前的尝试是徒劳的;相反,我们从中吸取了宝贵的教训,而那个项目的工具仍然对未来的工作很有用。我们的目标是继续完善EA,以实现最佳可能的结果,随着我们系列的推进。

    接下来,我们将加入一个“Magic数字”,增强我们的入场技术,并进一步提升我们在开发中的创造力。祝您交易愉快!

    文件 说明
    Trend Constraint Expert.mq5 源代码。

    返回顶部

    本文由MetaQuotes Ltd译自英文
    原文地址: https://www.mql5.com/en/articles/15322

    附加的文件 |
    开发回放系统(第 62 部分):玩转服务(三) 开发回放系统(第 62 部分):玩转服务(三)
    在本文中,我们将开始解决在使用真实数据时可能影响应用程序性能的分时报价过量问题。这种过量通常会干扰在相应窗口构建一分钟柱形所需的正确时间。
    创建 MQL5-Telegram 集成 EA 交易 (第 3 部分):将带有标题的图表截图从 MQL5 发送到 Telegram 创建 MQL5-Telegram 集成 EA 交易 (第 3 部分):将带有标题的图表截图从 MQL5 发送到 Telegram
    在本文中,我们创建一个 MQL5 EA 交易,将图表截图编码为图像数据并通过 HTTP 请求将其发送到 Telegram 聊天。通过集成图片编码和传输,我们直接在 Telegram 内通过可视化交易洞察增强了现有的 MQL5-Telegram 系统。
    您应当知道的 MQL5 向导技术(第 32 部分):正则化 您应当知道的 MQL5 向导技术(第 32 部分):正则化
    正则化是一种在贯穿神经网络各层应用离散权重,按比例惩罚损失函数的形式。我们来考察其重要性,对于一些不同的正则化形式,能够在配合向导组装的智能系统运行测试。
    交易中的神经网络:状态空间模型 交易中的神经网络:状态空间模型
    到目前为止,我们审阅的大量模型都是基于变换器架构。不过,在处理长序列时,它们或许效率低下。在本文中,我们将领略一种替代方向,即基于状态空间模型的时间序列预测。