control live ea

 

I've got an ea that I need to tweak parameters on WHILE it's running live trades. As there are a host of variables and arrays loaded with current data about the trades I don't want to shut it down and lose ea control over those trades.

I can easily enough code an hourly or daily check of the filesystem for the presence of a given semaphore file and then when the file is present have the system proceed to load a csv-based parameter set. This is not a problem. But it would be nicer to have an interface right on the terminal where I hit a button and WHAM! my parameter file is read at that instant by my ea that traps the button or method or whatever.

The alternative of having the file check done more frequently, say once a tick or every few minutes is not great as this ea is pushing 5K lines already and it does not need to be loaded down with any more tick-based activity...

I've gone through the mt4 function reference again and am drawing blanks (other than the semaphore file idea...)

Any suggestions?

thx, t.

 
tbuitendyk:

I've got an ea that I need to tweak parameters on WHILE it's running live trades. As there are a host of variables and arrays loaded with current data about the trades I don't want to shut it down and lose ea control over those trades.

I can easily enough code an hourly or daily check of the filesystem for the presence of a given semaphore file and then when the file is present have the system proceed to load a csv-based parameter set. This is not a problem. But it would be nicer to have an interface right on the terminal where I hit a button and WHAM! my parameter file is read at that instant by my ea that traps the button or method or whatever.

The alternative of having the file check done more frequently, say once a tick or every few minutes is not great as this ea is pushing 5K lines already and it does not need to be loaded down with any more tick-based activity...

I've gone through the mt4 function reference again and am drawing blanks (other than the semaphore file idea...)

Any suggestions?

thx, t.

Just use extern variables. Any extern variable can be changed during expert run by entering the Properties menu (right click on the chart and choose Expert Advisors > Properties, or just press F7).


Note that during the time when properties window is open the expert is disabled. As soon as u press OK the expert will continue running (start() will continue on next incoming tick unless u launch it from init() as well).


