0
votes

How is a TradeContext() relevant in the following scenarios?

Will a TradeContext() return busy in these situations() when sending trade instructions at the same time?

1) When the same EA, attached to different crosses, each on its own chart in the same instance of the MetaTrader Terminal 4 platform.

2) When different strategies, across different charts, but all using the same FX-cross, in one instance of the MetaTrader Terminal 4 platform.

3) When using multiple instances of the MetaTrader Terminal 4 platform, operating EA-code in either of the situations mentioned above.

1
I'm voting to close this question as off-topic because this is not about programming it is about how some external service works. We are not your favorite company's tech support.user177800
I disagree. This is a programming question. It asks how a function operates. There is no company involved but how MQL4 deals with TradeContext. It is an inbuilt function.Jean
Please read What types of questions should I avoid asking? before attempting to ask more questions.user177800
Whoa whoa @JarrodRoberson, I'm not absolutely 100% sure but having used MQL4 this looks like a legit MetaTrading scripting language programming question.adelriosantiago
I´m a Metatrader user and my opinion is that this is a programming question, about mql4, which is a programming language, so I disagree with @JarrodRobersonJ_P

1 Answers

1
votes

The case 3) has better client-server throughput, as each instance of MT4 Terminal platform contains it's own internal engine ( a Trade (management) Context instance ). This internal engine is technically invisible to user, but user has a responsibility to check the cases, when this engine is blocking the XTO's instructed to be fulfilled on the Server-side.


Fact #1: The platform evolves.

In early years, the MetaTrader Terminal 4 platform was quite often reporting cases, when it's internal implementation of a trade-management factory-pattern, dwelt in a state, which avoided any further request(s) from being processed.

Such indications were not asynchronously reported / did not interface with the flow of the MQL4-code execution, but was just indirectly accessible, after the code tried to inspect the GetLastError() or _LastError or via the IsTradeContextBusy() value:

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

and in cases, where _LastError == 146
== ERR_TRADE_CONTEXT_BUSY reports a state, when a Trade context was busy.

In other words, each XTO-operation in the workflow was thus typically surrounded by a careful Error-State-detection analysis code and included ( in some feasible form, where possible ) some sort of remedy actions, so as to overcome the blocked ( refused ) XTO-operation, until possible or having some time-out watchdog-controlled exit path.

After some years, maybe after Build 509, definitely after a Build 624+ came into deployment, this so far common ( hidden ) blocking-state ceased to appear so often.

If you observe cases, when a _LastError indeed reports the ERR_TRADE_CONTEXT_BUSY again, there will be more care needed so as to isolate such state, so best use a detailed logging of all the steps in the flow of the code-execution, so as to map the actual platform 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:                        {    ...
                                      }
   }

If testing durations, for which the situation gets not resolved, may use something like this:

  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;
              }