dingmaotu / mt4-server

Turn MetaTrader Terminal into a Redis compatible server with ZMQ sockets
Apache License 2.0
163 stars 94 forks source link

How to send trades commands with SL and TP #5

Open ildeb opened 4 years ago

ildeb commented 4 years ago

Hi, I would like to know if there is a way to set the parameters of a trading order via the redis client. In particular to the SL, TP, comments and the magic number. Thank you very much!

ildeb commented 4 years ago

I tried to edit the MqlCommand.mqh file to add a comment to the BUY order comand. Obviously it didn't work because I don't know how the library is structured.

Original file:

//+------------------------------------------------------------------+
//| Buy at market price                                              |
//| Syntax: BUY Symbol Lots                                          |
//| Results:                                                         |
//|   Success: Order id (RespInteger)                                |
//|   Fail:    RespError                                             |
//+------------------------------------------------------------------+
class BuyCommand: public MqlCommand
  {
public:
   RespValue        *call(const RespArray &command)
     {
      if(command.size()!=3) return new RespError("Invalid number of arguments for command BUY!");
      string symbol=dynamic_cast<RespBytes*>(command[1]).getValueAsString();
      double lots=StringToDouble(dynamic_cast<RespBytes*>(command[2]).getValueAsString());
      int id=OrderSend(symbol,OP_BUY,lots,FxSymbol::getAsk(symbol),3,0,0,NULL,0,0,clrNONE);
      if(id==-1)
        {
         int ec=Mql::getLastError();
         return new RespError(StringFormat("Failed to buy at market with error id (%d): %s",
                              ec,Mql::getErrorMessage(ec)));
        }
      else
        {
         return new RespInteger(id);
        }
     }
};

Modified file:

//+------------------------------------------------------------------+
//| Buy at market price                                              |
//| Syntax: BUY Symbol Lots                                          |
//| Results:                                                         |
//|   Success: Order id (RespInteger)                                |
//|   Fail:    RespError                                             |
//+------------------------------------------------------------------+
class BuyCommand: public MqlCommand
  {
public:
   RespValue        *call(const RespArray &command)
     {
      if(command.size()!=4) return new RespError("Invalid number of arguments for command BUY!");
      string symbol=dynamic_cast<RespBytes*>(command[1]).getValueAsString();
      double lots=StringToDouble(dynamic_cast<RespBytes*>(command[2]).getValueAsString());
      string comment=dynamic_cast<RespBytes*>(command[3]).getValueAsString();
      int id=OrderSend(symbol,OP_BUY,lots,FxSymbol::getAsk(symbol),3,0,0,comment,0,0,clrNONE);
      if(id==-1)
        {
         int ec=Mql::getLastError();
         return new RespError(StringFormat("Failed to buy at market with error id (%d): %s",
                              ec,Mql::getErrorMessage(ec)));
        }
      else
        {
         return new RespInteger(id);
        }
     }
  };

Result:

Schermata 2019-11-29 alle 12 14 57
ajax417 commented 4 years ago

@ildeb I just did this too, you are in the right file. what I did was modify it to take 3-5 parameters you could just make it always need five (SL & TP) see the first line of code. Then I parsed the fourth and fifth parameters if they are present, and added them to the OrderSend call. This way they are both optional.

the line int id=OrderSend(symbol,OP_BUY,lots,FxSymbol::getAsk(symbol),3,SL,TP,NULL,0,0,clrNONE); is where you would add your SL and TP values.

I hope this helps.

if(command.size() < 3 || command.size() > 5)
         return new RespError("Invalid number of arguments for command BUY!");
      string symbol=dynamic_cast<RespBytes*>(command[1]).getValueAsString();

      double SL = 0;
      // We know if it is greater then 3 we have a S/L
      if(command.size() > 3)
        {
        SL = StringToDouble(dynamic_cast<RespBytes*>(command[3]).getValueAsString());
        }

      double TP = 0;
      // We know if it is greater then 4 we have a T/P
      if(command.size() > 4)
        {
        TP = StringToDouble(dynamic_cast<RespBytes*>(command[4]).getValueAsString());
        }
      double lots=StringToDouble(dynamic_cast<RespBytes*>(command[2]).getValueAsString());
      int id=OrderSend(symbol,OP_BUY,lots,FxSymbol::getAsk(symbol),3,SL,TP,NULL,0,0,clrNONE);

note you will have to make an identical change under the sell order class further down in the file

ajax417 commented 4 years ago

My bad I read your a post a little more closely, In your MT4 installation folder you will have a Scripts folder with Mt4ServerRaw.mq4 and CommandProcessor.mqh in there. You will need to recompile the Mt4ServerRaw.mq4 to have the change take effect.