The only limitation to this method is that the properties windows will only pop-up when expert is not running (when start() has finished it's operation and is waiting for next incoming tick), so if u have your expert running in a loop, this won't work.

 
gordon wrote >>

Just use extern variables. Any extern variable can be changed during expert run by entering the Properties menu (right click on the chart and choose Expert Advisors > Properties, or just press F7).

Note that during the time when properties window is open the expert is disabled. As soon as u press OK the expert will continue running (start() will continue on next incoming tick unless u launch it from init() as well).

The only limitation to this method is that the properties windows will only pop-up when expert is not running (when start() has finished it's operation and is waiting for next incoming tick), so if u have your expert running in a loop, this won't work.

Cool. Did not know that.

The use of an extern won't work for me exactly as you've suggested as some of the data I'm accessing and updating includes a [20][20][13] int array among some other biggies. That being said I can add a couple of extern bools easily enough

extern bool dumpVLTbl;

extern bool loadVLTbl;

etc. and get at them via csv.

most helpful gordon. thx!

 
tbuitendyk:

Cool. Did not know that.

The use of an extern won't work for me exactly as you've suggested as some of the data I'm accessing and updating includes a [20][20][13] int array among some other biggies. That being said I can add a couple of extern bools easily enough

extern bool dumpVLTbl;

extern bool loadVLTbl;

etc. and get at them via csv.

most helpful gordon. thx!

Yeah, forgot to mention that arrays cannot be controlled this way. Either break an array into individual parameters or use a workaround involving read/write to file in whatever format u find most convenient. Externs can be of any type btw -> https://docs.mql4.com/basis/variables/extern

 
gordon wrote >>

Yeah, forgot to mention that arrays cannot be controlled this way. Either break an array into individual parameters or use a workaround involving read/write to file in whatever format u find most convenient. Externs can be of any type btw -> https://docs.mql4.com/basis/variables/extern

This ea's got a case of out of control externs already... Believe it or not there's over 400 already. I keep cringing on every compile as I keep expecting the platform to die. I don't know what the limit in a single ea is but I hope I've got some room to go cause I've got some more ideas that need to get in there!

thx again, t.

 
tbuitendyk:

This ea's got a case of out of control externs already... Believe it or not there's over 400 already. I keep cringing on every compile as I keep expecting the platform to die. I don't know what the limit in a single ea is but I hope I've got some room to go cause I've got some more ideas that need to get in there!

thx again, t.

I don't remember seeing any limitation on the number of externs in documentation. Then again, the documentation for MQL4 ain't all that good (in my humble opinion). But I wouldn't worry about it. I have had EA's with hundreds of variables with no problems. Just takes longer to compile...

 
gordon wrote >>

Just use extern variables. Any extern variable can be changed during expert run by entering the Properties menu (right click on the chart and choose Expert Advisors > Properties, or just press F7).

Note that during the time when properties window is open the expert is disabled. As soon as u press OK the expert will continue running (start() will continue on next incoming tick unless u launch it from init() as well).

The only limitation to this method is that the properties windows will only pop-up when expert is not running (when start() has finished it's operation and is waiting for next incoming tick), so if u have your expert running in a loop, this won't work.

Well gordon, I took your advice and now I've got live trades running on my account not under control of my EA.

Are you SURE that you are correct? Pehaps you were not aware that DeInit is called when properties are changed on a live EA?

In my experience, as soon as you hit OK on the EA parameters box DeInit is called, followed by Init, followed by Start on the next tick. Is it not correct that all variables with the exception of terminal level globals (i.e., NOT EA level globals) are wiped out when DeInit runs as by definition this means that the EA is being unloaded?!?

A word of warning before following gordon's advice everyone: You may find MetaTrader's behaviour is to UNLOAD your EA and RELOAD it, just like I found. That could be bad for your open positions.

 
tbuitendyk wrote >>

Well gordon, I took your advice and now I've got live trades running on my account not under control of my EA.

Are you SURE that you are correct? Pehaps you were not aware that DeInit is called when properties are changed on a live EA?

In my experience, as soon as you hit OK on the EA parameters box DeInit is called, followed by Init, followed by Start on the next tick. Is it not correct that all variables with the exception of terminal level globals (i.e., NOT EA level globals) are wiped out when DeInit runs as by definition this means that the EA is being unloaded?!?

A word of warning before following gordon's advice everyone: You may find MetaTrader's behaviour is to UNLOAD your EA and RELOAD it, just like I found. That could be bad for your open positions.

Well anyway, I've gone with plan 'A' which was to control my EA by scheduled response to user request for the internal tables. The following chunk of code lives at the top of my start() now. So now I simply drop a flag file "DumpTables.on" (or .off when not needed) or "LoadTables.on" and I can get at the data structures to control live trades on scheduled intervals. Interval1 between main cycles and Interval2 time to make my changes to the structures and get the CSV files ready for load into internal tables. I've tested this, it all works good, but certainly is not pretty.

Oh well, I'm not planning on ever selling this thing anyway! That would be dumb.

Now to fix my dangling trades problem...

t.

TickTime = TimeCurrent();

// scheduled internal table request servicing...
//
// associated variables: datetime LastTables (global initialized in init()), extern int TablesInterval1 / 2,
// bool StartTablesDump / Load (globals initialized to false), bool TablesRequestServiced (global initialized to false)
// semaphores: "DumpTables.on" and "LoadTables.on" are the filename semaphores

StartTablesDump = false;
StartTablesLoad = false;

if ( TickTime >= ( LastTables + TablesInterval1 ) )
{
if ( TickTime < ( LastTables + TablesInterval1 + TablesInterval2 ) )
{
// initially: check for "DumpTables.on" filename semaphore once per cycle

if ( !TablesRequestServiced )
{
TableRequestHandle = FileOpen( "DumpTables.on", FILE_READ );
if ( TableRequestHandle > 0 )
{
StartTablesDump = true;
FileClose( TableRequestHandle );
}
TablesRequestServiced = true;
}
}
else
{
// then check for "LoadTables.on" filename semaphore only once per cycle

TableRequestHandle = FileOpen( "LoadTables.on", FILE_READ );
if ( TableRequestHandle > 0 ) // (if we get a valid handle then the user request has been made)
{
StartTablesLoad = true;
FileClose( TableRequestHandle );
}
LastTables = LastTables + TablesInterval1;
TablesRequestServiced = false;
}
}

if ( StartTablesDump )
{
if ( DumpFancyTT )
DumpTTbl( false );
if ( DumpFancyVLT )
DumpVLTbl( false );
if ( DumpFancyOSPT )
DumpOSPTbl( false );

if ( DumpPlainTT )
DumpTTbl( true );
if ( DumpPlainVLT )
DumpVLTbl( true );
if ( DumpPlainOSPT )
DumpOSPTbl( true );
}

if ( StartTablesLoad )
{
if ( LoadTT )
LoadTTbl();
if ( LoadVLT )
LoadVLTbl();
if ( LoadOSPT )
LoadOSPTbl();
}

 
tbuitendyk:

Are you SURE that you are correct? Pehaps you were not aware that DeInit is called when properties are changed on a live EA?

I am sure about what I have written, which was an answer to what u asked. Perhaps I did not go into enough details, but since your question was so trivial, I assumed you have just started with MQL4 and did not want to burden u with too many details. Anyway, had u had more specific questions I would gladly answer them.

I am well aware that Deinit() is called and all the different problems associated with the behavior of extern params. Here are just some of the threads I remember discussing the subject -> https://www.mql5.com/en/forum/119716, https://www.mql5.com/en/forum/123535, https://www.mql5.com/en/forum/123553, and I am sure there are many others.


In my experience, as soon as you hit OK on the EA parameters box DeInit is called, followed by Init, followed by Start on the next tick. Is it not correct that all variables with the exception of terminal level globals (i.e., NOT EA level globals) are wiped out when DeInit runs as by definition this means that the EA is being unloaded?!?

tbuit, u don't need experience to know this. Have u bothered reading the book? The documentation?? It's specifically stated in both. Please read this ->MQL4 Reference -> Program Run.

To answer your question - all global level variables and static variables (including all arrays which are static by default) retain their value through EA deinit(). Normal function level variables (including in the function start()) are reinitialized. Extern variables are reinitialized back to the value they had the last time the user opened the properties window (which can cause problems in experts that change extern variable values via code).


...by definition this means that the EA is being unloaded?!?

NO! Did u know that even changing the time-scale of a chart causes the expert to deinit()? An expert going through a deinit() -> init() -> start() is nothing special and should be considered in the EA development.

An EA is 'unloaded' when the Terminal is closed (gracefully/ungracefully) or when the expert is detached from chart by the user. In these cases some kind of persistence level needs to be added to the expert in order for it to continue.


A word of warning before following gordon's advice everyone: You may find MetaTrader's behaviour is to UNLOAD your EA and RELOAD it, just like I found. That could be bad for your open positions.

Don't worry about other people. Most of them are well aware of this behavior because they bothered reading the book. The fact that u did not test your expert thoroughly on a Demo before rushing to put money on it is the cause of your current situation. Just think of the money lost, as a lesson learned!

 
tbuitendyk:

Well anyway, I've gone with plan 'A' which was to control my EA by scheduled response to user request for the internal tables....

There is really no reason for this. The properties window was designed so u can change extern parameters value DURING expert run. All u need is to design your expert to continue running through a deint(). It's really not that difficult (much easier and more reliable then what u r doing now). Anyway, good luck.

 
gordon wrote >>

I am sure about what I have written, which was an answer to what u asked. Perhaps I did not go into enough details, but since your question was so trivial, I assumed...

There's the problem in a nutshell. I guess assuming my 2,500 line init function is trivial was your first mistake.

t.

And by the way, thanks for assuming that I have not read the documentation. Maybe I'm not as bright as you think you are and don't retain 110% of everything I read... but I do think it's worth worrying about other people when I comment.

I guess running in forward testing and backtesting for about 3 months before commiting any money to my account does not qualify as sufficient backtesting. Did it occur to you that I may have done extensive backtesting and forward demo account testing but did not have need to change variables while hot before?

I guess not. That's the trouble with assuming things.

Reason: