【MQL4学习】AGICNUMBER: 定单的“魔法“识别符

0
回复
4813
查看
[复制链接]

41

主题

32

回帖

248

积分

中级会员

积分
248
来源: 2019-10-14 23:14:13 显示全部楼层 |阅读模式
1. 历史
在МТ3中,开仓的管理是非常费时的。交易者在处理开仓和平仓列表时,设置执行的工具是限定的。在区分“自己”和“他人”仓位时,方法非常复杂。在 МТ4中,状况有了明显的改变。现在,交易者可以使用多种函数来管理开仓,挂单并且获取平仓信息。
以MagicNumber命名的特殊参数被添加到定单识别符中。这个参数就是我们文章中将提及到的主题。

2.什么是 MagicNumber?
MQL4 参考:

  1. int OrderSend( string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, string comment=NULL, int magic=0, datetime expiration=0, color arrow_color=CLR_NONE)

  2. magic - 定单魔法数字。可以使用指定识别符。
复制代码

即,当定单被放置时,可以给定单指定独有的数字。这个数字将用于区分其他定单。当手动交易时,不使用(尽可能)这个特性,但是在智能交易(自动交易)运作时,此特性是不可替代的。

范例1: 在客户端内交易者和智能交易同时运行。
任务: 智能交易的运行必须按照它自己的形式计算,对于手动开仓不会干涉。
解决: 开仓的智能交易必须指定独特的MagicNumber(零除外)。接下来的日子里,智能交易只会管理提前设定的 MagicNumber 的定单。
范例 2: 在客户端内两个不同计算方法的智能交易同时运行。
任务: 智能交易只管理自己的定单。.
解决: 当开仓时,每个智能交易必须使用自己的 MagicNumber(零除外)。接下来的日子里,智能交易只会管理提前设定的MagicNumber的定单。
范例 3: 在客户端内几个智能交易,交易者和协助智能交易执行的不标准追踪止损同时运行。
任务: 交易的智能交易必须按照自己的形式计算,并且不干涉手动开仓。协助智能交易执行的追踪止损可以在手动开仓处修改,但是其他智能交易不能够开仓。
解决: 智能交易必须使用独有的MagicNumbers并且管理自己的仓位。协助智能交易修改的这些仓位,其 MagicNumber等于 0。
以上三个范例都很现实,用户可以提前解决问题。在这三个范例情况中,都是使用MagicNumber来解决问题的。这不是唯一解决问题的途径,但是最简单的途径。
3. 实践
现在让我们来解决特殊的任务:创建智能交易只管理自己的仓位,不理睬手动仓位和其他智能交易。
首先我们编写一个简单的智能交易,当 MACD 指标零线时,智能交易得到信号开仓。智能交易将会运行如下:

  1. int start()
  2. {
  3.     //---- 记住将要分析的指标值
  4.     //---- 注意:我们使用第一个和第二个柱。可以是每日的 1-bar 。
  5.     //---- (即., 信号晚些显现), 但是保护反复开仓和平仓
  6.     //---- 在柱内仓位的
  7.     double MACD_1 = iMACD( Symbol(), 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1 );
  8.     double MACD_2 = iMACD( Symbol(), 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 2 );

  9.     int _GetLastError = 0, _OrdersTotal = OrdersTotal();
  10.     //---- 在开仓中搜索
  11.     for ( int z = _OrdersTotal - 1; z >= 0; z -- )
  12.     {
  13.         //---- 如果在选择仓位中生成错误,转到下一步
  14.         if ( !OrderSelect( z, SELECT_BY_POS ) )
  15.         {
  16.             _GetLastError = GetLastError();
  17.             Print( "OrderSelect( ", z, ", SELECT_BY_POS ) - Error #", _GetLastError );
  18.             continue;
  19.         }

  20.         //---- 如果开仓不是当前货币对,略过
  21.         if ( OrderSymbol() != Symbol() ) continue;

  22.         //---- 如果开仓为BUY,
  23.         if ( OrderType() == OP_BUY )
  24.         {
  25.             //---- 如果 MACD指标看到的零线从上至下,
  26.             if ( NormalizeDouble( MACD_1, Digits + 1 ) <  0.0 &&
  27.                   NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0    )
  28.             {
  29.                 //---- 平仓
  30.                 if ( !OrderClose( OrderTicket(), OrderLots(), Bid, 5, Green ) )
  31.                 {
  32.                     _GetLastError = GetLastError();
  33.                     Alert( "错误 OrderClose # ", _GetLastError );
  34.                     return(-1);
  35.                 }
  36.             }
  37.             //---- 如果警报没有改变,退出: 开仓尚早
  38.             else return(0);
  39.         }
  40.         //---- 如果开仓位SELL,
  41.         if ( OrderType() == OP_SELL )
  42.         {
  43.             //----如果MACD指标看到零线从下到上,
  44.             if ( NormalizeDouble( MACD_1, Digits + 1 ) >  0.0 &&
  45.                   NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0    )
  46.             {
  47.                 //---- 平仓
  48.                 if ( !OrderClose( OrderTicket(), OrderLots(), Ask, 5, Red ) )
  49.                 {
  50.                     _GetLastError = GetLastError();
  51.                     Alert( "错误 OrderClose # ", _GetLastError );
  52.                     return(-1);
  53.                 }
  54.             }
  55.             //---- 如果警报没有改变,退出:开仓尚早
  56.             else return(0);
  57.         }
  58.     }

  59. //+------------------------------------------------------------------+
  60. //| 如果达到此点,没有仓位开仓                            |
  61. //| 检测是否仍有开仓的可能                                  |
  62. //+------------------------------------------------------------------+

  63.     //---- 如果MACD 指标看到零线从下到上,
  64.     if ( NormalizeDouble( MACD_1, Digits + 1 ) >  0.0 &&
  65.           NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0    )
  66.     {
  67.         //---- 开BUY仓
  68.         if ( OrderSend( Symbol(), OP_BUY, 0.1, Ask, 5, 0.0, 0.0, "MACD_test", 0, 0, Green ) < 0 )
  69.         {
  70.             _GetLastError = GetLastError();
  71.             Alert( "错误OrderSend # ", _GetLastError );
  72.             return(-1);
  73.         }
  74.         return(0);
  75.     }
  76.     //----如果MACD 指标看到零线从上至下,
  77.     if ( NormalizeDouble( MACD_1, Digits + 1 ) <  0.0 &&
  78.           NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0    )
  79.     {
  80.         //---- 开 SELL 仓
  81.         if ( OrderSend( Symbol(), OP_SELL, 0.1, Bid, 5, 0.0, 0.0, "MACD_test", 0, 0, Red ) < 0 )
  82.         {
  83.             _GetLastError = GetLastError();
  84.             Alert( "错误OrderSend # ", _GetLastError );
  85.             return(-1);
  86.         }
  87.         return(0);
  88.     }

  89.     return(0);
  90. }
