English Русский Español Deutsch 日本語 Português
preview
在 MetaTrader 5 中测试和优化二元期权策略

在 MetaTrader 5 中测试和优化二元期权策略

MetaTrader 5测试者 | 15 六月 2023, 09:57
1 183 0
Roman Poshtar
Roman Poshtar

概述

最近,我对二元期权产生了兴趣。 在网上冲浪,并查看了一些经纪商之后,发现几乎大多人都在他们的平台进行交易。 这些平台没有测试策略的能力,充其量只有一套浅薄的标准指标。 在审查了大量不同的二元期权策略后,我开始琢磨如何验证这些策略及其优化。 和往常一样,我们心爱的 MetaTrader 5 来拯救我了。 与往常一样,我将尝试尽可能简单地与您分享我的实验,在没有复杂方程和代码的情况下贡献真材实料。 但首先,关于二元期权是否值得深入研究,,极其理论尚存争论。


理论

二元期权是一种数字合约,其主题是预测选定时间段内资产价格的方向。 任务是正确判定市场形势发展的两种可能情景之一:资产是上涨还是下跌。 今天,我们有广泛的货币、证券和商品可在线选择。 实践中几乎任何东西(包括天气预报)都可以成为一种资产。 交易不需要在市场交易过程领域进行巨额投资,以及深厚的金融和经济知识。


二元期权的类型

最高价/最低价是最简单的二元期权类型,因为交易者只需要判定价格将朝哪个方向发展。 在看涨趋势中,建议买入最高价(看涨期权)。 如果预计资产将向下移动,则按最低价购买(看跌期权)。 最高价/最低价期权的利润从赌注的 10% 到 80% 不等。

“一次式触及”代表一个协议,其中需要判定所期望价位的达到。 平仓期间的价位无关紧要。 触及给定水平就足够了。 “一次式触及”的盈利能力高于平时,可能达到 95%,由于在大多数情况下很难预测它们,故您也可能会 100% 亏掉所有。

范围判定一个价格走廊,资产的价值将在到期时位于该走廊之内。 这也很难理解和预测。 盈利能力高达 95%。

下面我将测试和优化最高价/最低价期权的策略,因为我认为这是最受欢迎的。


优点和缺点

优点如下:

  • 简单 — 您可以把潜在损失或利润维持在固定数额,避免进行止损和止盈价位的复杂计算,如果您是初学者,这尤其实用。
  • 在期权经纪商的网站上简单注册 — 不需要一揽子文件。
  • 最广泛的资源 — 公司股票、股票指数、石油、黄金、加密货币,初始本金从 100 美元甚至更低。 而在股票或期货市场上交易需要更多金额的初始本金。

