首页学院交易策略EA智能交易文章详细

错误146 ("交易作业忙") 和如何处理

外汇网2021-06-17 09:41:18 62
汇外网 - 全球专业的黄金外汇门户导航行情资讯网站

1.MetaTrader 4客户端中 "交易运转" 的概念

来自MetaEditor参考文档的一段话:

来自智能交易和脚本的交易,只能够供应一个并在交易作业中开启 (来自智能交易和脚本的自动交易作业)。这就是为何假使智能交易业务作业忙,其余的智能交易或脚本在此刻不能调用函数生成错误146 (ERR_TRADE_CONTEXT_BUSY)。

换句话说,只有一个智能交易(脚本)可以准时交易。所以其余智能交易试图开始交易将被错误 146停止。文章将令寻到困难的处理方案。

2. 函数 IsTradeAllowed()

这是最简单的方法是运用名称为IsTradeAllowed()的函数找出交易作业忙。

来自 MetaEditor参考文档的一段话:

"bool IsTradeAllowed()

假使智能交易允许交易,返回TRUE 。否则,返回FALSE。

这就代表着假使函数 IsTradeAllowed()返回TRUE只有一个可以试图交易。

在交易业务以前务必检测完成。

函数错误运用范例:
  1. int start()
  2. {
  3. // 检测交易作业
  4. if(!IsTradeAllowed())
  5. {
  6. // 假使函数IsTradeAllowed() 返回FALSE, 通知用户
  7. Print("交易作业忙。智能交易不能开仓!");

  8. // 而且中止交易业务。现在一个替克进入将从新开始
  9. // 进入
  10. return(-1);

  11. }
  12. else
  13. {
  14. // 假使函数IsTradeAllowed()返回TRUE,通知用户
  15. // 并继续运行
  16. Print("交易作业空闲!开始运转...");

  17. }
  18. // 当下检测市场
  19. ...
  20. // 计算止损和赢利水平和标准手
  21. ...
  22. // 开仓
  23. if(OrderSend(...) < 0)
  24. Alert("开仓错误 # ", GetLastError());

  25. return(0);

  26. }

复制代码

在这个范例中,在start() 函数开始时检测交易运转状态。这是个错误想法: 在我们的智能交易计算的时期内交易作业会被其余智能交易占领(需要进入市场,止损和赢利,标准手等等)。这些情形,接受开仓将失利。

函数适当应用范例:
  1. int start()
  2. {
  3. // 当下检测市场
  4. ...
  5. // 计算止损和赢利水平,标准手数
  6. ...
  7. // 当下检测交易作业
  8. if(!IsTradeAllowed())
  9. {
  10. Print("交易作业忙! 智能交易不能开仓!");

  11. return(-1);

  12. }
  13. else
  14. Print("交易作业正常! 试图开仓...");

  15. //假使检测正常,开仓
  16. if(OrderSend(...) < 0)
  17. Alert("错误开仓 # ", GetLastError());

  18. return(0);

  19. }

复制代码

在开仓以前立刻检测交易作业状态,而且或许在两种动作举动之间插入其余的智能交易 .

该种方法存在两点不足:

智能交易在接收到清晰结果检测状态的同期,将试图开始交易.

假使检测失利,智能交易将试图运用下一个替克交易; 将令延期.

处理第二种不足很简单:等候交易作业空闲即可.随后,在其余智能交易终结后,智能交易将立刻开始交易.

范比如下:
  1. int start()
  2. {
  3. // 当下检测能否进入市场
  4. ...
  5. // 计算赢利/止损水平和标准手数
  6. ...
  7. // 检测交易作业能否空闲
  8. if(!IsTradeAllowed())
  9. {
  10. Print("交易作业忙!等候空闲...");

  11. // 无限循环
  12. while(true)
  13. {
  14. // 假使智能交易被用户停止,停止业务
  15. if(IsStopped())
  16. {
  17. Print("智能交易被用停止!");

  18. return(-1);

  19. }
  20. // 假使交易作业空闲,开始交易
  21. if(IsTradeAllowed())
  22. {
  23. Print("交易作业空闲!");

  24. break;
  25. }
  26. // 假使没有条件设置循环, "等候" 0.1秒
  27. // 而且检测从新开始
  28. Sleep(100);

  29. }
  30. }
  31. else
  32. Print("交易作业空闲!试图开仓...");

  33. // 试图开仓
  34. if(OrderSend(...) < 0)
  35. Alert("错误开仓 # ", GetLastError());

  36. return(0);

  37. }