复制代码


我们将按照以下方法让它管理自己的仓位:
  • 以Expert_ID 命名添加外部变量协助智能交易开仓来改变 MagicNumber 值
  • 在函数OrderSelect()选择仓位之后,对编译Expert_ID变量所选定单的MagicNumber 添加检测
  • 在开仓期间,我们将在MagicNumber处写下 Expert_ID的值替换 0
考虑上面的变化,代码将显现如下:
  1. extern int Expert_ID = 1234;

  2. int start()
  3. {
  4.     //---- 记住将要分析的指标值
  5.     //---- 注意:我们使用第一个和第二个柱。可以是每日的 1-bar 。
  6.     //---- (即., 信号晚些显现), 但是保护反复开仓和平仓
  7.     //---- 在柱内仓位的
  8.     double MACD_1 = iMACD( Symbol(), 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1 );
  9.     double MACD_2 = iMACD( Symbol(), 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 2 );

  10.     int _GetLastError = 0, _OrdersTotal = OrdersTotal();
  11.     //---- 在全部开仓中搜索
  12.     for ( int z = _OrdersTotal - 1; z >= 0; z -- )
  13.     {
  14.         //---- 如果在搜索仓位中生成错误。转到下一步
  15.         if ( !OrderSelect( z, SELECT_BY_POS ) )
  16.         {
  17.             _GetLastError = GetLastError();
  18.             Print( "OrderSelect( ", z, ", SELECT_BY_POS ) -错误 #", _GetLastError );
  19.             continue;
  20.         }

  21.         //---- 如果平仓仓位不是当前货币对,略过
  22.         if ( OrderSymbol() != Symbol() ) continue;

  23.         //---- 如果MagicNumber 不等于Expert_ID, 忽略此仓位
  24.         if ( OrderMagicNumber() != Expert_ID ) continue;

  25.         //---- 如果开BUY仓,
  26.         if ( OrderType() == OP_BUY )
  27.         {
  28.             //---- 如果MACD 指标看到零线从上到下,
  29.             if ( NormalizeDouble( MACD_1, Digits + 1 ) <  0.0 &&
  30.                   NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0    )
  31.             {
  32.                 //---- 平仓
  33.                 if ( !OrderClose( OrderTicket(), OrderLots(), Bid, 5, Green ) )
  34.                 {
  35.                     _GetLastError = GetLastError();
  36.                     Alert( "错误 OrderClose # ", _GetLastError );
  37.                     return(-1);
  38.                 }
  39.             }
  40.             //---- 如果警报没有改变, 退出: 开仓尚早
  41.             else
  42.             { return(0); }
  43.         }
  44.         //---- 如果开SELL仓,
  45.         if ( OrderType() == OP_SELL )
  46.         {
  47.             //---- 如果MACD指标看到零线从下到上,
  48.             if ( NormalizeDouble( MACD_1, Digits + 1 ) >  0.0 &&
  49.                   NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0    )
  50.             {
  51.                 //---- 平仓
  52.                 if ( !OrderClose( OrderTicket(), OrderLots(), Ask, 5, Red ) )
  53.                 {
  54.                     _GetLastError = GetLastError();
  55.                     Alert( "错误 OrderClose № ", _GetLastError );
  56.                     return(-1);
  57.                 }
  58.             }
  59.             //---- 如果警报没有改变,退出: 开仓尚早
  60.             else return(0);
  61.         }
  62.     }

  63. //+------------------------------------------------------------------+
  64. //| 如果执行达到此点,没有仓位开仓                          |
  65. //| 检测是否有可能开仓                                   |
  66. //+------------------------------------------------------------------+

  67.     //---- 如果MACD 指标看到零线从下到上,
  68.     if ( NormalizeDouble( MACD_1, Digits + 1 ) >  0.0 &&
  69.           NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0    )
  70.     {
  71.         //---- 开BUY仓
  72.         if ( OrderSend( Symbol(), OP_BUY, 0.1, Ask, 5, 0.0, 0.0, "MACD_test",
  73.               Expert_ID, 0, Green ) < 0 )
  74.         {
  75.             _GetLastError = GetLastError();
  76.             Alert( "错误OrderSend # ", _GetLastError );
  77.             return(-1);
  78.         }
  79.         return(0);
  80.     }
  81.     //---- 如果MACD 指标看到零线从上至下,
  82.     if ( NormalizeDouble( MACD_1, Digits + 1 ) <  0.0 &&
  83.           NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0    )
  84.     {
  85.         //---- 开SELL仓
  86.         if ( OrderSend( Symbol(), OP_SELL, 0.1, Bid, 5, 0.0, 0.0, "MACD_test",
  87.               Expert_ID, 0, Red ) < 0 )
  88.         {
  89.             _GetLastError = GetLastError();
  90.             Alert( "错误 OrderSend # ", _GetLastError );
  91.             return(-1);
  92.         }
  93.         return(0);
  94.     }

  95.     return(0);
  96. }
