What is the best way to trade multiple pairs of the same account?

 

What is the best way to trade multiple pairs?

Ex. I would like to trade like 4 pairs on the same account

When running EA, I face problem like error 146, TradeDispatcher is busy. I believe the cause of this is that MT4 is single threading and EA cannot make more than one trade at a time? Correct me if I am wrong.

 

 

I was thinking of solving this problem by running 4 separate MT4 Client terminal, trading the same account.

Q1: How to run different instance of the same MT4 using the same account on the same PC?

 

If Q1 is possible then 

Q2: Will I get the see updates of one another terminals' trades? Ex. I run 4 Terminals (Terminal 1,2,3,4), all running the same account. When Terminal 1 makes a trade, will I see that on Terminal 2,3,4?

 

Thanks in advance. 

 

You are correct in your assumptions.

Each instance of MT4 can be connected to one account and have just one "trading context".

You may run different charts in that instance/context each with one EA (and these EAs may or may not be the same of course).

If there is a chance that the EAs will attempt to perform TRADING operations at the same time, therefore contending for the single trading context, then you must decide either to:

- live with trade failures due to "Trade Context Busy" errors

- code your EAs to share the trading context by handling the above errors

- or (as you've pointed out) implement multiple instances of the MT4 platform (all of which may operate on the same account, or on different accounts)


A1: Simply clone the installation MT4 software installation folder multiple times. Each instance can sign on to the same or different broker accounts.

A2:Yes. All instances connected to the same account reflect the same orders in the current order pool. The only wrinkle (due to a poor MT4 client/server architecture decision) is to ensure that you configure the history window in each instance to display the same group of orders in the history pool. If you don't, then EAs operating on the same account could see a different set of orders when performing OrderSelect() on the history pool.

CB

 

You can also code your EA to trade multi-pairs on a single instance.

 
Matutin:

You can also code your EA to trade multi-pairs on a single instance.


That was option 2 in my list of 3.

CB

 
Create a semaphore so all EA instances don't conflict.
//+------------------------------------------------------------------+
//| Trade context semaphore.                                         |
//+------------------------------------------------------------------+
void RelTradeContext(){         // Set global variable for GetTradeContext = 0.
/*bool  need2refresh;           // Export=T to GetTradeContext=R|T|F,
                                // setDIR=R|F, start=F, ModifyStops=R|F */
    need2refresh = true;        // Assume caller did a OrderSend/Modify/Close.
    while( !(IsTesting() || IsStopped()) ){
        GlobalVariableSet(TC.GV.Name, 0.0); // Unlock the trade context.
        int _GetLastError = GetLastError();
        if (_GetLastError == 0) break;
        Comment("RelTradeContext: GlobalVariableSet('",
                TC.GV.Name,"',0.0)-Error #", _GetLastError );
    }
}   // void RelTradeContext()

int  Random(int min, int max){  return( MathRand()/32768.0*(max-min+1)+min );  }
#define ERR_146_MIN_WAIT_MSEC    1000   // Trade context busy random delay min
#define ERR_146_MAX_WAIT_MSEC    5000   // Trade context busy random delay max
void RandomSleep(){ Sleep(Random(ERR_146_MIN_WAIT_MSEC,ERR_146_MAX_WAIT_MSEC));}
#define ERR_146_TIMEOUT_MSEC    60000   // Trade context busy maximum delay
#include <stderror.mqh>                 // ERR_GLOBAL_VARIABLE_NOT_FOUND
int GetTradeContext(int maxWaitMsec = ERR_146_TIMEOUT_MSEC){
//  bool    need2refresh;               // Import from RelTradeContext
    /*Return codes:*/{
        #define TC_LOCKED        0  //  Success. The global variable TC.GV.Name
    //                                  was set to 1, locking out others.
        #define TC_REFRESH      +1  //  Success. The trade context was initially
    //                                  busy, but became free. The market info
    //                                  needed to be refreshed. Recompute trade
    //                                  values if necessary.
        #define TC_ERROR        -1  //  Error, interrupted by the user. The
    //                                  expert was removed from the chart, the
    //                                  terminal was closed, the chart period
    //                                  and/or symbol was changed, etc.)
        #define TC_TIMEOUT      -2  //  Error, the wait limit was exceeded.
    /*************************************************************************/}
    if ( IsTesting() ){                     // Only one EA runs under the tester
        if (need2refresh)   Refresh();
        return(TC_LOCKED);                  // Context always available.
    }
    /* If there is no global variable, create it. If the variable == 1 wait
     * until another thread sets it back to 0. Set it to 1. */
    int     startWaitingTime    = GetTickCount(),   // Remember start time.
            GTCreturn           = TC_LOCKED;        // Assume an idle context.
    bool    TC_locked           = false;            // Not yet.
    while(true){
        if ( IsStopped() ){     // The expert was terminated by the user, abort.
            Print("GTC: The expert was terminated by the user!");
            if (TC_locked)  RelTradeContext();
            return(TC_ERROR);
        }
        if (!TC_locked) {                           // Set the semaphore.
            if (GlobalVariableSetOnCondition( TC.GV.Name, 1.0, 0.0 )){
                TC_locked=true;                     // Semaphore now set.
                continue;                           // Check for non-sema EAs.
            }
            int _GetLastError   = GetLastError();   switch(_GetLastError){
            case 0:                             // Variable exists but is
                break;                          // already set. Need to wait.
            case ERR_GLOBAL_VARIABLE_NOT_FOUND:
                GlobalVariableSet(TC.GV.Name, 0.0); // Create it.
                _GetLastError   = GetLastError();
                if (_GetLastError == 0) continue;
                Print(  "GetTradeContext: GlobalVariableSet(", TC.GV.Name,
                            ", 0.0) Failed: ",  _GetLastError );    // Error
                return(TC_ERROR);
            default:
                Print(  "GetTradeContext:GlobalVariableSetOnCondition('",
                        TC.GV.Name, "',1.0,0.0)-Error #", _GetLastError);
                break;                      // Exit switch, wait and retry.
            }   // switch(_GetLastError)
        }   // Set the semaphore.
        else if (!IsTradeContextBusy()){            // Cleanup and return.
            if (GTCreturn == TC_REFRESH){           // Clear the Wait comment
                Comment(WindowExpertName(),": ", VERSION);
                need2refresh=true;
            }
            if (need2refresh)   Refresh();
            return(GTCreturn);
        }
        int delay = GetTickCount() - startWaitingTime ;
        if (delay > maxWaitMsec){                   // Abort.
            Print("Waiting time (", maxWaitMsec/1000, " sec) exceeded!");
            if (TC_locked)  RelTradeContext();
            return(TC_TIMEOUT);
        }
        Comment("Wait until another expert finishes trading... ", delay/1000.);
        RandomSleep();
        GTCreturn = TC_REFRESH;                     // Will need to refresh.
    }   // while
    /*NOTREACHED*/
}   // GetTradeContext
 
cloudbreaker:

You are correct in your assumptions.

Each instance of MT4 can be connected to one account and have just one "trading context".

You may run different charts in that instance/context each with one EA (and these EAs may or may not be the same of course).

If there is a chance that the EAs will attempt to perform TRADING operations at the same time, therefore contending for the single trading context, then you must decide either to:

- live with trade failures due to "Trade Context Busy" errors

- code your EAs to share the trading context by handling the above errors

- or (as you've pointed out) implement multiple instances of the MT4 platform (all of which may operate on the same account, or on different accounts)


A1: Simply clone the installation MT4 software installation folder multiple times. Each instance can sign on to the same or different broker accounts.

A2:Yes. All instances connected to the same account reflect the same orders in the current order pool. The only wrinkle (due to a poor MT4 client/server architecture decision) is to ensure that you configure the history window in each instance to display the same group of orders in the history pool. If you don't, then EAs operating on the same account could see a different set of orders when performing OrderSelect() on the history pool.

CB


"The only wrinkle (due to a poor MT4 client/server architecture decision) is to ensure that you configure the history window in each instance to display the same group of orders in the history pool. If you don't, then EAs operating on the same account could see a different set of orders when performing OrderSelect() on the history pool."

What do you mean?

How to configure the history window in each instance to display the same group of orders in the history pool?

 

Do you mean that customized time period for the history pool must be the same? That also apply to when using 1 client right?

Are you referring to the terminal history? 

https://docs.mql4.com/trading/OrderSelect 

Will there any problem with order pool when Select_By_Pos, Mode_Trades?

 

Thanks!