MT4 to Ctrader Trade copier using .csv file communicate

Created at 26 May 2020, 09:39
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
VH

VHS10

Joined 25.04.2020

MT4 to Ctrader Trade copier using .csv file communicate
26 May 2020, 09:39


Hello there,

I have the MT4 trade sender EA that sends orders to a file named TradeCopy.csv in the MQL directory on my computers hard-drive. Which appears to be working just fine

however i also have a Ctrader Cbot that is supposed to read this TradeCopy.csv and take orders from it but it doesn't seem to be working despite the fact that the file path in the code is correct.

Please take a look at the two codes.

The first one is the MT4 Trade sender EA

int delay=1000;
int start,TickCount;
int Size=0,PrevSize=0;
int cnt,TotalCounter;
string cmt;
string nl="\n";

int OrdId[],PrevOrdId[];
string OrdSym[],PrevOrdSym[];
int OrdTyp[],PrevOrdTyp[];
double OrdLot[],PrevOrdLot[];
double OrdPrice[],PrevOrdPrice[];
double OrdSL[],PrevOrdSL[];
double OrdTP[],PrevOrdTP[];


//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start() {

  while(!IsStopped()) {
    start=GetTickCount();
    cmt=start+nl+"Counter: "+TotalCounter;
    get_positions();
    if(compare_positions()) save_positions();
    Comment(cmt);
    TickCount=GetTickCount()-start;
    if(delay>TickCount)Sleep(delay-TickCount-2);
  }
  Alert("end, TradeCopy EA stopped");
  Comment("");
  return(0);


//----

}


void get_positions() {
  Size=OrdersTotal();
  if (Size!= PrevSize) {
    ArrayResize(OrdId,Size);
    ArrayResize(OrdSym,Size);
    ArrayResize(OrdTyp,Size);
    ArrayResize(OrdLot,Size);
    ArrayResize(OrdPrice,Size);
    ArrayResize(OrdSL,Size);
    ArrayResize(OrdTP,Size);
  }

  for(int cnt=0;cnt<Size;cnt++) {
    OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
    OrdId[cnt]=OrderTicket();
    OrdSym[cnt]=OrderSymbol();
    OrdTyp[cnt]=OrderType();
    OrdLot[cnt]=OrderLots();
    OrdPrice[cnt]=OrderOpenPrice();
    OrdSL[cnt]=OrderStopLoss();
    OrdTP[cnt]=OrderTakeProfit();
  }  
  cmt=cmt+nl+"Size: "+Size;  
}   
   
bool compare_positions() {
  if (PrevSize != Size)return(true);
  for(int i=0;i<Size;i++) {
    if (PrevOrdSL[i]!=OrdSL[i])return(true);
    if (PrevOrdTP[i]!=OrdTP[i])return(true);
    if (PrevOrdPrice[i]!=OrdPrice[i])return(true);
    if (PrevOrdId[i]!=OrdId[i])return(true);
    if (PrevOrdSym[i]!=OrdSym[i])return(true);
    if (PrevOrdPrice[i]!=OrdPrice[i])return(true);
    if (PrevOrdLot[i]!=OrdLot[i])return(true);
    if (PrevOrdTyp[i]!=OrdTyp[i])return(true);
  }    
  return(false);
}

void save_positions() {

  if (PrevSize != Size) {
    ArrayResize(PrevOrdId,Size);
    ArrayResize(PrevOrdSym,Size);
    ArrayResize(PrevOrdTyp,Size);
    ArrayResize(PrevOrdLot,Size);
    ArrayResize(PrevOrdPrice,Size);
    ArrayResize(PrevOrdSL,Size);
    ArrayResize(PrevOrdTP,Size);
    PrevSize=Size;
  }
  
  
  for(int i=0;i<Size;i++) {
    PrevOrdId[i]=OrdId[i];
    PrevOrdSym[i]=OrdSym[i];
    PrevOrdTyp[i]=OrdTyp[i];
    PrevOrdLot[i]=OrdLot[i];
    PrevOrdPrice[i]=OrdPrice[i];
    PrevOrdSL[i]=OrdSL[i];
    PrevOrdTP[i]=OrdTP[i];
  }


  int handle=FileOpen("TradeCopy.csv",FILE_CSV|FILE_WRITE,",");
  if(handle>0) {
    FileWrite(handle,TotalCounter);
    TotalCounter++;
    for(i=0;i<Size;i++) {
      FileWrite(handle,OrdId[i],OrdSym[i],OrdTyp[i],OrdLot[i],OrdPrice[i],OrdSL[i],OrdTP[i]);
    }
    FileClose(handle);
  }else Print("File open has failed, error: ",GetLastError());
}

 

This is for the Ctrader Cbot receiver

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo
{

    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    //AccessRights.FullAccess

    public class MT2cTrader : Robot
    {

        [Parameter("Orders Input File Path", DefaultValue = "C:\\Users\\trader\\AppData\\Roaming\\MetaQuotes\\Terminal\\69420FB8433504FEA0FA029C390238DB\\MQL4\\Files\\TradeCopy.csv")]
        // C:\\Users\\trader\\CSV\\TradeCopy.csv

        public string orders_input_file { get; set; }

        [Parameter("Slippage", DefaultValue = 3.5)]
        public double slippage { get; set; }


        [Parameter("Delimiter", DefaultValue = ";")]
        public string delimiter { get; set; }

        protected override void OnStart()
        {

        }

        private bool debug = true;

        protected override void OnTick()
        {
            //todo, check M.D.
            //price = marketDepth.AskEntries[0].Price; 
            //volume = marketDepth.AskEntries[0].Volume;

            string[] lines = new String[0];

            try
            {
                lines = File.ReadAllLines(orders_input_file);

            } catch (Exception e)
            {
                Print("Exception: " + e.Message);

                return;
            }

            List<string> existing_positions = new List<string>();

            foreach (string line in lines)
            {

                OrderData order = new OrderData(line.Split(delimiter.Length > 0 ? delimiter[0] : ','), MarketData);
                existing_positions.Add(order.label);

                if (debug)
                    Print(line);

                if (order.isCorrect() && (Positions.Find(order.label) == null))
                    ExecuteMarketOrder(order.type, order.symbol, order.lot, order.label, order.sl, order.tp, slippage);
            }

            for (int pos = 0; pos < Positions.Count; pos++)
                if (!existing_positions.Contains(Positions[pos].Label))
                    ClosePosition(Positions[pos]);
        }

    }

    public class OrderData
    {

        private const long mt_lot_coefficient = 100000;
        //corrected_100000_july1
        public Symbol symbol;
        public TradeType type;
        public long lot;
        public int sl;
        public int tp;
        public string label;
        private bool initialized_properly = true;

        public OrderData(string[] raw_pieces, MarketData market_data)
        {
            try
            {
                this.label = raw_pieces[0].Trim();
                this.symbol = market_data.GetSymbol(raw_pieces[1].Trim());
                this.setType(Convert.ToInt32(raw_pieces[2].Trim()));
                this.lot = Convert.ToInt64(this.parseDouble(raw_pieces[3]) * mt_lot_coefficient);
                double price = this.parseDouble(raw_pieces[4]);
                this.sl = this.getPipDistance(price, this.parseDouble(raw_pieces[5]));
                this.tp = this.getPipDistance(price, this.parseDouble(raw_pieces[6]));
            } catch (Exception e)
            {
                return;
            }

            {
                this.initialized_properly = false;
            }
        }

        public bool isCorrect()
        {
            return this.initialized_properly;
        }

        private double parseDouble(string value)
        {
            return double.Parse(value.Trim().Replace(',', '.'), System.Globalization.CultureInfo.InvariantCulture);
        }





        private void setType(int mt_type)
        {
            this.type = mt_type == 0 ? TradeType.Buy : TradeType.Sell;
        }

        private int getPipDistance(double basic_price, double close_price)
        {
            return Convert.ToInt32(Math.Round(Math.Abs(basic_price - close_price) / this.symbol.PipSize));
        }

    }

}

 


@VHS10
Replies

firemyst
28 May 2020, 07:38

RE: MT4 to Ctrader Trade Copier using .csv to communicate

Does it print out an exception?

 

If not, after you read the file in, print out a random line number (like 5) to the log and see if it prints anything.

this will at least confirm whether or not it's reading the file in.


@firemyst

VHS10
28 May 2020, 09:40

RE: RE: MT4 to Ctrader Trade Copier using .csv to communicate

firemyst said:

Does it print out an exception?

 

If not, after you read the file in, print out a random line number (like 5) to the log and see if it prints anything.

this will at least confirm whether or not it's reading the file in.

I appreciate your response,

This is the error message that generates right before the bot crashes.

28/05/2020 06:33:44.134 | New cBot, EURUSD, m1 | Crashed in OnTick with NullReferenceException: Object reference not set to an instance of an object.

This error comes after the log prints out number one (1). so that confirms it's reading the file in


@VHS10