复制代码
现在,当智能交易运行时,用户可以手动开仓。智能交易将不会干涉。

4. 多个相同的智能交易在一种货币对的不同图表上
存在这样的状况,相同的智能交易必须在相同货币对的图表中运行,但是需要不同的时间周期。例如,如果我们尝试添加我们的智能交易同时添加到 EURUSD, H1图表和 EURUSD, M30图表,他们将会相互影响:每个都会“考虑”开仓并且会默认管理。
这个问题可以通过 Expert_ID 一个协调另一个的方式解决。但是这羊不是很方便。如果很多智能交易在运行,他们的ID必然会混乱。
解决这个问题我们需要以 MagicNumber 值作为图表周期。怎样执行呢?如果我们添加图表周期到 Expert_ID, 可能2个不同的智能交易在2个不同的图表上生成相同的 MagicNumber。
所以我们最好用 Expert_ID值乘以 10 并且把图表周期(代码从1 到 9, 精确值)放置到最后  。
如下图表:
  1. int Period_ID = 0;
  2.     switch ( Period() )
  3.     {
  4.         case PERIOD_MN1: Period_ID = 9; break;
  5.         case PERIOD_W1:  Period_ID = 8; break;
  6.         case PERIOD_D1:  Period_ID = 7; break;
  7.         case PERIOD_H4:  Period_ID = 6; break;
  8.         case PERIOD_H1:  Period_ID = 5; break;
  9.         case PERIOD_M30: Period_ID = 4; break;
  10.         case PERIOD_M15: Period_ID = 3; break;
  11.         case PERIOD_M5:  Period_ID = 2; break;
  12.         case PERIOD_M1:  Period_ID = 1; break;
  13.     }
  14.     _MagicNumber = Expert_ID * 10 + Period_ID;
