launching MT4 with EAs and currencies from the command-line - page 2

 
vgoklani:

It would never trade if I had to wait that long, that's the point of using so many sessions! Obviously each of my EAs sleep for a few milliseconds when "IsTradeContextBusy() == true", but it would never trade if I ran 30. That's why I run three EAs in 50, most of which go bankrupt, and so I need to create new demo accounts too.

Anyway, perhaps you could help me with another question. I have a very simple script which outputs my trades, (outputResults) and I would like to run it once per day. Is there an intelligent way of making it run automatically at say 9am? I could just keep checking the time, and then have it run when the current time equals 9am. But that seems like a huge waste of cpu time, I was wondering if there was something more clever.


Perhaps sleep(), seems you're already familiar with this function. Have it sleep for 24 hours. WHRoeder have posted really good examples of these in the past. I don't have a link handy. Perhaps you could do a search on the forum. Good-Trading.

-Zen- 

 
I like that idea! But do the scripts interfere with the processing threads? Is there a more direct way of triggering the scripts outside the "sand-boxed" MT4 environment?
 
vgoklani:
I like that idea! But do the scripts interfere with the processing threads? Is there a more direct way of triggering the scripts outside the "sand-boxed" MT4 environment?
  1. every script and every EA runs in its own thread.
  2. MT4 has no API that is accessible from the outside. You will need an EA or script running that will communicate with the outside world and implement the MT4 side of your own IPC protocol, the only workaround that might be helpful in some cases is that you can use the windows messaging to talk to most of MT4's UI components directly are there are even some undocumented messages that can be used to trigger events like the immediate calling of start() on a certain chart, this makes the needed polling inside the EA easier. For Menus and buttons and other UI elements MT4 uses native win32 controls and you can use the windows API to talk to them.
 
vgoklani:
I am not a commercial undertaking (!), just a guy trying to scalp the forex market! I decided to run 50 different variations of my strategy to see if I could map the volatility over the week. A lot of my strategies work one day and then collapse afterwards... Believe me, trying to load MT4 50 times on your own home-made computer is really painful... anyway, hopefully someone else will be nice enough to give me some hints.

Oh, okay then...

The easiest way to control, from outside MT4, which symbols and EAs are loaded at startup is to create/modify/overwrite the chart .chr files (usually in profiles\default, unless you switch profile). The only issue with this is different symbol-naming on different brokers. A chart file for EURUSD won't work (without modification) on a broker using a naming convention such as EURUSDFXF, EURUSDcx etc.

As 7bit is saying, the only way of launching a script from outside MT4 is to have something running within MT4 which listens for some sort of signal, and then uses the nasty undocumented methods such as https://www.mql5.com/en/forum/115967 for launching a script.

However, in your example of a script which runs once per day, I can't see why you don't just write it as an EA which watches the current time and only does anything once per day. The processor usage is going to be utterly trivial, not "a huge waste of cpu time".

 
vgoklani:

[...] Is there any way to specify which currencies and EAs would run in each session of MT4 from the command-line? On a separate note, is it possible to launch an MT4 script from the command-line, while MT4 is already running? [...]

One possible solution is to have one Master Terminal launch other Terminals, 'injecting' them with the required experts, charts and settings that need to be run at startup. This can be done via methods decribed here -> https://www.mql5.com/en/articles/1467. A method to shutdown a Terminal when it's not 'in use' anymore and report this back to the Master Terminal is needed. Many ways to achieve this...
 

vgoklani:

I run several (50+) sessions of MT4 simultaneously, and I find the process of individually opening each MT4 with 3+ EAs to be quite tedious. Is there any way to specify which currencies and EAs would run in each session of MT4 from the command-line? On a separate note, is it possible to launch an MT4 script from the command-line, while MT4 is already running?

  1. Each separate MT4 must be a separate install. Do not run multiple terminals from the same install. You can set up each with the EA's you want and start all of them via command line script (startMT.bat)
    start "mt" "C:\fx\mt1\terminal.exe"
    start "mt" "C:\fx\mt2\terminal.exe"
    ...
  2. Alternatively, avoid the context is busy by using one terminal and have the EAs use a semaphore:
    //+------------------------------------------------------------------+
    //| 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 );   Sleep(1000);
        }
    }   // 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
    
    

Reason: