如何让 MQL4 代码在交易上下文的实际状态下工作?
How to get MQL4 code work under an actual state of a Trade context?
TradeContext()
在以下场景中有何相关性?
TradeContext()
return 会在这些情况下忙吗()同时发送交易指令?
1) 当同一个 EA 附加到不同的交叉盘时,每个交叉盘在 MetaTrader Terminal 4 平台的同一实例中各自的图表上。
2) 在 MetaTrader Terminal 4 平台的一个实例中,不同的策略,跨不同的图表,但都使用相同的 FX-cross。
3) 当使用MetaTrader Terminal 4 平台的多个实例时,在上述任一情况下操作EA代码。
案例 3) 具有更好的 client-server 吞吐量,因为 MT4 终端平台的每个实例都包含其自己的内部引擎(贸易(管理)上下文实例)。这个内部引擎在技术上对用户是不可见的,但是用户有责任检查案例,当这个引擎阻止 XTO 的指令在 Server-side.
上实现时
事实 1:平台不断发展。
早些年,MetaTrader Terminal 4 平台经常报告案例,当它的内部实现 trade-management factory-pattern,停留在一个状态,避免任何进一步的请求免于处理。
此类指示未异步报告/未与 MQL4 代码执行流程交互,而是在代码尝试检查 GetLastError()
或 _LastError
或通过 IsTradeContextBusy()
值:
#include <stdlib.mqh>
#include <stderror.mqh>
...
ErrorDescription( GetLastError() ); // was available for showing an Error state
和
在某些情况下,_LastError == 146
== ERR_TRADE_CONTEXT_BUSY
报告一个状态,当贸易上下文繁忙时。
换句话说,工作流中的每个 XTO-operation 因此通常都被仔细的 Error-State-detection 分析代码所包围,并包含(在可能的情况下以某种可行的形式)某种补救措施,因此为了克服阻塞(拒绝)XTO-operation,直到可能或有一些 time-out watchdog-controlled 退出路径。
几年后,也许在 Build 509 之后,肯定是在 Build 624+ 部署之后,这个到目前为止常见的(隐藏的)blocking-state 不再出现,所以经常。
如果你观察案例,当_LastError
确实再次报告ERR_TRADE_CONTEXT_BUSY
时,会有需要更加小心以隔离此类状态,因此最好使用 code-execution 流程中所有步骤的详细日志记录,以便映射实际平台状态。
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;
}
TradeContext()
在以下场景中有何相关性?
TradeContext()
return 会在这些情况下忙吗()同时发送交易指令?
1) 当同一个 EA 附加到不同的交叉盘时,每个交叉盘在 MetaTrader Terminal 4 平台的同一实例中各自的图表上。
2) 在 MetaTrader Terminal 4 平台的一个实例中,不同的策略,跨不同的图表,但都使用相同的 FX-cross。
3) 当使用MetaTrader Terminal 4 平台的多个实例时,在上述任一情况下操作EA代码。
案例 3) 具有更好的 client-server 吞吐量,因为 MT4 终端平台的每个实例都包含其自己的内部引擎(贸易(管理)上下文实例)。这个内部引擎在技术上对用户是不可见的,但是用户有责任检查案例,当这个引擎阻止 XTO 的指令在 Server-side.
上实现时事实 1:平台不断发展。
早些年,MetaTrader Terminal 4 平台经常报告案例,当它的内部实现 trade-management factory-pattern,停留在一个状态,避免任何进一步的请求免于处理。
此类指示未异步报告/未与 MQL4 代码执行流程交互,而是在代码尝试检查 GetLastError()
或 _LastError
或通过 IsTradeContextBusy()
值:
#include <stdlib.mqh>
#include <stderror.mqh>
...
ErrorDescription( GetLastError() ); // was available for showing an Error state
和
在某些情况下,_LastError == 146
== ERR_TRADE_CONTEXT_BUSY
报告一个状态,当贸易上下文繁忙时。
换句话说,工作流中的每个 XTO-operation 因此通常都被仔细的 Error-State-detection 分析代码所包围,并包含(在可能的情况下以某种可行的形式)某种补救措施,因此为了克服阻塞(拒绝)XTO-operation,直到可能或有一些 time-out watchdog-controlled 退出路径。
几年后,也许在 Build 509 之后,肯定是在 Build 624+ 部署之后,这个到目前为止常见的(隐藏的)blocking-state 不再出现,所以经常。
如果你观察案例,当_LastError
确实再次报告ERR_TRADE_CONTEXT_BUSY
时,会有需要更加小心以隔离此类状态,因此最好使用 code-execution 流程中所有步骤的详细日志记录,以便映射实际平台状态。
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;
}