复制代码

该种情形显现,我们可以表示下方错误:

函数 IsTradeAllowed()不仅仅能够显现交易作业的状态,同样可以在无限循环中以“隐藏”开启/关闭;假使从图表中手动去除,将停止运转。

假使智能交易等候交易作业空闲,在这个时间里,价格会更改而且或许用这个价格交易 - 报告需要创下开仓从新计算。

纠正的错误代码将令是下方:
  1. // 智能交易等候交易的时间time (in seconds) whithin which the expert will wait until the trade
  2. // 交易作业空闲(假使忙)
  3. int MaxWaiting_sec = 30;
  4. int start()
  5. {
  6. // 当下检验能否进入市场
  7. ...
  8. // 计算止损,赢利和标准手数
  9. ...
  10. // 检测交易作业能否空闲
  11. if(!IsTradeAllowed())
  12. {
  13. int StartWaitingTime = GetTickCount();

  14. Print("交易作业忙!等候空闲...");

  15. // 无限循环
  16. while(true)
  17. {
  18. // 如过用户中止智能交易,停止业务
  19. if(IsStopped())
  20. {
  21. Print("智能交易被用户中止!");

  22. return(-1);

  23. }
  24. // 假使等候时间胜过命名变量
  25. // MaxWaiting_sec, 停止业务
  26. if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
  27. {
  28. Print("标准限定(" + MaxWaiting_sec + " sec)胜过!");

  29. return(-2);

  30. }
  31. // 假使交易作业空闲,
  32. if(IsTradeAllowed())
  33. {
  34. Print("交易作业空闲!");

  35. // 创下市场信息
  36. RefreshRates();

  37. // 从新计算止损和赢利水平
  38. ...
  39. // 离开循环状态并开始交易
  40. break;
  41. }
  42. // 如过没有条件离开,请 "等候"0.1秒
  43. // 而且从新开始检测
  44. Sleep(100);

  45. }
  46. }
  47. else
  48. Print("交易作业空闲!试图开仓...");

  49. // 试图开仓
  50. if(OrderSend(...) < 0)
  51. Alert("错误开仓 # ", GetLastError());

  52. return(0);

  53. }

复制代码

对于上面的范例,我们还可以添加:

创下市场信息(RefreshRates())而且从新计算止损和赢利水平

在胜过最大时间限定等候后 MaxWaiting_sec,智能交易将停止业务

以上的这些代码你已经可以运用到你的智能交易中。

当下让我们来谈谈在单独函数中的检测。这会简化在智能交易中的简化和用法。
  1. /////////////////////////////////////////////////////////////////////////////////
  2. // int _IsTradeAllowed( int MaxWaiting_sec = 30 )
  3. //
  4. // 函数检测交易作业状态. R返回代码:
  5. //1 - 交易作业空闲, 允许交易
  6. //0 - 交易作业忙,但是将空闲。创下市场信息后允许交易。
  7. // -1 - 交易作业忙,用户中止等候(智能交易从图表中删除,终端删除,图表周期/货币对更改等等)
  8. // -2 - 交易作业忙,高达最大等候限度 (MaxWaiting_sec).
  9. // 智能交易禁止交易(检测 "Allow live trading" ).
  10. //
  11. // MaxWaiting_sec - 函数将等候的时间
  12. // 直到交易作业控点(假使交易作业忙).默认值,30.
  13. /////////////////////////////////////////////////////////////////////////////////
  14. int _IsTradeAllowed(int MaxWaiting_sec = 30)
  15. {
  16. // 检测交易作业能否空闲
  17. if(!IsTradeAllowed())
  18. {
  19. int StartWaitingTime = GetTickCount();

  20. Print("交易作业忙!等候空闲...");

  21. // 无限循环
  22. while(true)
  23. {
  24. // 假使智能交易被用户中止,停止业务
  25. if(IsStopped())
  26. {
  27. Print("智能交易被用户中止!");

  28. return(-1);

  29. }
  30. // 假使等候时间多出指定
  31. // MaxWaiting_sec 变量 ,停止业务
  32. if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
  33. {
  34. Print("等候限度胜过 (" + MaxWaiting_sec + " сек.)!");

  35. return(-2);

  36. }
  37. // 假使交易作业空闲
  38. if(IsTradeAllowed())
  39. {
  40. Print("交易作业空闲!");

  41. return(0);

  42. }
  43. // 假使没有条件离开循环状态,请"等候" 0.1秒
  44. // 而且从新开始检测 Sleep(100);

  45. }
  46. }
  47. else
  48. {
  49. Print("交易作业空闲!");

  50. return(1);

  51. }
  52. }

