MAGICNUMBER: 定单的“魔法“识别符

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

121

主题

5

回帖

503

积分

实习版主

积分
503
来源: 2019-10-28 22:51:59 显示全部楼层 |阅读模式
在运用MT4进行量化交易中,如果一个账户中多个策略同时运行,或者一个策略在多品种中运行,如何管理这些策略,魔法号是一个比较好的方法。那么什么是魔法号吗?
下面我们看一下下单函数

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)

magic - 定单魔法数字。可以使用指定识别符。
下单函数中的magic参数既是魔法号。
即,当定单被放置时,可以给定单指定独有的数字。这个数字将用于区分其他定单。当手动交易时,不使用(尽可能)这个特性,但是在智能交易(自动交易)运作时,此特性是不可替代的。

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

  1. //+------------------------------------------------------------------+
  2. //|                                                          魔法号.mq4 |
  3. //|                        Copyright 2018, MetaQuotes Software Corp. |
  4. //|                                          [url]https://www.geekquant.com[/url] |
  5. //+------------------------------------------------------------------+
  6. #property copyright "Copyright 2018, MetaQuotes Software Corp."
  7. #property link      "https://www.geekquant.com"
  8. #property version   "1.00"
  9. #property strict
  10. //+------------------------------------------------------------------+
  11. //| Expert initialization function                                   |
  12. //+------------------------------------------------------------------+
  13. int OnInit()
  14.   {
  15. //--- create timer
  16.    EventSetTimer(60);
  17.    
  18. //---
  19.    return(INIT_SUCCEEDED);
  20.   }
  21. //+------------------------------------------------------------------+
  22. //| Expert deinitialization function                                 |
  23. //+------------------------------------------------------------------+
  24. void OnDeinit(const int reason)
  25.   {
  26. //--- destroy timer
  27.    EventKillTimer();
  28.    
  29.   }
  30. //+------------------------------------------------------------------+
  31. //| Expert tick function                                             |
  32. //+------------------------------------------------------------------+


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

  41.     int _GetLastError = 0, _OrdersTotal = OrdersTotal();
  42.     //---- 在开仓中搜索
  43.     for ( int z = _OrdersTotal - 1; z >= 0; z -- )
  44.     {
  45.         //---- 如果在选择仓位中生成错误,转到下一步
  46.         if ( !OrderSelect( z, SELECT_BY_POS ) )
  47.         {
  48.             _GetLastError = GetLastError();
  49.             Print( "OrderSelect( ", z, ", SELECT_BY_POS ) - Error #", _GetLastError );
  50.             continue;
  51.         }

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

  54.         //---- 如果开仓为BUY,
  55.         if ( OrderType() == OP_BUY )
  56.         {
  57.             //---- 如果 MACD指标看到的零线从上至下,
  58.             if ( NormalizeDouble( MACD_1, Digits + 1 ) <  0.0 &&
  59.                   NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0    )
  60.             {
  61.                 //---- 平仓
  62.                 if ( !OrderClose( OrderTicket(), OrderLots(), Bid, 5, Green ) )
  63.                 {
  64.                     _GetLastError = GetLastError();
  65.                     Alert( "错误 OrderClose # ", _GetLastError );
  66.                     return(-1);
  67.                 }
  68.             }
  69.             //---- 如果警报没有改变,退出: 开仓尚早
  70.             else return(0);
  71.         }
  72.         //---- 如果开仓位SELL,
  73.         if ( OrderType() == OP_SELL )
  74.         {
  75.             //----如果MACD指标看到零线从下到上,
  76.             if ( NormalizeDouble( MACD_1, Digits + 1 ) >  0.0 &&
  77.                   NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0    )
  78.             {
  79.                 //---- 平仓
  80.                 if ( !OrderClose( OrderTicket(), OrderLots(), Ask, 5, Red ) )
  81.                 {
  82.                     _GetLastError = GetLastError();
  83.                     Alert( "错误 OrderClose # ", _GetLastError );
  84.                     return(-1);
  85.                 }
  86.             }
  87.             //---- 如果警报没有改变,退出:开仓尚早
  88.             else return(0);
  89.         }
  90.     }

  91. //+------------------------------------------------------------------+
  92. //| 如果达到此点,没有仓位开仓                            |
  93. //| 检测是否仍有开仓的可能                                  |
  94. //+------------------------------------------------------------------+

  95.     //---- 如果MACD 指标看到零线从下到上,
  96.     if ( NormalizeDouble( MACD_1, Digits + 1 ) >  0.0 &&
  97.           NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0    )
  98.     {
  99.         //---- 开BUY仓
  100.         if ( OrderSend( Symbol(), OP_BUY, 0.1, Ask, 5, 0.0, 0.0, "MACD_test", 0, 0, Green ) < 0 )
  101.         {
  102.             _GetLastError = GetLastError();
  103.             Alert( "错误OrderSend # ", _GetLastError );
  104.             return(-1);
  105.         }
  106.         return(0);
  107.     }
  108.     //----如果MACD 指标看到零线从上至下,
  109.     if ( NormalizeDouble( MACD_1, Digits + 1 ) <  0.0 &&
  110.           NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0    )
  111.     {
  112.         //---- 开 SELL 仓
  113.         if ( OrderSend( Symbol(), OP_SELL, 0.1, Bid, 5, 0.0, 0.0, "MACD_test", 0, 0, Red ) < 0 )
  114.         {
  115.             _GetLastError = GetLastError();
  116.             Alert( "错误OrderSend # ", _GetLastError );
  117.             return(-1);
  118.         }
  119.         return(0);
  120.     }

  121.     return(0);
  122. }
复制代码


以上代码在运行的时候是没有问题的,但是在执行之后,如果同时自己手动进行交易,这个时候程序就没办法识别是手动单子还是程序下的单子,这个时候就需要对单子进行处理和识别,如何做那,其实就是加一个魔法号数字即可。


  1. //+------------------------------------------------------------------+
  2. //|                                                          魔法号.mq4 |
  3. //|                        Copyright 2018, MetaQuotes Software Corp. |
  4. //|                                          https://www.geekquant.com |
  5. //+------------------------------------------------------------------+
  6. #property copyright "Copyright 2018, MetaQuotes Software Corp."
  7. #property link      "https://www.geekquant.com"
  8. #property version   "1.00"
  9. #property strict

  10. extern int Expert_ID = 1234;
  11. //+------------------------------------------------------------------+
  12. //| Expert initialization function                                   |
  13. //+------------------------------------------------------------------+
  14. int OnInit()
  15.   {
  16. //--- create timer
  17.    EventSetTimer(60);
  18.    
  19. //---
  20.    return(INIT_SUCCEEDED);
  21.   }
  22. //+------------------------------------------------------------------+
  23. //| Expert deinitialization function                                 |
  24. //+------------------------------------------------------------------+
  25. void OnDeinit(const int reason)
  26.   {
  27. //--- destroy timer
  28.    EventKillTimer();
  29.    
  30.   }
  31. //+------------------------------------------------------------------+
  32. //| Expert tick function                                             |
  33. //+------------------------------------------------------------------+


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

  42.     int _GetLastError = 0, _OrdersTotal = OrdersTotal();
  43.     //---- 在全部开仓中搜索
  44.     for ( int z = _OrdersTotal - 1; z >= 0; z -- )
  45.     {
  46.         //---- 如果在搜索仓位中生成错误。转到下一步
  47.         if ( !OrderSelect( z, SELECT_BY_POS ) )
  48.         {
  49.             _GetLastError = GetLastError();
  50.             Print( "OrderSelect( ", z, ", SELECT_BY_POS ) -错误 #", _GetLastError );
  51.             continue;
  52.         }

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

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

  57.         //---- 如果开BUY仓,
  58.         if ( OrderType() == OP_BUY )
  59.         {
  60.             //---- 如果MACD 指标看到零线从上到下,
  61.             if ( NormalizeDouble( MACD_1, Digits + 1 ) <  0.0 &&
  62.                   NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0    )
  63.             {
  64.                 //---- 平仓
  65.                 if ( !OrderClose( OrderTicket(), OrderLots(), Bid, 5, Green ) )
  66.                 {
  67.                     _GetLastError = GetLastError();
  68.                     Alert( "错误 OrderClose # ", _GetLastError );
  69.                     return(-1);
  70.                 }
  71.             }
  72.             //---- 如果警报没有改变, 退出: 开仓尚早
  73.             else
  74.             { return(0); }
  75.         }
  76.         //---- 如果开SELL仓,
  77.         if ( OrderType() == OP_SELL )
  78.         {
  79.             //---- 如果MACD指标看到零线从下到上,
  80.             if ( NormalizeDouble( MACD_1, Digits + 1 ) >  0.0 &&
  81.                   NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0    )
  82.             {
  83.                 //---- 平仓
  84.                 if ( !OrderClose( OrderTicket(), OrderLots(), Ask, 5, Red ) )
  85.                 {
  86.                     _GetLastError = GetLastError();
  87.                     Alert( "错误 OrderClose № ", _GetLastError );
  88.                     return(-1);
  89.                 }
  90.             }
  91.             //---- 如果警报没有改变,退出: 开仓尚早
  92.             else return(0);
  93.         }
  94.     }

  95. //+------------------------------------------------------------------+
  96. //| 如果执行达到此点,没有仓位开仓                          |
  97. //| 检测是否有可能开仓                                   |
  98. //+------------------------------------------------------------------+

  99.     //---- 如果MACD 指标看到零线从下到上,
  100.     if ( NormalizeDouble( MACD_1, Digits + 1 ) >  0.0 &&
  101.           NormalizeDouble( MACD_2, Digits + 1 ) <= 0.0    )
  102.     {
  103.         //---- 开BUY仓
  104.         if ( OrderSend( Symbol(), OP_BUY, 0.1, Ask, 5, 0.0, 0.0, "MACD_test",
  105.               Expert_ID, 0, Green ) < 0 )
  106.         {
  107.             _GetLastError = GetLastError();
  108.             Alert( "错误OrderSend # ", _GetLastError );
  109.             return(-1);
  110.         }
  111.         return(0);
  112.     }
  113.     //---- 如果MACD 指标看到零线从上至下,
  114.     if ( NormalizeDouble( MACD_1, Digits + 1 ) <  0.0 &&
  115.           NormalizeDouble( MACD_2, Digits + 1 ) >= 0.0    )
  116.     {
  117.         //---- 开SELL仓
  118.         if ( OrderSend( Symbol(), OP_SELL, 0.1, Bid, 5, 0.0, 0.0, "MACD_test",
  119.               Expert_ID, 0, Red ) < 0 )
  120.         {
  121.             _GetLastError = GetLastError();
  122.             Alert( "错误 OrderSend # ", _GetLastError );
  123.             return(-1);
  124.         }
  125.         return(0);
  126.     }

  127.     return(0);
  128. }

复制代码



添加魔法号之后,当智能交易运行时,用户可以手动开仓。智能交易将不会干涉。


多个相同的智能交易在一种货币对的不同图表上
存在这样的状况,相同的智能交易必须在相同货币对的图表中运行,但是需要不同的时间周期。例如,如果我们尝试添加我们的智能交易同时添加到 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. //+------------------------------------------------------------------+
  2. //|                                                          魔法号.mq4 |
  3. //|                        Copyright 2018, MetaQuotes Software Corp. |
  4. //|                                          https://www.geekquant.com |
  5. //+------------------------------------------------------------------+
  6. #property copyright "Copyright 2018, MetaQuotes Software Corp."
  7. #property link      "https://www.geekquant.com"
  8. #property version   "1.00"
  9. #property strict

  10. extern int Expert_ID = 1234;
  11. int _MagicNumber = 0;

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

  28.     return(0);
  29. }

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

  38.     int _GetLastError = 0, _OrdersTotal = OrdersTotal();
  39.     //---- 在全部开仓中搜索
  40.     for ( int z = _OrdersTotal - 1; z >= 0; z -- )
  41.     {
  42.         //---- 如果在搜索过程中生成错误。转到下一步
  43.         if ( !OrderSelect( z, SELECT_BY_POS ) )
  44.         {
  45.             _GetLastError = GetLastError();
  46.             Print( "OrderSelect( ", z, ", SELECT_BY_POS ) - 错误#", _GetLastError );
  47.             continue;
  48.         }

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

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

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

  90. //+------------------------------------------------------------------+
  91. //| 如果执行达到此点,没有仓位开仓                          |
  92. //| 检测是否仍有可能开仓                                  |
  93. //+------------------------------------------------------------------+

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

  122.     return(0);
  123. }
复制代码

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

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

使用以上代码,用户能够改善他的智能交易并且“教会”智能交易区分自己的仓位和他人的仓位。







回复

使用道具 举报

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