复制代码

现在添加这个代码智能交易的 init()函数并且用 Expert_ID替换MagicNumber。

最终版本的智能交易如下:
  1. extern int Expert_ID = 1234;
  2. int _MagicNumber = 0;

  3. int init()
  4. {
  5.     int Period_ID = 0;
  6.     switch ( Period() )
  7.     {
  8.         case PERIOD_MN1: Period_ID = 9; break;
  9.         case PERIOD_W1:  Period_ID = 8; break;
  10.         case PERIOD_D1:  Period_ID = 7; break;
  11.         case PERIOD_H4:  Period_ID = 6; break;
  12.         case PERIOD_H1:  Period_ID = 5; break;
  13.         case PERIOD_M30: Period_ID = 4; break;
  14.         case PERIOD_M15: Period_ID = 3; break;
  15.         case PERIOD_M5:  Period_ID = 2; break;
  16.         case PERIOD_M1:  Period_ID = 1; break;
  17.     }
  18.     _MagicNumber = Expert_ID * 10 + Period_ID;

  19.     return(0);
  20. }

  21. int start()
  22. {
  23.     //---- 记住将要分析的指标值
  24.     //---- 注意:我们使用第一个和第二个柱。可以是每日的 1-bar 。
  25.     //---- (即., 信号晚些显现), 但是保护反复开仓和平仓
  26.     //---- 在柱内仓位的
  27.     double MACD_1 = iMACD( Symbol(), 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1 );
  28.     double MACD_2 = iMACD( Symbol(), 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 2 );

  29.     int _GetLastError = 0, _OrdersTotal = OrdersTotal();
  30.     //---- 在全部开仓中搜索
  31.     for ( int z = _OrdersTotal - 1; z >= 0; z -- )
  32.     {
  33.         //---- 如果在搜索过程中生成错误。转到下一步
  34.         if ( !OrderSelect( z, SELECT_BY_POS ) )
  35.         {
  36.             _GetLastError = GetLastError();
  37.             Print( "OrderSelect( ", z, ", SELECT_BY_POS ) - 错误#", _GetLastError );
  38.             continue;
  39.         }

  40.         //---- 如果开仓仓位不是当前货币对,忽略
  41.         if ( OrderSymbol() != Symbol() ) continue;

  42.         //---- 如果MagicNumber 不等于 _MagicNumber, 忽略此仓位
  43.         if ( OrderMagicNumber() != _MagicNumber ) continue;

  44.         //----如果开BUY仓,
  45.         if ( OrderType() == OP_BUY )
  46.         {
  47.             //---- 如果MACD指标看见零线从上至下,
  48.             if ( NormalizeDouble( MACD_1, Digits + 1 ) <  0.0 &&
  49.                   NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0    )
  50.             {
  51.                 //---- 平仓
  52.                 if ( !OrderClose( OrderTicket(), OrderLots(), Bid, 5, Green ) )
  53.                 {
  54.                     _GetLastError = GetLastError();
  55.                     Alert( "错误 OrderClose # ", _GetLastError );
  56.                     return(-1);
  57.                 }
  58.             }
  59.             //---- 如果警报没有改变,停止: 开新仓位尚早
  60.             else return(0);
  61.         }
  62.         //---- 如果开SELL仓,
  63.         if ( OrderType() == OP_SELL )
  64.         {
  65.             //---- 如果MACD指标看见零线从下到上,
  66.             if ( NormalizeDouble( MACD_1, Digits + 1 ) >  0.0 &&
  67.                   NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0    )
  68.             {
  69.                 //----平仓
  70.                 if ( !OrderClose( OrderTicket(), OrderLots(), Ask, 5, Red ) )
  71.                 {
  72.                     _GetLastError = GetLastError();
  73.                     Alert( "错误OrderClose № ", _GetLastError );
  74.                     return(-1);
  75.                 }
  76.             }
  77.             //---- 如果警报没有改变, 停止: 开新仓位尚早
  78.             else return(0);
  79.         }
  80.     }

  81. //+------------------------------------------------------------------+
  82. //| 如果执行达到此点,没有仓位开仓                          |
  83. //| 检测是否仍有可能开仓                                  |
  84. //+------------------------------------------------------------------+

  85.     //---- 如果MACD 指标看见零线从下到上,
  86.     if ( NormalizeDouble( MACD_1, Digits + 1 ) >  0.0 &&
  87.           NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0    )
  88.     {
  89.         //---- 开 BUY 仓
  90.         if ( OrderSend( Symbol(), OP_BUY, 0.1, Ask, 5, 0.0, 0.0, "MACD_test",
  91.               _MagicNumber, 0, Green ) < 0 )
  92.         {
  93.             _GetLastError = GetLastError();
  94.             Alert( "错误 OrderSend # ", _GetLastError );
  95.             return(-1);
  96.         }
  97.         return(0);
  98.     }
  99.     //---- 如果MACD 指标看到零线从上至下,
  100.     if ( NormalizeDouble( MACD_1, Digits + 1 ) <  0.0 &&
  101.           NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0    )
  102.     {
  103.         //---- 开 SELL 仓
  104.         if ( OrderSend( Symbol(), OP_SELL, 0.1, Bid, 5, 0.0, 0.0, "MACD_test",
  105.               _MagicNumber, 0, Red ) < 0 )
  106.         {
  107.             _GetLastError = GetLastError();
  108.             Alert( "错误 OrderSend # ", _GetLastError );
  109.             return(-1);
  110.         }
  111.         return(0);
  112.     }

  113.     return(0);
  114. }
复制代码

这样的显示智能交易可以在不同周期的几个图表中使用。

如果需要在相同时间周期和货币对的图表(例如, EURUSD H1 和EURUSD H4)上开启两个智能交易, 此Expert_ID 变量值将被改变。但是这种情况很罕见。

使用以上代码,用户能够改善他的智能交易并且“教会”智能交易区分自己的仓位和他人的仓位。
瑞士法郎-瑞郎-硬币.jpg


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 免费注册
关注微信