复制代码

对于智能交易运用函数的一个模板:
  1. int start()
  2. {
  3. // 当下检测能否进入市场
  4. ...
  5. // 计算止损,赢利水平和标准手数
  6. ...
  7. // 检测交易作业能否空闲
  8. int TradeAllow = _IsTradeAllowed();

  9. if(TradeAllow < 0)
  10. {
  11. return(-1);

  12. }
  13. if(TradeAllow == 0)
  14. {
  15. RefreshRates();

  16. // 从新计算赢利水平和止损水平
  17. ...
  18. }
  19. // 开仓
  20. if(OrderSend(...) < 0)
  21. Alert("错误开仓 # ", GetLastError());

  22. return(0);

  23. }

复制代码

自此我们得出下方结论:

函数 IsTradeAllowed()很方便运用,而且对于两到三个智能交易同期运行同样适用。尽管存在一部分不足,当很多智能交易同期运行时会显现错误 146。假使"Allow live trading" 禁止,同样或许显现智能交易"hanging" 。

这就是为何我们考虑处理方案-整体变量作为一个 "信号旗"的原因。

3.客户终端的整体变量

首先是概念:

客户终端的整体变量是所有智能交易,脚本和指标的变量通道。这就代表着整体变量可以由一个智能交易创建,其余的智能交易同样可以运用 。

在 MQL4中给予了下方函数的整体变量:

GlobalVariableCheck() - 检测已经存在的整体变量

GlobalVariableDel() - 删除整体变量

GlobalVariableGet() - 获取整体变量值

GlobalVariableSet() - 创建或修改整体变量

GlobalVariableSetOnCondition() - 用户更改整体变量的指定值。不同于 GlobalVariableSet(),新值将被设定。这个函数是一个创建semaphore的核心。

GlobalVariablesDeleteAll() - 删除所有整体变量 (我们不敢想象它的实用性:))

为何运用 GlobalVariableSetOnCondition(),并非是联合函数 GlobalVariableGet()和 GlobalVariableSet()呢? 同样的原因:两个函数以前或许重合。如此其余的智能交易则不能插入。这就不运用的原因。

4. 信号旗的基本理念

智能交易准备交易应当检测信号旗的状态。假使信号旗表明 "红色" (整体变量 = 1),代表着其余智能交易在运行中,如此需要等候。假使表明“绿色” (整体变量 = 0),交易可以立刻开始 (但不要忘记对其余智能交易设定"红色")。

自此,我们创建了2个函数:一个设定"红色",其他设定“绿色”。实际上,他们相似。我们试图地策划了函数的次序(函数TradeIsBusy() 和函数TradeIsNotBusy()) 而且赋予实践。

5. 函数TradeIsBusy()

像我们前面所讲的,这个函数的首要功能是使智能交易等候直至“绿色”显现,而且将其切换成“红色”。此外,我们需要检验能否存在整体变量,而且执行创建。假使不存在。这个检测会从智能交易的函数init() 中执行逻辑性地实施。 但是随后或许被用户删除而且不会有智能交易执行运行。这就是我们将它放置到创建函数中的原因。

所有的这些整体变量的运行都需要伴随信息的展示和错误的生成。 应当记住"hanging":函数的业务时间需要限定。