缺点:

  • 高风险和负面期望。 需要两场取胜才能弥补一场的损失。 盈利效率高达 80%。 亏损操作的成本将高于取胜操作。
  • “赌博”模式从长远来看终会带来损失。 有些人试图在交易时应用来赌场的技巧,如马丁格尔(译者按:逆势翻倍加仓)等方法,这违反了正确交易的规则,最终导致资金爆仓。
  • 大笔佣金。

    货币对。 优化和前向验证测试范围。 设置

    以下是所有优化和测试参数:

    • 外汇;
    • EURUSD;
    • M5, M15, M30, H1;
    • 到期时间 5, 15, 30 分钟和 1 小时。
    • 优化范围 1 年。 2021.01.28 - 2022.01.28.
    • 前向验证测试范围 1 年。 2022.01.28 - 2023.01.28;
    • 初始本金 10,000;
    • 比率 10;
    • 利率 80%。

      技术方面

      我们需要用于测试和优化的输入:

      1. StartDepo  - 启动资金;
      2. OptionRate - 比率;
      3. ExpirationTime - 到期时间;
      4. ProfitPercent - 盈利百分比;
      5. TimeFrame - 指标时间帧
      6. Optimization - 优化开关;
      7. OptimizationFileName – 存储优化结果的文件名。
      input string N0 = "------------Open settings----------------";
      input double StartDepo = 10000;
      input int OptionRate = 10;
      input string N1 = "------------Close settings---------------";
      input int ExpirationTime = 1; //ExpirationTime 1=5 min, 2=15 min, 3=30 min, 4=60 min
      input double ProfitPercent = 80;
      input string N2 = "------------Optimization settings--------";
      input int TimeFrame = 1; //TimeFrame 1=5 min, 2=15 min, 3=30 min, 4=60 min
      input bool Optimization = false;
      input string OptimizationFileName = "Optimization.csv";
      input string N3 = "------------Other settings---------------";
      input int Slippage = 10;
      input int Magic = 111111;
      input string EAComment = "2Ma+RSI+Stochastic Oscillator";

      我们还需要变量来存储和跟踪资金,以及可盈利和无盈利期权购买数量的变化:

      1. XStartDepo - 存储当前资金;
      2. Profit - 存储可盈利期权购买数量;
      3. Loss - 存储无盈利期权购买数量;
      double XStartDepo = StartDepo;
      int Profit=0;
      int Loss=0;

      为了在 MetaTrader 5 中跟踪开仓时间,并在时间到期后平仓,我们将调用返回开仓时间的函数。

      //+------------------------------------------------------------------+
      //| Get open time in positions                                       |
      //+------------------------------------------------------------------+
      datetime GetTime(string symb="0", int type=-1, int mg=-1,int index=0) {
       datetime p[];
       int c=-1, pr=0;
        if(symb=="0") { symb=Symbol();}
         for(int i=PositionsTotal()-1;i>=0;i--){
            if(position.SelectByIndex(i)) {
           if(position.PositionType()==POSITION_TYPE_BUY || position.PositionType()==POSITION_TYPE_SELL) {
            if((position.Symbol()==symb||symb=="")&&(type<0||position.PositionType()==type)&&(mg<0||position.Magic()==mg)) {
             c++;
             ArrayResize(p, c+1);
             p[c]=position.Time();
             pr=c>=index?index:c;
             
       }}}}
        return(c==-1?0:p[pr]);
       }

      为了跟踪持仓的盈利能力,并决定我们是否赢得了赌注,我们将调用一个函数来返回持仓于当前时间的利润。 佣金和掉期利率此刻不被考虑在内。

      //+------------------------------------------------------------------+
      //| Get profit in positions                                          |
      //+------------------------------------------------------------------+
      double GetProfit(string symb="0", int type=-1, int mg=-1,int index=0) {
       double p[];
       int c=-1, pr=0;
        if(symb=="0") { symb=Symbol();}
         for(int i=PositionsTotal()-1;i>=0;i--){
            if(position.SelectByIndex(i)) {
           if(position.PositionType()==POSITION_TYPE_BUY || position.PositionType()==POSITION_TYPE_SELL) {
            if((position.Symbol()==symb||symb=="")&&(type<0||position.PositionType()==type)&&(mg<0||position.Magic()==mg)) {
             c++;
             ArrayResize(p, c+1);
             p[c]=position.Profit();
             pr=c>=index?index:c;
             
       }}}}
        return(c==-1?0:p[pr]);
       }

      应用若干个触发器,以便仅处理新传入的信号。 换言之,只有当有新信号时,才允许入场。 在同一信号上的重复入场将被忽略:

      1. TrigerSell - 买入看跌期权;
      2. TrigerBuy - 买入看涨期权;
      int TrigerSell=0;
      int TrigerBuy=0;

      持仓离场、在初始资金基础上增/减资金,以及计算所购期权的盈亏,均通过跟踪持仓的当前时间至和到期时间来贯彻。

      //Sell (Put)
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      为了进行优化,使用变量来判定所需的时间帧和到期时间。 优化模式依据 Optimization 变量启用。 优化的本质来自 CSV 等文件的运用。 在 OnDeinit 中完成测试后,将所有必要的变量写入文件。优化时,EA 创建一个存储结果的 CSV 文件,位于 “C:\Users\您的登录名\AppData\Roaming\MetaQuotes\Terminal\Common\Files”。

      1. 最终资金;
      2. 盈利交易数量;
      3. 亏损交易数量;
      4. 时间帧·;
      5. 到期时间。
      //+------------------------------------------------------------------+
      //| Expert deinitialization function                                 |
      //+------------------------------------------------------------------+
      void OnDeinit(const int reason)
        {
      
      if (Optimization==true){
       if (FileIsExist(OptimizationFileName)==false){
         filehandle = FileOpen(OptimizationFileName,FILE_WRITE|FILE_READ|FILE_CSV|FILE_COMMON|FILE_ANSI, ";");
          if(filehandle!=INVALID_HANDLE)
           {
            FileSeek(filehandle, 0, SEEK_END);
            FileWrite(filehandle,DoubleToString(XStartDepo),IntegerToString(Profit),IntegerToString(Loss),IntegerToString(XTimeFrame),IntegerToString(XExpirationTime));
            FileClose(filehandle);
           }
       }
      }
      
        }

      您可以在可视化模式下观查测试。 为简单起见,我们调用 Comment() 显示当前结果。

      当前结果


      策略

      2Ma+RSI+Stochastic 振荡器策略

      该策略由一家知名经纪商提供,作为二元期权的剥头皮策略。 策略的建议时间帧为 5 分钟。 过期时间为 5 分钟。

      指标:

      1. 一对周期为 5 和 10 的指数移动平均线;
      2. RSI,默认设置;
      3. Stochastic 振荡器,设置参数值 14, 3, 3。

      满足多个条件时的“上涨”信号(或买入看涨期权):

      1. 红色移动平均线向上穿过蓝色移动平均线;
      2. RSI 高于 50;
      3. Stochastic 的快速指标线向上穿过慢速指标线(虚线)。

      上行策略 1

      如果存在某些因素,则形成“下降”信号(买入看跌期权):
      1. 红色 MA 向下穿过蓝色 MA;;
      2. RSI 指数位于 50 以下;
      3. Stochastic 振荡器的快速线向下穿过慢速线。

      下行策略 1

      我选择了相反方向的 MA 交点作为这个新信号策略的触发器。 策略代码如下所示。

      //Sell (Put)
      
      if((ind_In1S1[1]>ind_In2S1[1]) && (ind_In1S1[2]>ind_In2S1[2])){TrigerSell=1;}
      
         if ((TrigerSell==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (ind_In1S1[1]<ind_In2S1[1]) && (ind_In1S1[0]<ind_In2S1[0]) && (ind_In4S1[1]<50) && (ind_In4S1[0]<50) && (ind_In3S1_1[1]<ind_In3S1_2[1])){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerSell=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
      if((ind_In1S1[1]<ind_In2S1[1]) && (ind_In1S1[2]<ind_In2S1[2])){TrigerBuy=1;}
      
         if ((TrigerBuy==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (ind_In1S1[1]>ind_In2S1[1]) && (ind_In1S1[0]>ind_In2S1[0]) && (ind_In4S1[1]>50) && (ind_In4S1[0]>50) && (ind_In3S1_1[1]>ind_In3S1_2[1])){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerBuy=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      该测试产生以下结果:

      • 最终资金 1964
      • 盈利交易 1273
      • 亏损交易 1822。

      结果

      优化后,我们得到结果。 正如我们所见,我们的资金在任何时间帧和到期时间都没有增加。

      优化结果


      Maverick 策略

      这是一个有趣而简单的期权策略,名为 Maverick。 它基于两个技术分析指标。 据说可以非常准确地判定入场和离场交易点。 交易的时间帧为 1-5 分钟。 为了接收更多信号,我们可以同时打开多个含有不同资产的图表。

      指标:

      1. 布林带 20 和 StDev(标准偏差)2;
      2. RSI 指标。 RSI 参数 – 周期 4,边界为 80 和 20。

      增长预测。 买入看涨期权:

      一旦 RSI 指标线进入 20 以下的超卖区域,而价格线触及或超过布林带,等待第一根看涨蜡烛,并入场进行向上交易。

      买入看涨

      下跌预测。 买入看跌期权:

      在 RSI 指标线进入 80 以上的超买区域,并且价格线已经超过布林指标的上限后,等待第一根看跌蜡烛,并进行向下交易。

      买入看跌

      我选择在布林指标通道内收盘前一根蜡烛作为新的信号触发器。 策略代码如下所示。

      //Sell (Put)
      
      if(iClose(symbolS1.Name(),XTimeFrame,1)<ind_In1S1_1[1]){TrigerSell=1;}
      
         if ((TrigerSell==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (iClose(symbolS1.Name(),XTimeFrame,2)>ind_In1S1_1[2]) && (ind_In2S1[2]>80) && (iClose(symbolS1.Name(),XTimeFrame,1)<iOpen(symbolS1.Name(),XTimeFrame,1))){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerSell=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
      if(iClose(symbolS1.Name(),XTimeFrame,1)>ind_In1S1_2[1]){TrigerBuy=1;}
      
         if ((TrigerBuy==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (iClose(symbolS1.Name(),XTimeFrame,2)<ind_In1S1_2[2]) && (ind_In2S1[2]<20) && (iClose(symbolS1.Name(),XTimeFrame,1)>iOpen(symbolS1.Name(),XTimeFrame,1))){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerBuy=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      我们开始检查。 我们先在 M5 上进行测试。 得到的结果:

      • 最终资金 3312;
      • 盈利交易 1589;
      • 亏损交易 1940。

      结果

      我们经历了亏损。 虽然结果比以前的策略略好。 我们执行优化,希望能赚取正数值的金额。 唉,该策略未起作用:

      优化结果


       Vortex+TSI 策略

      二元期权的策略被称为 Vortex,这是因为选用了同名指标。 事实上,该策略涉及两个指标 — 主要指标,以及作为过滤器的第二个指标。 建议的时间帧是 1-5 分钟。

      指标:

      1. Vortex 14;
      2. 真实强度指标 (TSI) 25, 13, 5, 指数。

      对于购买看涨期权:

      1. 等待两个指标线同时彼此相交,当蓝线在顶部,红色线下降时;
      2. Vortex 指标线应发散。

      成长

      对于购买看跌期权:

      1. 等待两个指标的线同时彼此相交,当红线在顶部,蓝色线下降;
      2. Vortex 指标线应发散。

      暴跌

      真实强度指示器的反向交叉用作新的信号触发。 策略代码如下所示。
      //Sell (Put)
      
      if(ind_In1S1_1[1]>ind_In1S1_2[1]){TrigerSell=1;}
      
         if ((TrigerSell==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (ind_In1S1_1[0]<ind_In1S1_2[0]) && (ind_In1S1_1[1]<ind_In1S1_2[1]) && (ind_In2S1_1[0]<ind_In2S1_2[0]) && (ind_In2S1_1[1]<ind_In2S1_2[1]) && (ind_In2S1_1[0]<ind_In2S1_1[1]) && (ind_In2S1_2[0]>ind_In2S1_2[1]) && (ind_In2S1_1[1]<ind_In2S1_1[2]) && (ind_In2S1_2[1]>ind_In2S1_2[2])){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerSell=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
      if(ind_In1S1_1[1]<ind_In1S1_2[1]){TrigerBuy=1;}
      
         if ((TrigerBuy==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (ind_In1S1_1[0]>ind_In1S1_2[0]) && (ind_In1S1_1[1]>ind_In1S1_2[1]) && (ind_In2S1_1[0]>ind_In2S1_2[0]) && (ind_In2S1_1[1]>ind_In2S1_2[1]) && (ind_In2S1_1[0]>ind_In2S1_1[1]) && (ind_In2S1_2[0]<ind_In2S1_2[1]) && (ind_In2S1_1[1]>ind_In2S1_1[2]) && (ind_In2S1_2[1]<ind_In2S1_2[2])){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerBuy=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      是时候开始测试我们的指标策略了。 我们先在 M5 上进行测试。 得到的结果:

      • 最终资金 -3118;
      • 盈利交易 1914;
      • 亏损交易 2843。

      亏损交易的数量更多。 最终资金额为负数。 或许优化会有所帮助。

      结果

      优化结果不言自明:

      优化结果


      在测试了大约 10 种不同的策略,但均未得到满意的预期结果后,我决定开发自己的策略。 根据获得的经验,我决定尝试一种不同的方法。 该策略名为“新建”

      新建 策略

      我将利用超卖和超买状况作为策略的核心部分。 我还决定添加摊平操作。 虽然我反对这样的决策,但看看结果仍然很有趣。

      指标:

      轨道线 14, 0, 0,1 简单平均 方法应用于 收盘价.

      “向上”信号或买入看涨期权:

      1. 要价(Ask)小于轨道线指标的下边线;
      2. 从轨道线指标的底线到要价(Ask)的距离(以点为单位)大于 Distance 参数值。

      向上

      “向下”信号或买入看跌期权:

      1. 出价(Bid)高于轨道线指标的上边线;
      2. 从轨道线指标的底线到出价(Bid)的距离(以点为单位)大于 Distance 参数值。

      向下

      策略中不使用触发器。 如果满足条件,且无持仓,则会持续监控新的入场信号。 以下是未采用摊平操作的策略代码

      //Sell (Put)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (BidS1>(ind_In1S1_1[0]+(Distance*PointS1)))){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (AskS1<(ind_In1S1_2[0]-(Distance*PointS1)))){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      我们在 M5 上进行测试。 Distance=150。 下面的屏幕截图中是未采用摊平操作的测试结果

      结果 1

      最终资金 8952;盈利交易 874;

      亏损交易 804。

      可盈利的项目比无盈利的项目多,但我们仍损失了部分资金。 这是负面的期望。 采用这种方法时,连续输掉的最大项目序列是两次,那么我认为运用摊平方式会对我们有利。 

      在下面的屏幕截图中是未采用摊平方式的优化结果。 为了方便和清晰起见,决定在报告中仅包括有盈利的情况:

      优化结果 1

      我们来加入摊平操作。 我决定限制摊平操作的项目数量。 为此,我引入了一个新参数 Averageaging,默认情况下为 4。 摊平策略代码如下:

      //Sell (Put)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (BidS1>(ind_In1S1_1[0]+(Distance*PointS1)))){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         Print(((XOptionRate*LossIn)*LossIn));
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+(((XOptionRate*LossIn)*ProfitPercent)/100);
           Profit++;
           LossIn=1;
          }
          else{
           XStartDepo=XStartDepo-(XOptionRate*LossIn);
           Loss++;
           LossIn++;
           if(LossIn>Averaging){LossIn=1;}
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (AskS1<(ind_In1S1_2[0]-(Distance*PointS1)))){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         Print(((XOptionRate*LossIn)*LossIn));
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+(((XOptionRate*LossIn)*ProfitPercent)/100);
           Profit++;
           LossIn=1;
          }
          else{
           XStartDepo=XStartDepo-(XOptionRate*LossIn);
           Loss++;
           LossIn++;
           if(LossIn>Averaging){LossIn=1;}
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      摊平操作测试结果。 最终,成功。

      摊平 1

      摊平操作优化结果:

      优化结果 1

      一个更有趣的选择的结果,在亏损交易后乘以倍增率。 代码提供如下:

      //Sell (Put)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (BidS1>(ind_In1S1_1[0]+(Distance*PointS1)))){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         Print(((XOptionRate*LossIn)*LossIn));
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((((XOptionRate*LossIn)*LossIn)*ProfitPercent)/100);
           Profit++;
           LossIn=1;
          }
          else{
           XStartDepo=XStartDepo-((XOptionRate*LossIn)*LossIn);
           Loss++;
           LossIn++;
           if(LossIn>Averaging){LossIn=1;}
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (AskS1<(ind_In1S1_2[0]-(Distance*PointS1)))){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         Print(((XOptionRate*LossIn)*LossIn));
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((((XOptionRate*LossIn)*LossIn)*ProfitPercent)/100);
           Profit++;
           LossIn=1;
          }
          else{
           XStartDepo=XStartDepo-((XOptionRate*LossIn)*LossIn);
           Loss++;
           LossIn++;
           if(LossIn>Averaging){LossIn=1;}
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      经优化的有趣变体的结果:

      优化结果 2


      结束语

      从所做的所有工作中可以得出什么结论? 99% 的指标策略实际上不起作用。 通过稍微改变方法,可以制定良好的盈利策略。 有必要在入场之前检查所有东西。 与往常一样,MetaTrader 5 将帮助我们解决这个问题。顺便说一句,已有了 100% 盈利能力的选项,这可作为额外思考的养料。您可从附件中下载以智能系统形式实现的所有研究过的策略。


      本文由MetaQuotes Ltd译自俄文
      原文地址: https://www.mql5.com/ru/articles/12103

      附加的文件 |
      MQL5.zip (24.76 KB)
      创建综合性猫头鹰交易策略 创建综合性猫头鹰交易策略
      我的交易策略基于经典的基本面,以及在所有类型的市场中广泛采用的指标的改进。 这是一个现成的工具,允许您追随提议的新型盈利交易策略。
      MQL5 中的范畴论 (第 2 部分) MQL5 中的范畴论 (第 2 部分)
      范畴论是数学的一个多样化和不断扩展的分支,到目前为止,在 MQL5 社区中还相对难以发现。 这些系列文章旨在介绍和研究其一些概念,其总体目标是建立一个开放的函数库,吸引评论和研讨,同时希望在交易者的策略开发中进一步在运用这一非凡的领域。
      如何选择智能系统:拒绝一款交易机器人的 20 条强大准则 如何选择智能系统:拒绝一款交易机器人的 20 条强大准则
      本文尝试回答这个问题:我们如何选择正确的智能系统? 哪些最适合我们的投资组合,我们如何过滤市场上提供的庞大交易机器人列表? 本文将介绍二十条明确而强大的准则来拒绝一款智能系统。 每条提出的准则都将得到很好的解释,从而帮助您做出更持久的决定,并为您建立一个更有前途的智能系统集合,从而赚取利润。
      MQL5 酷宝书 — 宏观经济事件数据库 MQL5 酷宝书 — 宏观经济事件数据库
      本文讨论了基于 SQLite 引擎处理数据库的可能性。 形成的 CDatabase 类就是为了方便和有效地运用 OOP 原则。 随后它会参与宏观经济事件数据库的创建和管理。 本文提供了使用 CDatabase 类的多种方法的示例。