如何让MQL4代码在Trade上下文的实际状态下工作?

时间:2018-02-17 06:10:19

标签: mql4 algorithmic-trading metatrader4

TradeContext() 在以下情况下如何相关?

在同时发送交易指令时,TradeContext()是否会在这些情况下()返回忙碌状态?

1)当同一个EA连接到不同的十字架时,每个都在MetaTrader Terminal 4平台的同一个实例的图表上。

2)在MetaTrader Terminal 4平台的一个实例中,不同的策略,不同的图表,但都使用相同的FX-cross。

3)当使用MetaTrader Terminal 4平台的多个实例时,在上述任何一种情况下操作EA代码。

1 个答案:

答案 0 :(得分:1)

案例3)具有更好的客户端 - 服务器吞吐量,因为MT4终端平台的每个实例都包含它自己的内部引擎(交易(管理)上下文实例)。这个内部引擎在技术上对用户是不可见的,但是当引擎阻止XTO被指示在服务器端完成时,用户有责任检查案例。

事实#1:平台不断发展。

早年,MetaTrader Terminal 4平台经常报告案例,当它是一个贸易管理工厂模式的内部实施时,居住在一个州,这避免了任何进一步的请求被处理。

此类指示未异步报告/未与MQL4代码执行流程相关联,但在代码尝试检查 GetLastError() 或<之后,只能间接访问strong> _LastError 或通过 IsTradeContextBusy() 值:

#include <stdlib.mqh>
#include <stderror.mqh>
...
ErrorDescription( GetLastError() ); // was available for showing an Error state

和     在案例中, _LastError == 146
 当交易环境繁忙时, == ERR_TRADE_CONTEXT_BUSY 会报告一个州。

换句话说,工作流程中的每个XTO操作通常都包含一个仔细的错误状态检测分析代码,并包含(在某种可行的形式,如果可能的话)某种补救措施,以便克服阻止(拒绝)XTO操作,直到可能或有一些超时看门狗控制的退出路径。

经过几年,也许在Build 509之后,肯定是在 Build 624 + 部署之后,这个迄今为止常见的(隐藏)阻塞状态不再经常出现。

如果您观察到案例,当 _LastError 确实再次报告 ERR_TRADE_CONTEXT_BUSY 时,需要更多关注以便隔离state,所以最好使用详细记录代码执行流程中的所有步骤,以便映射实际的平台状态。

switch( Error )
{  case ...

   case ERR_TRADE_CONTEXT_BUSY:    {  // ERR_TRADE_CONTEXT_BUSY
                                         aLogSTRING     = StringConcatenate( msLIB.anElapsedTimeSTRING(), "[ ", DoubleToStr( GetTickCount(), 0 ), " ] Trying to OrderModify() aPendingOrderOBJECT for this SONAR_BEEP Monitor at MT4Server side. <localhost>MT4Terminal reports: [ERR_TRADE_CONTEXT_BUSY] <state>. Will Sleep() here a bit more." );
                                         aComment.ADD(            aLogSTRING );
                                         aMXact.aDeferredLOGGER(  aLogSTRING, TRUE );
                                         Sleep( 60 * 1000 );
                                         break;
                                      }
   ...
   default:                        {    ...
                                      }
   }

如果测试持续时间(情况未得到解决)可能会使用以下内容:

  while (  !IsStopped() )  {                   // LOOP FOREVER, UNTIL IsStopped()
           tix.START = GetTickCount();         // STO()_______pre-STORE()_________________________ .START
           if (  IsTradeContextBusy() ) {      // if BUSY().......MEASURE......................... .START inner-LOOP
                 while (  IsTradeContextBusy() && !IsStopped() )  {       // LOOP @BUSY()_________________________________________________________________________ tix
                          Sleep( msLIB.RT.LOOP_inMeasureSleep.ms );       //             Sleep(*)
                       }  // .............................................// LOOP .or. !BUSY()--------------------------------------------------------<_LOOP_>----     .or. { !IsTradeContextBusy() | IsStopped() }
                 tix.END    = GetTickCount();  //  STO()__________________ .END   inner-LOOP _____________________________________________________________________ tix
                 tix.BUSY   = tix.END - tix.START;
              // aString2LOG= StringConcatenate(   TimeToStr( TimeCurrent(), _time2str.MASK ),";", DoubleToStr( tix.START, 0 ), ";",  DoubleToStr( tix.BUSY, 0 ) );
                 aString2LOG= StringConcatenate(   TimeToStr( TimeLocal(),   _time2str.MASK ),";", DoubleToStr( tix.START, 0 ), ";",  DoubleToStr( tix.BUSY, 0 ) );        // TimeLocal() works either before/after Market Closes and no quotes arrive ( thus avoiding the hanging at TimeCurrent() at the time of the last known Quote.... )
              // LOG.append
              // LOG ------------------------|||||||||||||||--------------------------   
                                      aMXact.aDeferredLOGGER( aString2LOG, ( IsStopped() ) );
                 aComment.ADD( StringConcatenate(    msLIB.anElapsedTimeSTRING(),
                                                     " <localhost>.<aTradingCONTEXT>.BUSY was <OBSERVED> at ",
                                                     DoubleToStr( aLoopCOUNTER.RollOVER * msLIB.RT.LOOP_nLoops2ShowGuiMSG + aLoopCOUNTER, 0 ),
                                                     " loop, < cpuClockTIXs.START | cpuClockTIXs.DURATION> ",
                                                     aString2LOG
                                                  )
                             );
                 aLoopCOUNTER.RollOVER = 0;
                 aLoopCOUNTER = 0;
              }