1.MetaTrader 4客户端中 "交易运转" 的概念来自MetaEditor参考文档的一段话:
来自智能交易和脚本的交易,只能够供应一个并在交易作业中开启 (来自智能交易和脚本的自动交易作业)。这就是为何假使智能交易业务作业忙,其余的智能交易或脚本在此刻不能调用函数生成错误146 (ERR_TRADE_CONTEXT_BUSY)。换句话说,只有一个智能交易(脚本)可以准时交易。所以其余智能交易试图开始交易将被错误 146停止。文章将令寻到困难的处理方案。
2. 函数 IsTradeAllowed()这是最简单的方法是运用名称为IsTradeAllowed()的函数找出交易作业忙。
来自 MetaEditor参考文档的一段话:
"bool IsTradeAllowed()假使智能交易允许交易,返回TRUE 。否则,返回FALSE。这就代表着假使函数 IsTradeAllowed()返回TRUE只有一个可以试图交易。
在交易业务以前务必检测完成。
函数错误运用范例:
- int start()
- {
- // 检测交易作业
- if(!IsTradeAllowed())
- {
- // 假使函数IsTradeAllowed() 返回FALSE, 通知用户
- Print("交易作业忙。智能交易不能开仓!");
- // 而且中止交易业务。现在一个替克进入将从新开始
- // 进入
- return(-1);
- }
- else
- {
- // 假使函数IsTradeAllowed()返回TRUE,通知用户
- // 并继续运行
- Print("交易作业空闲!开始运转...");
- }
- // 当下检测市场
- ...
- // 计算止损和赢利水平和标准手
- ...
- // 开仓
- if(OrderSend(...) < 0)
- Alert("开仓错误 # ", GetLastError());
- return(0);
- }
复制代码在这个范例中,在start() 函数开始时检测交易运转状态。这是个错误想法: 在我们的智能交易计算的时期内交易作业会被其余智能交易占领(需要进入市场,止损和赢利,标准手等等)。这些情形,接受开仓将失利。
函数适当应用范例:
- int start()
- {
- // 当下检测市场
- ...
- // 计算止损和赢利水平,标准手数
- ...
- // 当下检测交易作业
- if(!IsTradeAllowed())
- {
- Print("交易作业忙! 智能交易不能开仓!");
- return(-1);
- }
- else
- Print("交易作业正常! 试图开仓...");
- //假使检测正常,开仓
- if(OrderSend(...) < 0)
- Alert("错误开仓 # ", GetLastError());
- return(0);
- }
复制代码在开仓以前立刻检测交易作业状态,而且或许在两种动作举动之间插入其余的智能交易 .
该种方法存在两点不足:
智能交易在接收到清晰结果检测状态的同期,将试图开始交易.
假使检测失利,智能交易将试图运用下一个替克交易; 将令延期.
处理第二种不足很简单:等候交易作业空闲即可.随后,在其余智能交易终结后,智能交易将立刻开始交易.
范比如下:
- int start()
- {
- // 当下检测能否进入市场
- ...
- // 计算赢利/止损水平和标准手数
- ...
- // 检测交易作业能否空闲
- if(!IsTradeAllowed())
- {
- Print("交易作业忙!等候空闲...");
- // 无限循环
- while(true)
- {
- // 假使智能交易被用户停止,停止业务
- if(IsStopped())
- {
- Print("智能交易被用停止!");
- return(-1);
- }
- // 假使交易作业空闲,开始交易
- if(IsTradeAllowed())
- {
- Print("交易作业空闲!");
- break;
- }
- // 假使没有条件设置循环, "等候" 0.1秒
- // 而且检测从新开始
- Sleep(100);
- }
- }
- else
- Print("交易作业空闲!试图开仓...");
- // 试图开仓
- if(OrderSend(...) < 0)
- Alert("错误开仓 # ", GetLastError());
- return(0);
- }
复制代码该种情形显现,我们可以表示下方错误:
函数 IsTradeAllowed()不仅仅能够显现交易作业的状态,同样可以在无限循环中以“隐藏”开启/关闭;假使从图表中手动去除,将停止运转。
假使智能交易等候交易作业空闲,在这个时间里,价格会更改而且或许用这个价格交易 - 报告需要创下开仓从新计算。
纠正的错误代码将令是下方:
- // 智能交易等候交易的时间time (in seconds) whithin which the expert will wait until the trade
- // 交易作业空闲(假使忙)
- int MaxWaiting_sec = 30;
- int start()
- {
- // 当下检验能否进入市场
- ...
- // 计算止损,赢利和标准手数
- ...
- // 检测交易作业能否空闲
- if(!IsTradeAllowed())
- {
- int StartWaitingTime = GetTickCount();
- Print("交易作业忙!等候空闲...");
- // 无限循环
- while(true)
- {
- // 如过用户中止智能交易,停止业务
- if(IsStopped())
- {
- Print("智能交易被用户中止!");
- return(-1);
- }
- // 假使等候时间胜过命名变量
- // MaxWaiting_sec, 停止业务
- if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
- {
- Print("标准限定(" + MaxWaiting_sec + " sec)胜过!");
- return(-2);
- }
- // 假使交易作业空闲,
- if(IsTradeAllowed())
- {
- Print("交易作业空闲!");
- // 创下市场信息
- RefreshRates();
- // 从新计算止损和赢利水平
- ...
- // 离开循环状态并开始交易
- break;
- }
- // 如过没有条件离开,请 "等候"0.1秒
- // 而且从新开始检测
- Sleep(100);
- }
- }
- else
- Print("交易作业空闲!试图开仓...");
-
- // 试图开仓
- if(OrderSend(...) < 0)
- Alert("错误开仓 # ", GetLastError());
-
- return(0);
- }
-
复制代码对于上面的范例,我们还可以添加:
创下市场信息(RefreshRates())而且从新计算止损和赢利水平
在胜过最大时间限定等候后 MaxWaiting_sec,智能交易将停止业务
以上的这些代码你已经可以运用到你的智能交易中。
当下让我们来谈谈在单独函数中的检测。这会简化在智能交易中的简化和用法。
- /////////////////////////////////////////////////////////////////////////////////
- // int _IsTradeAllowed( int MaxWaiting_sec = 30 )
- //
- // 函数检测交易作业状态. R返回代码:
- //1 - 交易作业空闲, 允许交易
- //0 - 交易作业忙,但是将空闲。创下市场信息后允许交易。
- // -1 - 交易作业忙,用户中止等候(智能交易从图表中删除,终端删除,图表周期/货币对更改等等)
- // -2 - 交易作业忙,高达最大等候限度 (MaxWaiting_sec).
- // 智能交易禁止交易(检测 "Allow live trading" ).
- //
- // MaxWaiting_sec - 函数将等候的时间
- // 直到交易作业控点(假使交易作业忙).默认值,30.
- /////////////////////////////////////////////////////////////////////////////////
- int _IsTradeAllowed(int MaxWaiting_sec = 30)
- {
- // 检测交易作业能否空闲
- if(!IsTradeAllowed())
- {
- int StartWaitingTime = GetTickCount();
- Print("交易作业忙!等候空闲...");
- // 无限循环
- while(true)
- {
- // 假使智能交易被用户中止,停止业务
- if(IsStopped())
- {
- Print("智能交易被用户中止!");
- return(-1);
- }
- // 假使等候时间多出指定
- // MaxWaiting_sec 变量 ,停止业务
- if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
- {
- Print("等候限度胜过 (" + MaxWaiting_sec + " сек.)!");
- return(-2);
- }
- // 假使交易作业空闲
- if(IsTradeAllowed())
- {
- Print("交易作业空闲!");
- return(0);
- }
- // 假使没有条件离开循环状态,请"等候" 0.1秒
- // 而且从新开始检测 Sleep(100);
- }
- }
- else
- {
- Print("交易作业空闲!");
- return(1);
- }
- }
复制代码对于智能交易运用函数的一个模板:
- int start()
- {
- // 当下检测能否进入市场
- ...
- // 计算止损,赢利水平和标准手数
- ...
- // 检测交易作业能否空闲
- int TradeAllow = _IsTradeAllowed();
- if(TradeAllow < 0)
- {
- return(-1);
- }
- if(TradeAllow == 0)
- {
- RefreshRates();
- // 从新计算赢利水平和止损水平
- ...
- }
- // 开仓
- if(OrderSend(...) < 0)
- Alert("错误开仓 # ", GetLastError());
- return(0);
- }
复制代码自此我们得出下方结论:
函数 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":函数的业务时间需要限定。
这就是我们最终得到的:
- /////////////////////////////////////////////////////////////////////////////////
- // int TradeIsBusy( int MaxWaiting_sec = 30 )
- //
- // 函数还原TradeIsBusy 值0 - 1.
- // 在开启时假使TradeIsBusy = 1 ,函数等候直至 TradeIsBusy 为 0,
- // 随后还原
- // 假使TradeIsBusy没有任何整体变量,函数将令自己创建。
- // 返回代码:
- //1 - 成功编译。TradeIsBusy整体变量值指定为 1
- // -1 - TradeIsBusy = 1 函数在此刻开启,等候用户中止
- // (智能交易从图表中去除,终端被停止,图表周期/货币对被更改等等)
- // -2 - TradeIsBusy = 1 函数在此刻开启,等候限定超时
- // (MaxWaiting_sec)
- /////////////////////////////////////////////////////////////////////////////////
- int TradeIsBusy( int MaxWaiting_sec = 30 )
- {
- // 试探时,没有理由划分交易作业 - 导致终止
- // 此函数
- if(IsTesting())
- return(1);
- int _GetLastError = 0, StartWaitingTime = GetTickCount();
- //+------------------------------------------------------------------+
- //| 检测整体变量能否存在,假使没有,创建整体变量 |
- //+------------------------------------------------------------------+
- while(true)
- {
- // 假使智能交易被用户中止,停止业务
- if(IsStopped())
- {
- Print("智能交易被用户中止!");
- return(-1);
- }
- // 假使等候时间胜过指定限定时间
- // MaxWaiting_sec, 停止业务
- if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
- {
- Print("等候时间(" + MaxWaiting_sec + " sec)多出!");
- return(-2);
- }
- // 检测整体变量能否存在
- // 假使不存在离开循环模式,执行更改
- // TradeIsBusy值
- if(GlobalVariableCheck( "TradeIsBusy" ))
- break;
- else
- // 假使GlobalVariableCheck 返回FALSE, 代表着整体变量不存在或者
- // 检测中生成错误
- {
- _GetLastError = GetLastError();
- // 假使依然有错误信息表明,等候0.1 秒,
- //从新开始检测
- if(_GetLastError != 0)
- {
- Print("TradeIsBusy()-GlobalVariableCheck("TradeIsBusy")-Error #",
- _GetLastError );
- Sleep(100);
- continue;
- }
- }
- // 假使没有错误,代表着没有整体变量,试图创建
- // 整体变量
- //假使 the GlobalVariableSet > 0, 表明整体变量成功创建。
- // 离开函数
- if(GlobalVariableSet( "TradeIsBusy", 1.0 ) > 0 )
- return(1);
- else
- // 假使GlobalVariableSet返回值<= 0, 表明有错误
- // 在变量创建时生成
- {
- _GetLastError = GetLastError();
- //表明信息,等候0.1秒,又一次试图
- if(_GetLastError != 0)
- {
- Print("TradeIsBusy()-GlobalVariableSet("TradeIsBusy",0.0 )-Error #",
- _GetLastError );
- Sleep(100);
- continue;
- }
- }
- }
- //+----------------------------------------------------------------------------------+
- //| 假使函数高达实施点,表明整体变量 |
- //| 变量退出. |
- //| 等候TradeIsBusy 值形成0 而且更改 TradeIsBusy 值为 1 |
- //+----------------------------------------------------------------------------------+
- while(true)
- {
- // 假使智能交易被用户中止,停止业务
- if(IsStopped())
- {
- Print("智能交易被用户中止!");
- return(-1);
- }
- // 假使等候胜过限定时间
- // MaxWaiting_sec, 停止业务
- if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
- {
- Print("等候时间 (" + MaxWaiting_sec + " sec) 多出!");
- return(-2);
- }
- // 试图更改 TradeIsBusy的值从 0 - 1
- // 假使成功,离开函数返回1 ("成功编译")
- if(GlobalVariableSetOnCondition( "TradeIsBusy", 1.0, 0.0 ))
- return(1);
- else
- // 假使失利,或许致使失利的2个原因: TradeIsBusy = 1 (随后等候),
-
- // 错误生成(需要我们检测)
- {
- _GetLastError = GetLastError();
- // 假使依然存在错误,表明信息而且从新试图
- if(_GetLastError != 0)
- {
- Print("TradeIsBusy()-GlobalVariableSetOnCondition("TradeIsBusy",1.0,0.0 )-Error #",
- _GetLastError );
- continue;
- }
- }
- //假使没有错误,表明TradeIsBusy = 1 (其余智能交易在运行),
- // 随后表明信息而且等候...
- Comment("等候其余智能交易交易完成...");
- Sleep(1000);
- Comment("");
- }
- }
-
复制代码在这里可以清楚地目睹:
检测整体变量能否存在,假使没有,执行创建
尝试更改整体变量的值从 0到 1;假使其值等于0,将开启。
函数可以运行 MaxWaiting_sec,而且不从图表中删除任何商品。
错误信息生成你可以在日志中寻到。
6. 函数TradeIsNotBusy()函数TradeIsNotBusy 处理返回的困难:开启"绿色"。
这项功能没有限定而且不能由用户中止。方式非常简单:假使 "绿色" 关闭,智能交易将不会执行交易。
不会返回任何代码:结果只能被成功编译。
参见下面示例:
- /////////////////////////////////////////////////////////////////////////////////
- // void TradeIsNotBusy()
- //
- // 函数设置整体变量 TradeIsBusy 值等于0.
- // 假使TradeIsBusy不存在,函数创建。
- /////////////////////////////////////////////////////////////////////////////////
- void TradeIsNotBusy()
- {
- int _GetLastError;
- // 试探时,交易作业不被划分 - 导致终止
- // 此函数
- if(IsTesting())
- {
- return(0);
- }
- while(true)
- {
- // 假使智能交易被用户中止,停止业务
- if(IsStopped())
- {
- Print("智能交易被用户中止!");
- return(-1);
- }
- // 试图设置整变量值= 0 (创建整体变量)
- // 假使 GlobalVariableSet 返回值 > 0, 表明成功
- // 离开函数
- if(GlobalVariableSet( "TradeIsBusy", 0.0 ) > 0)
- return(1);
- else
- // 假使GlobalVariableSet 返回值 <= 0, 表明错误生成
- // 表明信息,等候而且试图从新开始
- {
- _GetLastError = GetLastError();
- if(_GetLastError != 0 )
- Print("TradeIsNotBusy()-GlobalVariableSet("TradeIsBusy",0.0)-Error #",
- _GetLastError );
- }
- Sleep(100);
- }
- }
复制代码7. 在智能交易中的结合运用当下我们有 3 个函数可以通向交易作业。使他们简单地结合到智能交易中,我们可以创建一个 TradeContext.mq4 文件而且运用 #include (获取文件)。
这是一个运用函数 TradeIsBusy()和函数TradeIsNotBusy()的模板:
- #include
-
- int start()
- {
- // 当下检测能否进入市场
- ...
- // 计算止损水平,赢利水平和标准手数
- ...
- // 等候交易作业空闲而且进入(假使生成错误,
- // 离开)
- if(TradeIsBusy() < 0)
- return(-1);
- // 创下市场信息
- RefreshRates();
- // 从新计算止损和赢利水平
- ...
- // 开仓
- if(OrderSend(...) < 0)
- {
- Alert("错误开仓位置 # ", GetLastError());
- }
-
- //设置交易作业空闲
- TradeIsNotBusy();
-
- return(0);
- }
-
复制代码在运用函数 TradeIsBusy()和函数 TradeIsNotBusy()时,只有一个困难能够造成: 假使在交易作业变成忙后,智能交易从图表中去除,变量 TradeIsBusy将令等于 1。其余的智能交易将不或许运行。
这个困难可以很轻松地处理: 在智能交易在图表中交易时,不从图表中去除;)
在终端停歇时, TradeIsBusy值也有机会不等于0。该种情形,函数 TradeIsNotBusy()从智能交易的函数 init() 被运用。
诚然,在任什么时候间内可以手动更改变量值: 终端内的F3键 。不提倡执行运用。