Restarting Expert Advisers Remotley using Pending Orders

Introduction

From time to time, I need to give a "kick" to an Expert Adviser I am running and restart it, thus freeing up it resources and initializing its logic. But, I am not always able to login into the machine its running on remotely and do it. Sometime the connectivity is not strong enough or the firewall doesn't allow using remote logic.


How did I solve it? Using pending buy orders with specific open price to initiate a certain work flow on the Expert side. Which means a set of commands which are read and actioned on remotely.

Remote Control Library

To create modularity and avoid changing all the advisers using this functionality. I created a library called RemoteControl.mqh to have all of the relevant functions. Specifically, to restart an expert remotely, I will enforce the expert to apply a template on the chart its running in which will force an exit and a restart.

I do so by creating the following case:

case RC_RESTART_EXPERT:
{
if(CloseOrder(OrderTicket(), OrderLots())==false)
Log(StringConcatenate("Failed closing remote instruction message, please close manually instruction ",(int)DoubleToString(OrderOpenPrice())),true,GetLastError());

Log("Restarting the expert adviser");
if(ChartApplyTemplate(ChartID(),StringConcatenate(MQLInfoString(MQL_PROGRAM_NAME),".tpl"))==true)
Log(StringConcatenate(MQLInfoString(MQL_PROGRAM_NAME)," restarted successfully"));
else
Log(StringConcatenate("Failed applying ",MQLInfoString(MQL_PROGRAM_NAME),", template, please restart manually"),true,GetLastError());

break;
}

with the constant #define RC_RESTART_EXPERT 10005

and functions:
void Log(string argMessage,bool argSendNotificationFlag=true,int argErrorCode=0) export
{
if(argErrorCode!=0)
{
argMessage=StringConcatenate(argMessage,", Error: ",argErrorCode," - ",ErrorDescription(argErrorCode));

if(TerminalInfoInteger(TERMINAL_EMAIL_ENABLED))
SendMail(StringConcatenate("Something went wrong with ",MQLInfoString(MQL_PROGRAM_NAME)),argMessage);
}

Print(StringConcatenate(AccountServer(),", ",IntegerToString(AccountNumber()),", ",MQLInfoString(MQL_PROGRAM_NAME),", ",Symbol()," ",argMessage,", Balance = ",DoubleToString(AccountBalance(),2)," ",AccountCurrency(),", P&L = ",DoubleToString(AccountProfit(),2)," ",AccountCurrency(),", Equity = ",DoubleToString(AccountEquity(),2)," ",AccountCurrency(),", Margin = ",DoubleToString(AccountMargin(),2)," ",AccountCurrency(),", Margin (%) = ",DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN_LEVEL),2),"%"));

if(argSendNotificationFlag==true)
SendNotification(StringConcatenate(AccountServer(),", ",IntegerToString(AccountNumber()),", ",MQLInfoString(MQL_PROGRAM_NAME),", ",Symbol()," ",argMessage,", Balance = ",DoubleToString(AccountBalance(),2)," ",AccountCurrency(),", P&L = ",DoubleToString(AccountProfit(),2)," ",AccountCurrency(),", Equity = ",DoubleToString(AccountEquity(),2)," ",AccountCurrency(),", Margin = ",DoubleToString(AccountMargin(),2)," ",AccountCurrency(),", Margin (%) = ",DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN_LEVEL),2),"%"));
}

and

bool CloseOrder(int argOrder,double argLotSize) export
{
if(OrderSelect(argOrder,SELECT_BY_TICKET) && OrderCloseTime()==0)
{
if(OrderType()!=OP_BUY && OrderType()!=OP_SELL)
return ClosePendingOrder(argOrder);
else if(OrderCloseTime()==0 && OrderClose(argOrder,VerifyLotSize(OrderSymbol(),argLotSize),OrderType()==OP_BUY?MarketInfo(OrderSymbol(),MODE_BID):MarketInfo(OrderSymbol(),MODE_ASK),Slippage,OrderType()==OP_BUY?clrGreen:clrRed)==false)
{
Log(StringConcatenate("Closing order #",argOrder," failed, verified lot size = ",VerifyLotSize(OrderSymbol(),argLotSize)),false,GetLastError());

return false;
}
}
else
{
Log(StringConcatenate("Closing order failed selecting order #",argOrder,", verified lot size = ",VerifyLotSize(OrderSymbol(),argLotSize)),false,GetLastError());
return false;
}

return true;
}

To use this functionality, I added an integer tracking the orders number, every time it changes, I run through the open orders and check whether there is an open pending buy order with the pending price equal to 10005.If that is the case, the expert will call the apple template exit and install itself without the need to login to the VPS:
if(OrdersNumber!=OrdersTotal())
{
ProcessRemoteInstructions();

OrdersNumber=OrdersTotal();
}

Where
void ProcessRemoteInstructions() export
{
for(int i=OrdersTotal()-1;i>=0;i--)

if(OrderSelect(i,SELECT_BY_POS) && StringCompare(Symbol(),OrderSymbol())==0 && OrderType()==OP_BUYSTOP)
{
switch((int)OrderOpenPrice())

With this, I am able to anywhere I want, once I see the expert is misbehaving or the market conditions caused it to get out of balance, I open a pending buy stop with 10005 as pending price and let the expert pick it up and restart:


The final step after adding this code to your expert advisers, is saving a template with the same name as the expert adviser you wish to monitor:




As usual, free free to reach out to me by https://t.me/roymeshulam if you have any questions about my code or trading experience and don't forget to follow me at https://twitter.com/roymeshulam

Comments