这就是我们最终得到的:
  1. /////////////////////////////////////////////////////////////////////////////////
  2. // int TradeIsBusy( int MaxWaiting_sec = 30 )
  3. //
  4. // 函数还原TradeIsBusy 值0 - 1.
  5. // 在开启时假使TradeIsBusy = 1 ,函数等候直至 TradeIsBusy 为 0,
  6. // 随后还原
  7. // 假使TradeIsBusy没有任何整体变量,函数将令自己创建。
  8. // 返回代码:
  9. //1 - 成功编译。TradeIsBusy整体变量值指定为 1
  10. // -1 - TradeIsBusy = 1 函数在此刻开启,等候用户中止
  11. // (智能交易从图表中去除,终端被停止,图表周期/货币对被更改等等)
  12. // -2 - TradeIsBusy = 1 函数在此刻开启,等候限定超时
  13. // (MaxWaiting_sec)
  14. /////////////////////////////////////////////////////////////////////////////////
  15. int TradeIsBusy( int MaxWaiting_sec = 30 )
  16. {
  17. // 试探时,没有理由划分交易作业 - 导致终止
  18. // 此函数
  19. if(IsTesting())
  20. return(1);

  21. int _GetLastError = 0, StartWaitingTime = GetTickCount();

  22. //+------------------------------------------------------------------+
  23. //| 检测整体变量能否存在,假使没有,创建整体变量 |
  24. //+------------------------------------------------------------------+
  25. while(true)
  26. {
  27. // 假使智能交易被用户中止,停止业务
  28. if(IsStopped())
  29. {
  30. Print("智能交易被用户中止!");

  31. return(-1);

  32. }
  33. // 假使等候时间胜过指定限定时间
  34. // MaxWaiting_sec, 停止业务
  35. if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
  36. {
  37. Print("等候时间(" + MaxWaiting_sec + " sec)多出!");

  38. return(-2);

  39. }
  40. // 检测整体变量能否存在
  41. // 假使不存在离开循环模式,执行更改
  42. // TradeIsBusy值
  43. if(GlobalVariableCheck( "TradeIsBusy" ))
  44. break;
  45. else
  46. // 假使GlobalVariableCheck 返回FALSE, 代表着整体变量不存在或者
  47. // 检测中生成错误
  48. {
  49. _GetLastError = GetLastError();

  50. // 假使依然有错误信息表明,等候0.1 秒,
  51. //从新开始检测
  52. if(_GetLastError != 0)
  53. {
  54. Print("TradeIsBusy()-GlobalVariableCheck("TradeIsBusy")-Error #",
  55. _GetLastError );

  56. Sleep(100);

  57. continue;
  58. }
  59. }
  60. // 假使没有错误,代表着没有整体变量,试图创建
  61. // 整体变量
  62. //假使 the GlobalVariableSet > 0, 表明整体变量成功创建。
  63. // 离开函数
  64. if(GlobalVariableSet( "TradeIsBusy", 1.0 ) > 0 )
  65. return(1);

  66. else
  67. // 假使GlobalVariableSet返回值<= 0, 表明有错误
  68. // 在变量创建时生成
  69. {
  70. _GetLastError = GetLastError();

  71. //表明信息,等候0.1秒,又一次试图
  72. if(_GetLastError != 0)
  73. {
  74. Print("TradeIsBusy()-GlobalVariableSet("TradeIsBusy",0.0 )-Error #",
  75. _GetLastError );

  76. Sleep(100);

  77. continue;
  78. }
  79. }
  80. }
  81. //+----------------------------------------------------------------------------------+
  82. //| 假使函数高达实施点,表明整体变量 |
  83. //| 变量退出. |
  84. //| 等候TradeIsBusy 值形成0 而且更改 TradeIsBusy 值为 1 |
  85. //+----------------------------------------------------------------------------------+
  86. while(true)
  87. {
  88. // 假使智能交易被用户中止,停止业务
  89. if(IsStopped())
  90. {
  91. Print("智能交易被用户中止!");

  92. return(-1);

  93. }
  94. // 假使等候胜过限定时间
  95. // MaxWaiting_sec, 停止业务
  96. if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
  97. {
  98. Print("等候时间 (" + MaxWaiting_sec + " sec) 多出!");

  99. return(-2);

  100. }
  101. // 试图更改 TradeIsBusy的值从 0 - 1
  102. // 假使成功,离开函数返回1 ("成功编译")
  103. if(GlobalVariableSetOnCondition( "TradeIsBusy", 1.0, 0.0 ))
  104. return(1);

  105. else
  106. // 假使失利,或许致使失利的2个原因: TradeIsBusy = 1 (随后等候),
  107. // 错误生成(需要我们检测)
  108. {
  109. _GetLastError = GetLastError();

  110. // 假使依然存在错误,表明信息而且从新试图
  111. if(_GetLastError != 0)
  112. {
  113. Print("TradeIsBusy()-GlobalVariableSetOnCondition("TradeIsBusy",1.0,0.0 )-Error #",
  114. _GetLastError );

  115. continue;
  116. }
  117. }
  118. //假使没有错误,表明TradeIsBusy = 1 (其余智能交易在运行),
  119. // 随后表明信息而且等候...
  120. Comment("等候其余智能交易交易完成...");

  121. Sleep(1000);

  122. Comment("");

  123. }
  124. }

复制代码

在这里可以清楚地目睹:

检测整体变量能否存在,假使没有,执行创建

尝试更改整体变量的值从 0到 1;假使其值等于0,将开启。

函数可以运行 MaxWaiting_sec,而且不从图表中删除任何商品。

错误信息生成你可以在日志中寻到。

6. 函数TradeIsNotBusy()

函数TradeIsNotBusy 处理返回的困难:开启"绿色"。

这项功能没有限定而且不能由用户中止。方式非常简单:假使 "绿色" 关闭,智能交易将不会执行交易。

不会返回任何代码:结果只能被成功编译。

参见下面示例:
  1. /////////////////////////////////////////////////////////////////////////////////
  2. // void TradeIsNotBusy()
  3. //
  4. // 函数设置整体变量 TradeIsBusy 值等于0.
  5. // 假使TradeIsBusy不存在,函数创建。
  6. /////////////////////////////////////////////////////////////////////////////////
  7. void TradeIsNotBusy()
  8. {
  9. int _GetLastError;
  10. // 试探时,交易作业不被划分 - 导致终止
  11. // 此函数
  12. if(IsTesting())
  13. {
  14. return(0);

  15. }
  16. while(true)
  17. {
  18. // 假使智能交易被用户中止,停止业务
  19. if(IsStopped())
  20. {
  21. Print("智能交易被用户中止!");

  22. return(-1);

  23. }
  24. // 试图设置整变量值= 0 (创建整体变量)
  25. // 假使 GlobalVariableSet 返回值 > 0, 表明成功
  26. // 离开函数
  27. if(GlobalVariableSet( "TradeIsBusy", 0.0 ) > 0)
  28. return(1);

  29. else
  30. // 假使GlobalVariableSet 返回值 <= 0, 表明错误生成
  31. // 表明信息,等候而且试图从新开始
  32. {
  33. _GetLastError = GetLastError();

  34. if(_GetLastError != 0 )
  35. Print("TradeIsNotBusy()-GlobalVariableSet("TradeIsBusy",0.0)-Error #",
  36. _GetLastError );

  37. }
  38. Sleep(100);

  39. }
  40. }

复制代码

7. 在智能交易中的结合运用

当下我们有 3 个函数可以通向交易作业。使他们简单地结合到智能交易中,我们可以创建一个 TradeContext.mq4 文件而且运用 #include (获取文件)。

这是一个运用函数 TradeIsBusy()和函数TradeIsNotBusy()的模板:
  1. #include
  2. int start()
  3. {
  4. // 当下检测能否进入市场
  5. ...
  6. // 计算止损水平,赢利水平和标准手数
  7. ...
  8. // 等候交易作业空闲而且进入(假使生成错误,
  9. // 离开)
  10. if(TradeIsBusy() < 0)
  11. return(-1);

  12. // 创下市场信息
  13. RefreshRates();

  14. // 从新计算止损和赢利水平
  15. ...
  16. // 开仓
  17. if(OrderSend(...) < 0)
  18. {
  19. Alert("错误开仓位置 # ", GetLastError());

  20. }
  21. //设置交易作业空闲
  22. TradeIsNotBusy();

  23. return(0);

  24. }

复制代码

在运用函数 TradeIsBusy()和函数 TradeIsNotBusy()时,只有一个困难能够造成: 假使在交易作业变成忙后,智能交易从图表中去除,变量 TradeIsBusy将令等于 1。其余的智能交易将不或许运行。

这个困难可以很轻松地处理: 在智能交易在图表中交易时,不从图表中去除;)

在终端停歇时, TradeIsBusy值也有机会不等于0。该种情形,函数 TradeIsNotBusy()从智能交易的函数 init() 被运用。

诚然,在任什么时候间内可以手动更改变量值: 终端内的F3键 。不提倡执行运用。
标签:

随机快审展示
加入快审,优先展示

加入VIP