diff --git a/MT4socketAPI/Asset.cs b/MT4socketAPI/Asset.cs index 71bea0f..6a3d30e 100644 --- a/MT4socketAPI/Asset.cs +++ b/MT4socketAPI/Asset.cs @@ -7,7 +7,7 @@ namespace MTsocketAPI.MT4 { - public class Asset + public class Asset { //public string MSG { get; set; } public string NAME { get; set; } @@ -39,7 +39,9 @@ public class Asset public string CURRENCY_MARGIN { get; set; } public string DESCRIPTION { get; set; } public string PATH { get; set; } - public override string ToString() + public List> SESSION_QUOTE { get; set; } + public List> SESSION_TRADE { get; set; } + public override string ToString() { return JsonConvert.SerializeObject(this); } diff --git a/MT4socketAPI/MTsocketAPI4.csproj b/MT4socketAPI/MTsocketAPI4.csproj index d3a3b53..80f83c4 100644 --- a/MT4socketAPI/MTsocketAPI4.csproj +++ b/MT4socketAPI/MTsocketAPI4.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 enable enable diff --git a/MT4socketAPI/Quote.cs b/MT4socketAPI/Quote.cs index 33433c5..fcbbc52 100644 --- a/MT4socketAPI/Quote.cs +++ b/MT4socketAPI/Quote.cs @@ -1,6 +1,7 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -33,4 +34,18 @@ public override string ToString() return JsonConvert.SerializeObject(this); } } + + public class OHLC_Req + { + //public string MSG { get; set; } + [Required] + public string SYMBOL { get; set; } + [Required] + public TimeFrame TIMEFRAME { get; set; } + public int? DEPTH { get; set; } + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + } } diff --git a/MT4socketAPI/Terminal.cs b/MT4socketAPI/Terminal.cs index de6594a..bbe3ffe 100644 --- a/MT4socketAPI/Terminal.cs +++ b/MT4socketAPI/Terminal.cs @@ -46,569 +46,698 @@ public enum Applied_Price PRICE_TYPICAL, PRICE_WEIGHTED } - public class Terminal - { - public string host = "localhost"; - public int cmd_port = 77; - public int data_port = 78; - static int bufferLen = 8192; - - //public int Product = 0; - - TcpClient tcpClient_cmd; - TcpClient tcpClient_data; - - public event EventHandler OnConnect; - public event EventHandler OnDisconnect; - public event EventHandler OnPrice; - public event EventHandler OnOHLC; - - public string Version { get; set; } - - public JObject SendCommand(JObject cmd) - { - JObject jresult; - - string responseData = string.Empty; - - try - { - byte[] data = Encoding.ASCII.GetBytes(cmd.ToString(Formatting.None) + "\r\n"); - - NetworkStream stream = tcpClient_cmd.GetStream(); - - stream.Write(data, 0, data.Length); - - data = new byte[bufferLen]; - - int bytes; - do - { - bytes = stream.Read(data, 0, bufferLen); - responseData += Encoding.ASCII.GetString(data, 0, bytes); - } while (stream.DataAvailable); - - jresult = JsonConvert.DeserializeObject(responseData); - - //stream.Close(); - //tcpClient_cmd.Close(); - - return jresult; - } - catch (Exception ex) - { - throw new FormatException(ex.Message); - } - } - - private void ListenMTData() - { - Thread listen = new Thread(() => ListenMTDataStream()); - listen.IsBackground = true; - listen.Start(); - } - - private void ListenMTDataStream() - { - int bytes; - byte[] data = new byte[bufferLen]; - - NetworkStream stream = tcpClient_data.GetStream(); - - do - { - string responseData = string.Empty; - - do - { - bytes = stream.Read(data, 0, data.Length); - responseData += Encoding.ASCII.GetString(data, 0, bytes); - } while (stream.DataAvailable); - - responseData.Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList().ForEach( - line => { - JObject jresult = JObject.Parse(line); - if (jresult["MSG"].ToString() == "TRACK_PRICES") - { - Quote price = JsonConvert.DeserializeObject(line); - if (OnPrice != null) OnPrice(this, price); - } - else if (jresult["MSG"].ToString() == "TRACK_OHLC") - { - OHLC_Msg price = JsonConvert.DeserializeObject(line); - if (OnOHLC != null) OnOHLC(this, price); - } - }); - } while (true); - } - - public bool Connect(string host = "localhost", int cmd_port = 77, int data_port = 78) - { - try - { - tcpClient_cmd = new TcpClient(host, cmd_port); - tcpClient_data = new TcpClient(host, data_port); - - ListenMTData(); - - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "VERSION"; - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - Version = res["NUMBER"].ToString(); - - if (Convert.ToDouble(Version) < 4.1) - { - throw new Exception("This API version needs at least MTsocketAPI 4.1 version"); - } - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception ex) - { - throw new Exception(ex.Message); - } - - if (OnConnect != null) OnConnect(this, new EventArgs()); - return true; - } - - public TerminalInfo GetTerminalInfo() - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "TERMINAL_INFO"; - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject(res.ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - public AccountStatus GetAccountStatus() - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "ACCOUNT_STATUS"; - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject(res.ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - public List GetOrderList() - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "ORDER_LIST"; - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject>(res["TRADES"].ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - public double MA_Indicator(string Symbol, TimeFrame tf, int MA_Period, int MA_Shift, MA_Method MA_Method, Applied_Price Applied_Price, int Shift) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "MA_INDICATOR"; - json_cmd["SYMBOL"] = Symbol; - json_cmd["TIMEFRAME"] = tf.ToString(); - json_cmd["MA_PERIOD"] = MA_Period; - json_cmd["MA_SHIFT"] = MA_Shift; - json_cmd["MA_METHOD"] = MA_Method.ToString(); - json_cmd["APPLIED_PRICE"] = Applied_Price.ToString(); - json_cmd["SHIFT"] = Shift; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return Convert.ToDouble(res["DATA_VALUE"]); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - public double ATR_Indicator(string Symbol, TimeFrame tf, int Period, int Shift) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "ATR_INDICATOR"; - json_cmd["SYMBOL"] = Symbol; - json_cmd["TIMEFRAME"] = tf.ToString(); - json_cmd["PERIOD"] = Period; - json_cmd["SHIFT"] = Shift; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return Convert.ToDouble(res["DATA_VALUE"]); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - public double Custom_Indicator(string Symbol, TimeFrame tf, string Indicator_Name, int Mode, int Shift, List Param = null) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "CUSTOM_INDICATOR"; - json_cmd["SYMBOL"] = Symbol; - json_cmd["TIMEFRAME"] = tf.ToString(); - json_cmd["INDICATOR_NAME"] = Indicator_Name; - json_cmd["MODE"] = Mode; - json_cmd["SHIFT"] = Shift; - - if (Param != null) - { - switch (Param.Count) - { - case 4: - json_cmd["PARAM1"] = Convert.ToDouble(Param[0]); - json_cmd["PARAM2"] = Convert.ToDouble(Param[1]); - json_cmd["PARAM3"] = Convert.ToDouble(Param[2]); - json_cmd["PARAM4"] = Convert.ToDouble(Param[3]); - break; - case 3: - json_cmd["PARAM1"] = Convert.ToDouble(Param[0]); - json_cmd["PARAM2"] = Convert.ToDouble(Param[1]); - json_cmd["PARAM3"] = Convert.ToDouble(Param[2]); - break; - case 2: - json_cmd["PARAM1"] = Convert.ToDouble(Param[0]); - json_cmd["PARAM2"] = Convert.ToDouble(Param[1]); - break; - case 1: - json_cmd["PARAM1"] = Convert.ToDouble(Param[0]); - break; - } - } - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return Convert.ToDouble(res["DATA_VALUE"]); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - public long SendOrder(string Symbol, double Volume, OrderType Type, double Price = 0, double SL = 0, double TP = 0, double Slippage = 0, string Comment = "", int MagicNr = 0, string Expiration = "1970/01/01 00:00") - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "ORDER_SEND"; - json_cmd["SYMBOL"] = Symbol; - json_cmd["VOLUME"] = Volume; - json_cmd["TYPE"] = Type.ToString(); - if (SL > 0) json_cmd["SL"] = SL; - if (TP > 0) json_cmd["TP"] = TP; - if (Price > 0) json_cmd["PRICE"] = Price; - if (Slippage > 0) json_cmd["SLIPPAGE"] = Slippage; - if (Comment != "") json_cmd["COMMENT"] = Comment; - if (MagicNr > 0) json_cmd["MAGICNR"] = MagicNr; - if (Expiration != "1970/01/01 00:00") json_cmd["EXPIRATION"] = Expiration; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return Convert.ToInt32(res["TICKET"].ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - - throw; - } - } - - public bool OrderModify(long Ticket, double SL = 0, double TP = 0) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "ORDER_MODIFY"; - json_cmd["TICKET"] = Ticket; - if (SL > 0) json_cmd["SL"] = SL; - if (TP != 0) json_cmd["TP"] = TP; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return true; - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - public string OrderClose(long Ticket, double Volume = 0, double Price = 0, double Slippage = 0) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "ORDER_CLOSE"; - json_cmd["TICKET"] = Ticket; - if (Volume > 0) json_cmd["VOLUME"] = Volume; - if (Price != 0) json_cmd["PRICE"] = Price; - if (Slippage != 0) json_cmd["SLIPPAGE"] = Slippage; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return res["TYPE"].ToString();//JsonConvert.DeserializeObject(res.ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - public List GetSymbolList() - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "SYMBOL_LIST"; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject>(res["SYMBOLS"].ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - public Asset GetSymbolInfo(string Symbol) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "SYMBOL_INFO"; - json_cmd["SYMBOL"] = Symbol; - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject(res.ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - public Quote GetQuote(string Symbol) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "QUOTE"; - json_cmd["SYMBOL"] = Symbol; - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject(res.ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - public List PriceHistory(string Symbol, TimeFrame tf, DateTime From, DateTime To) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "PRICE_HISTORY"; - json_cmd["SYMBOL"] = Symbol; - json_cmd["TIMEFRAME"] = tf.ToString(); - json_cmd["FROM_DATE"] = From.ToString("yyyy.MM.dd HH:mm"); - json_cmd["TO_DATE"] = To.ToString("yyyy.MM.dd HH:mm"); - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject>(res["RATES"].ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - public bool TrackPrices(List symbols) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "TRACK_PRICES"; - - JArray ja = new JArray(); - foreach (string symbol in symbols) - ja.Add(symbol); - - json_cmd["SYMBOLS"] = ja; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return true; - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - public bool TrackOHLC(List symbols, TimeFrame tf) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "TRACK_OHLC"; - json_cmd["TIMEFRAME"] = tf.ToString(); - - JArray ja = new JArray(); - foreach (string symbol in symbols) - ja.Add(symbol); - - json_cmd["SYMBOLS"] = ja; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return true; - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - } + + public interface ITerminal + { + string Version { get; set; } + + event EventHandler OnConnect; + event EventHandler OnDisconnect; + event EventHandler OnOHLC; + event EventHandler OnPrice; + + double ATR_Indicator(string Symbol, TimeFrame tf, int Period, int Shift); + bool Connect(string host = "localhost", int cmd_port = 71, int data_port = 72); + double Custom_Indicator(string Symbol, TimeFrame tf, string Indicator_Name, int Mode, int Shift, List Params = null); + AccountStatus GetAccountStatus(); + List GetOrderList(); + List GetOrderHistory(DateTime From, DateTime To); + Quote GetQuote(string Symbol); + Asset GetSymbolInfo(string Symbol); + List GetSymbolList(); + TerminalInfo GetTerminalInfo(); + double MA_Indicator(string Symbol, TimeFrame tf, int MA_Period, int MA_Shift, MA_Method MA_Method, Applied_Price Applied_Price, int Shift); + string OrderClose(long Ticket, double Volume = 0, double Price = 0, double Slippage = 0); + bool OrderModify(long Ticket, double SL = 0, double TP = 0); + List PriceHistory(string Symbol, TimeFrame tf, DateTime From, DateTime To); + JObject SendCommand(JObject cmd); + Task SendCommandAsync(string host, int port, JObject cmd); + long SendOrder(string Symbol, double Volume, OrderType Type, double Price = 0, double SL = 0, double TP = 0, double Slippage = 0, string Comment = "", int MagicNr = 0, string Expiration = "1970/01/01 00:00"); + bool TrackOHLC(List ohlc_request); + bool TrackPrices(List symbols); + bool TrackPrices(List symbols); + } + + public class Terminal : ITerminal + { + public string host = "127.0.0.1"; + public int cmd_port = 77; + public int data_port = 78; + static int bufferLen = 8192; + + //public int Product = 0; + + TcpClient tcpClient_cmd; + TcpClient tcpClient_data; + + public event EventHandler OnConnect; + public event EventHandler OnDisconnect; + public event EventHandler OnPrice; + public event EventHandler OnOHLC; + + public string Version { get; set; } + + public JObject SendCommand(JObject cmd) + { + JObject jresult; + + string responseData = string.Empty; + + try + { + byte[] data = Encoding.ASCII.GetBytes(cmd.ToString(Formatting.None) + "\r\n"); + + NetworkStream stream = tcpClient_cmd.GetStream(); + + stream.Write(data, 0, data.Length); + + data = new byte[bufferLen]; + + int bytes; + do + { + bytes = stream.Read(data, 0, bufferLen); + responseData += Encoding.ASCII.GetString(data, 0, bytes); + } while (stream.DataAvailable); + + jresult = JsonConvert.DeserializeObject(responseData); + + return jresult; + } + catch (Exception ex) + { + throw new FormatException(ex.Message); + } + } + + public async Task SendCommandAsync(string host, int port, JObject cmd) + { + try + { + byte[] data = Encoding.ASCII.GetBytes(cmd.ToString(Formatting.None) + "\r\n"); + + if (tcpClient_cmd == null || tcpClient_cmd.Connected == false) + { + tcpClient_cmd = new TcpClient(); + await tcpClient_cmd.ConnectAsync(host, port); + } + + NetworkStream stream = tcpClient_cmd.GetStream(); + stream.ReadTimeout = 3000; + await stream.WriteAsync(data, 0, data.Length); + + data = new byte[bufferLen]; + + string responseData = string.Empty; + + int bytes; + do + { + bytes = await stream.ReadAsync(data, 0, bufferLen); + responseData += Encoding.ASCII.GetString(data, 0, bytes); + } while (stream.DataAvailable || !responseData.EndsWith("\r\n")); + + JObject? jresult = JsonConvert.DeserializeObject(responseData); + + tcpClient_cmd.Close(); + + if (jresult != null) + return jresult; + else + throw new Exception("Error with deserialization in SendCommand"); + } + catch (Exception) + { + throw; + } + + } + + private void ListenMTData() + { + Thread listen = new Thread(() => ListenMTDataStream()); + listen.IsBackground = true; + listen.Start(); + } + + private void ListenMTDataStream() + { + int bytes; + byte[] data = new byte[bufferLen]; + + NetworkStream stream = tcpClient_data.GetStream(); + + do + { + string responseData = string.Empty; + + do + { + bytes = stream.Read(data, 0, data.Length); + responseData += Encoding.ASCII.GetString(data, 0, bytes); + } while (stream.DataAvailable); + + responseData.Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList().ForEach( + line => + { + JObject jresult = JObject.Parse(line); + if (jresult["MSG"].ToString() == "TRACK_PRICES") + { + Quote price = JsonConvert.DeserializeObject(line); + if (OnPrice != null) OnPrice(this, price); + } + else if (jresult["MSG"].ToString() == "TRACK_OHLC") + { + OHLC_Msg price = JsonConvert.DeserializeObject(line); + if (OnOHLC != null) OnOHLC(this, price); + } + }); + } while (true); + } + + public bool Connect(string host = "localhost", int cmd_port = 77, int data_port = 78) + { + try + { + tcpClient_cmd = new TcpClient(host, cmd_port); + tcpClient_data = new TcpClient(host, data_port); + + ListenMTData(); + + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "VERSION"; + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + Version = res["NUMBER"].ToString(); + + if (Convert.ToDouble(Version) < 4.1) + { + throw new Exception("This API version needs at least MTsocketAPI 4.1 version"); + } + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception ex) + { + throw new Exception(ex.Message); + } + + if (OnConnect != null) OnConnect(this, new EventArgs()); + return true; + } + + public TerminalInfo GetTerminalInfo() + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "TERMINAL_INFO"; + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject(res.ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + public AccountStatus GetAccountStatus() + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "ACCOUNT_STATUS"; + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject(res.ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + public List GetOrderList() + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "ORDER_LIST"; + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject>(res["TRADES"].ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + public List GetOrderHistory(DateTime From, DateTime To) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "TRADE_HISTORY"; + json_cmd["FROM_DATE"] = From.ToString("yyyy.MM.dd HH:mm"); + json_cmd["TO_DATE"] = To.ToString("yyyy.MM.dd HH:mm"); + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject>(res["TRADES"].ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + public double MA_Indicator(string Symbol, TimeFrame tf, int MA_Period, int MA_Shift, MA_Method MA_Method, Applied_Price Applied_Price, int Shift) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "MA_INDICATOR"; + json_cmd["SYMBOL"] = Symbol; + json_cmd["TIMEFRAME"] = tf.ToString(); + json_cmd["MA_PERIOD"] = MA_Period; + json_cmd["MA_SHIFT"] = MA_Shift; + json_cmd["MA_METHOD"] = MA_Method.ToString(); + json_cmd["APPLIED_PRICE"] = Applied_Price.ToString(); + json_cmd["SHIFT"] = Shift; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return Convert.ToDouble(res["DATA_VALUE"]); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + public double ATR_Indicator(string Symbol, TimeFrame tf, int Period, int Shift) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "ATR_INDICATOR"; + json_cmd["SYMBOL"] = Symbol; + json_cmd["TIMEFRAME"] = tf.ToString(); + json_cmd["PERIOD"] = Period; + json_cmd["SHIFT"] = Shift; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return Convert.ToDouble(res["DATA_VALUE"]); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + public double Custom_Indicator(string Symbol, TimeFrame tf, string Indicator_Name, int Mode, int Shift, List Params = null) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "CUSTOM_INDICATOR"; + json_cmd["SYMBOL"] = Symbol; + json_cmd["TIMEFRAME"] = tf.ToString(); + json_cmd["INDICATOR_NAME"] = Indicator_Name; + json_cmd["MODE"] = Mode; + json_cmd["SHIFT"] = Shift; + + int i = 1; + + foreach (var param in Params) + { + double valorD; + int valorI; + if (int.TryParse(param, out valorI)) + json_cmd["PARAM" + i.ToString()] = valorI; + else if (double.TryParse(param, out valorD)) + json_cmd["PARAM" + i.ToString()] = valorD; + else + json_cmd["PARAM" + i.ToString()] = param.ToString(); + + i++; + } + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return Convert.ToDouble(res["DATA_VALUE"]); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + public long SendOrder(string Symbol, double Volume, OrderType Type, double Price = 0, double SL = 0, double TP = 0, double Slippage = 0, string Comment = "", int MagicNr = 0, string Expiration = "1970/01/01 00:00") + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "ORDER_SEND"; + json_cmd["SYMBOL"] = Symbol; + json_cmd["VOLUME"] = Volume; + json_cmd["TYPE"] = Type.ToString(); + if (SL > 0) json_cmd["SL"] = SL; + if (TP > 0) json_cmd["TP"] = TP; + if (Price > 0) json_cmd["PRICE"] = Price; + if (Slippage > 0) json_cmd["SLIPPAGE"] = Slippage; + if (Comment != "") json_cmd["COMMENT"] = Comment; + if (MagicNr > 0) json_cmd["MAGICNR"] = MagicNr; + if (Expiration != "1970/01/01 00:00") json_cmd["EXPIRATION"] = Expiration; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return Convert.ToInt32(res["TICKET"].ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + + throw; + } + } + + public bool OrderModify(long Ticket, double SL = 0, double TP = 0) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "ORDER_MODIFY"; + json_cmd["TICKET"] = Ticket; + if (SL > 0) json_cmd["SL"] = SL; + if (TP != 0) json_cmd["TP"] = TP; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return true; + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + public string OrderClose(long Ticket, double Volume = 0, double Price = 0, double Slippage = 0) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "ORDER_CLOSE"; + json_cmd["TICKET"] = Ticket; + if (Volume > 0) json_cmd["VOLUME"] = Volume; + if (Price != 0) json_cmd["PRICE"] = Price; + if (Slippage != 0) json_cmd["SLIPPAGE"] = Slippage; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return res["TYPE"].ToString(); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + public List GetSymbolList() + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "SYMBOL_LIST"; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject>(res["SYMBOLS"].ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + public Asset GetSymbolInfo(string Symbol) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "SYMBOL_INFO"; + json_cmd["SYMBOL"] = Symbol; + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject(res.ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + public Quote GetQuote(string Symbol) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "QUOTE"; + json_cmd["SYMBOL"] = Symbol; + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject(res.ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + public List PriceHistory(string Symbol, TimeFrame tf, DateTime From, DateTime To) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "PRICE_HISTORY"; + json_cmd["SYMBOL"] = Symbol; + json_cmd["TIMEFRAME"] = tf.ToString(); + json_cmd["FROM_DATE"] = From.ToString("yyyy.MM.dd HH:mm"); + json_cmd["TO_DATE"] = To.ToString("yyyy.MM.dd HH:mm"); + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject>(res["RATES"].ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + public bool TrackPrices(List symbols) + { + try + { + JObject json_cmd = new JObject(); + + json_cmd["MSG"] = "TRACK_PRICES"; + + JArray ja = new JArray(); + + symbols = symbols.Where(x => x.TRADE_MODE > 0).ToList(); //Avoid disabled symbols + + foreach (Asset symbol in symbols) + ja.Add(symbol.NAME); + + json_cmd["SYMBOLS"] = ja; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return true; + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + public bool TrackPrices(List symbols) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "TRACK_PRICES"; + + JArray ja = new JArray(); + foreach (string symbol in symbols) + ja.Add(symbol); + + json_cmd["SYMBOLS"] = ja; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return true; + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + public bool TrackOHLC(List ohlc_request) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "TRACK_OHLC"; + + JArray ja = new JArray(); + foreach (OHLC_Req item in ohlc_request) + { + JObject jo = new JObject(); + jo["SYMBOL"] = item.SYMBOL; + jo["TIMEFRAME"] = item.TIMEFRAME.ToString(); + if (item.DEPTH != null) jo["DEPTH"] = item.DEPTH; + ja.Add(jo); + } + + json_cmd["OHLC"] = ja; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return true; + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + } } \ No newline at end of file diff --git a/MT5socketAPI/Asset.cs b/MT5socketAPI/Asset.cs index 18a228f..e8a7a5a 100644 --- a/MT5socketAPI/Asset.cs +++ b/MT5socketAPI/Asset.cs @@ -43,8 +43,10 @@ public class Asset public string CURRENCY_MARGIN { get; set; } public string DESCRIPTION { get; set; } public string PATH { get; set; } + public List> SESSION_QUOTE { get; set; } + public List> SESSION_TRADE { get; set; } - public override string ToString() + public override string ToString() { return JsonConvert.SerializeObject(this); } diff --git a/MT5socketAPI/CalendarList.cs b/MT5socketAPI/CalendarList.cs new file mode 100644 index 0000000..075a671 --- /dev/null +++ b/MT5socketAPI/CalendarList.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MTsocketAPI.MT5 +{ + // Root myDeserializedClass = JsonConvert.DeserializeObject(myJsonResponse); + public class Event + { + public string TIME { get; set; } + public int EVENT_COUNTRY_ID { get; set; } + public int EVENT_DIGITS { get; set; } + public string EVENT_CODE { get; set; } + public string EVENT_FREQUENCY { get; set; } + public int EVENT_ID { get; set; } + public string EVENT_IMPORTANCE { get; set; } + public string EVENT_MULTIPLIER { get; set; } + public string EVENT_NAME { get; set; } + public string EVENT_SECTOR { get; set; } + public string EVENT_SOURCE_URL { get; set; } + public string EVENT_TIME_MODE { get; set; } + public string EVENT_TYPE { get; set; } + public string EVENT_UNIT { get; set; } + public double ACTUAL_VALUE { get; set; } + public double FORECAST_VALUE { get; set; } + public double PREVIOUS_VALUE { get; set; } + public string IMPACT_TYPE { get; set; } + public int REVISION { get; set; } + public string PERIOD { get; set; } + public double? REVISED_VALUE { get; set; } + } + + public class CalendarList + { + public string MSG { get; set; } + public List EVENTS { get; set; } + public int ERROR_ID { get; set; } + public string ERROR_DESCRIPTION { get; set; } + } +} diff --git a/MT5socketAPI/Deal.cs b/MT5socketAPI/Deal.cs index 18ae579..fabb311 100644 --- a/MT5socketAPI/Deal.cs +++ b/MT5socketAPI/Deal.cs @@ -32,7 +32,7 @@ public override string ToString() } - public class Order_Deal + public class OrderDeal { public string TIME { get; set; } public long TICKET { get; set; } diff --git a/MT5socketAPI/MTsocketAPI5.csproj b/MT5socketAPI/MTsocketAPI5.csproj index dbb72de..3123d8b 100644 --- a/MT5socketAPI/MTsocketAPI5.csproj +++ b/MT5socketAPI/MTsocketAPI5.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable diff --git a/MT5socketAPI/Position.cs b/MT5socketAPI/Position.cs index 43412c7..66633b5 100644 --- a/MT5socketAPI/Position.cs +++ b/MT5socketAPI/Position.cs @@ -30,6 +30,7 @@ public class Position public long REASON { get; set; } public double PRICE_CURRENT { get; set; } public string EXTERNAL_ID { get; set; } + public double CHANGE { get; set; } public override string ToString() { return JsonConvert.SerializeObject(this); diff --git a/MT5socketAPI/Quote.cs b/MT5socketAPI/Quote.cs index 17d42f5..441837e 100644 --- a/MT5socketAPI/Quote.cs +++ b/MT5socketAPI/Quote.cs @@ -1,6 +1,7 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -32,4 +33,18 @@ public override string ToString() return JsonConvert.SerializeObject(this); } } + + public class OHLC_Req + { + //public string MSG { get; set; } + [Required] + public string SYMBOL { get; set; } + [Required] + public TimeFrame TIMEFRAME { get; set; } + public int? DEPTH { get; set; } + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + } } diff --git a/MT5socketAPI/Rates.cs b/MT5socketAPI/Rates.cs index bdb44ae..362755e 100644 --- a/MT5socketAPI/Rates.cs +++ b/MT5socketAPI/Rates.cs @@ -23,4 +23,23 @@ public override string ToString() } } + + public class MarketBook + { + public double PRICE { get; set; } + public int VOLUME { get; set; } + public double VOLUMEREAL { get; set; } + public string TYPE { get; set; } + } + + public class MarketDepth + { + //public string MSG { get; set; } + public string SYMBOL { get; set; } + public List MARKET_BOOK { get; set; } + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + } } diff --git a/MT5socketAPI/Terminal.cs b/MT5socketAPI/Terminal.cs index bb3b21c..2795c59 100644 --- a/MT5socketAPI/Terminal.cs +++ b/MT5socketAPI/Terminal.cs @@ -2,6 +2,7 @@ using Newtonsoft.Json; using System.Net.Sockets; using System.Text; +using System.Globalization; namespace MTsocketAPI.MT5 { @@ -14,6 +15,51 @@ public enum OrderType ORDER_TYPE_BUY_STOP, ORDER_TYPE_SELL_STOP } + + public enum TradeRetCode : long + { + TRADE_RETCODE_REQUOTE = 10004, + TRADE_RETCODE_REJECT = 1006, + TRADE_RETCODE_CANCEL = 10007, + TRADE_RETCODE_PLACED = 10008, + TRADE_RETCODE_DONE = 10009, + TRADE_RETCODE_DONE_PARTIAL = 10010, + TRADE_RETCODE_ERROR = 10011, + TRADE_RETCODE_TIMEOUT = 10012, + TRADE_RETCODE_INVALID = 10013, + TRADE_RETCODE_INVALID_VOLUME = 10014, + TRADE_RETCODE_INVALID_PRICE = 10015, + TRADE_RETCODE_INVALID_STOPS = 10016, + TRADE_RETCODE_TRADE_DISABLED = 10017, + TRADE_RETCODE_MARKET_CLOSED = 10018, + TRADE_RETCODE_NO_MONEY = 10019, + TRADE_RETCODE_PRICE_CHANGED = 10020, + TRADE_RETCODE_PRICE_OFF = 10021, + TRADE_RETCODE_INVALID_EXPIRATION = 10022, + TRADE_RETCODE_ORDER_CHANGED = 10023, + TRADE_RETCODE_TOO_MANY_REQUESTS = 10024, + TRADE_RETCODE_NO_CHANGES = 10025, + TRADE_RETCODE_SERVER_DISABLES_AT = 10026, + TRADE_RETCODE_CLIENT_DISABLES_AT = 10027, + TRADE_RETCODE_LOCKED = 10028, + TRADE_RETCODE_FROZEN = 10029, + TRADE_RETCODE_INVALID_FILL = 10030, + TRADE_RETCODE_CONNECTION = 10031, + TRADE_RETCODE_ONLY_REAL = 10032, + TRADE_RETCODE_LIMIT_ORDERS = 10033, + TRADE_RETCODE_LIMIT_VOLUME = 10034, + TRADE_RETCODE_INVALID_ORDER = 10035, + TRADE_RETCODE_POSITION_CLOSED = 10036, + TRADE_RETCODE_INVALID_CLOSE_VOLUME = 10038, + TRADE_RETCODE_CLOSE_ORDER_EXIST = 10039, + TRADE_RETCODE_LIMIT_POSITIONS = 10040, + TRADE_RETCODE_REJECT_CANCEL = 10041, + TRADE_RETCODE_LONG_ONLY = 10042, + TRADE_RETCODE_SHORT_ONLY = 10043, + TRADE_RETCODE_CLOSE_ONLY = 10044, + TRADE_RETCODE_FIFO_CLOSE = 10045, + TRADE_RETCODE_HEDGE_PROHIBITED = 10046 + } public enum TimeFrame { PERIOD_M1, @@ -66,273 +112,331 @@ public enum Applied_Price PRICE_WEIGHTED } - public class Terminal - { - public Terminal() { } - - public string host = "localhost"; - public int cmd_port = 77; - public int data_port = 78; - static int bufferLen = 65536; - - TcpClient tcpClient_cmd; - TcpClient tcpClient_data; - - public event EventHandler OnConnect; - public event EventHandler OnDisconnect; - public event EventHandler OnPrice; - public event EventHandler OnOHLC; - public event EventHandler OnOrderEvent; - - /// - /// MTsocketAPI version - /// - public string Version { get; set; } - - /// - /// Send RAW JSON command to MTsocketAPI - /// - /// JSON command - /// JSON reply - public JObject SendCommand(JObject cmd) - { - try - { - byte[] data = Encoding.ASCII.GetBytes(cmd.ToString(Formatting.None) + "\r\n"); - - NetworkStream stream = tcpClient_cmd.GetStream(); - - stream.Write(data, 0, data.Length); - - data = new byte[bufferLen]; - - string responseData = string.Empty; - - int bytes; - do - { - bytes = stream.Read(data, 0, bufferLen); - responseData += Encoding.ASCII.GetString(data, 0, bytes); - } while (stream.DataAvailable || !responseData.EndsWith("\r\n")); - - JObject? jresult = JsonConvert.DeserializeObject(responseData); - - if (jresult != null) - return jresult; - else - throw new Exception("Error with deserialization in SendCommand"); - } - catch (Exception) - { - throw; - } - } - - private void ListenMTData() - { - Thread listen = new Thread(() => ListenMTDataStream()); - listen.IsBackground = true; - listen.Start(); - } - - private void ListenMTDataStream() - { - int bytes; - byte[] data = new byte[bufferLen]; - - NetworkStream stream = tcpClient_data.GetStream(); - - do - { - string responseData = string.Empty; - - do - { - try - { - bytes = stream.Read(data, 0, data.Length); - responseData += Encoding.ASCII.GetString(data, 0, bytes); - } - catch (Exception ex) - { - - } - - } while (stream.DataAvailable); - - try - { - responseData.Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList().ForEach( - line => { - JObject jresult = JObject.Parse(line); - if (jresult["MSG"].ToString() == "TRACK_PRICES") - { - Quote price = JsonConvert.DeserializeObject(line); - if (OnPrice != null) OnPrice(this, price); - } - else if (jresult["MSG"].ToString() == "TRACK_OHLC") - { - OHLC_Msg price = JsonConvert.DeserializeObject(line); - if (OnOHLC != null) OnOHLC(this, price); - } - else if (jresult["MSG"].ToString() == "TRACK_TRADE_EVENTS") - { - OrderEvent ordEvent = JsonConvert.DeserializeObject(line); - if (OnOrderEvent != null) OnOrderEvent(this, ordEvent); - } - }); - } - catch (Exception ex) - { - - } - - } while (true); - } + public class Terminal : ITerminal + { + public Terminal() { } + + public string host = "127.0.0.1"; + public int cmd_port = 77; + public int data_port = 78; + static int bufferLen = 65536; + + TcpClient tcpClient_cmd; + TcpClient tcpClient_data; + + public event EventHandler OnConnect; + public event EventHandler OnDisconnect; + public event EventHandler OnPrice; + public event EventHandler OnMarketDepth; + public event EventHandler OnOHLC; + public event EventHandler OnOrderEvent; + + /// + /// MTsocketAPI version + /// + public string Version { get; set; } + private object sendCmdLock = new object(); + + /// + /// Send RAW JSON command to MTsocketAPI + /// + /// JSON command + /// JSON reply + public JObject SendCommand(JObject cmd) + { + lock (sendCmdLock) + { + try + { + byte[] data = Encoding.ASCII.GetBytes(cmd.ToString(Formatting.None) + "\r\n"); + + NetworkStream stream = tcpClient_cmd.GetStream(); + stream.ReadTimeout = 3000; + stream.Write(data, 0, data.Length); + + data = new byte[bufferLen]; + + string responseData = string.Empty; + + int bytes; + do + { + bytes = stream.Read(data, 0, bufferLen); + responseData += Encoding.ASCII.GetString(data, 0, bytes); + } while (stream.DataAvailable || !responseData.EndsWith("\r\n")); + + JObject? jresult = JsonConvert.DeserializeObject(responseData); + + if (jresult != null) + return jresult; + else + throw new Exception("Error with deserialization in SendCommand"); + } + catch (Exception) + { + throw; + } + } + } + + public async Task SendCommandAsync(string host, int port, JObject cmd) + { + try + { + byte[] data = Encoding.ASCII.GetBytes(cmd.ToString(Formatting.None) + "\r\n"); + + if (tcpClient_cmd == null || tcpClient_cmd.Connected == false) + { + tcpClient_cmd = new TcpClient(); + await tcpClient_cmd.ConnectAsync(host, port); + } + + NetworkStream stream = tcpClient_cmd.GetStream(); + stream.ReadTimeout = 3000; + await stream.WriteAsync(data, 0, data.Length); + + data = new byte[bufferLen]; + + string responseData = string.Empty; + + int bytes; + do + { + bytes = await stream.ReadAsync(data, 0, bufferLen); + responseData += Encoding.ASCII.GetString(data, 0, bytes); + } while (stream.DataAvailable || !responseData.EndsWith("\r\n")); + + JObject? jresult = JsonConvert.DeserializeObject(responseData); + + tcpClient_cmd.Close(); + + if (jresult != null) + return jresult; + else + throw new Exception("Error with deserialization in SendCommand"); + } + catch (Exception) + { + throw; + } + + } + + private void ListenMTData() + { + Thread listen = new Thread(() => ListenMTDataStream()); + listen.IsBackground = true; + listen.Start(); + } + + private void ListenMTDataStream() + { + int bytes; + byte[] data = new byte[bufferLen]; + + NetworkStream stream = tcpClient_data.GetStream(); + + do + { + string responseData = string.Empty; + + do + { + try + { + bytes = stream.Read(data, 0, data.Length); + responseData += Encoding.ASCII.GetString(data, 0, bytes); + } + catch (Exception ex) + { + + } + + } while (stream.DataAvailable); + + try + { + responseData.Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList().ForEach( + line => + { + JObject jresult = JObject.Parse(line); + if (jresult["MSG"].ToString() == "TRACK_PRICES") + { + Quote price = JsonConvert.DeserializeObject(line); + if (OnPrice != null) OnPrice(this, price); + } + if (jresult["MSG"].ToString() == "TRACK_MBOOK") + { + MarketDepth domdata = JsonConvert.DeserializeObject(line); + if (OnMarketDepth != null) OnMarketDepth(this, domdata); + } + else if (jresult["MSG"].ToString() == "TRACK_OHLC") + { + OHLC_Msg price = JsonConvert.DeserializeObject(line); + if (OnOHLC != null) OnOHLC(this, price); + } + else if (jresult["MSG"].ToString() == "TRACK_TRADE_EVENTS") + { + OrderEvent ordEvent = JsonConvert.DeserializeObject(line); + if (OnOrderEvent != null) OnOrderEvent(this, ordEvent); + } + }); + } + catch (Exception ex) + { + + } + + } while (true); + } + + /// + /// Connect to MTsocketAPI + /// + /// Hostname or IP Address + /// MTsocketAPI command port + /// MTsocketAPI data port + /// True = connect successful, False = connect fail + public bool Connect(string host = "127.0.0.1", int cmd_port = 77, int data_port = 78) + { + try + { + tcpClient_cmd = new TcpClient(host, cmd_port); + tcpClient_data = new TcpClient(host, data_port); + + ListenMTData(); + + //JObject json_cmd = new JObject(); + //json_cmd["MSG"] = "VERSION"; + //JObject res = SendCommand(json_cmd); + + //if (res["ERROR_ID"].ToString() == "0") + //{ + // Version = res["NUMBER"].ToString(); + + // if (Convert.ToDouble(Version,CultureInfo.InvariantCulture) < 5.21) + // { + // throw new Exception("This API version needs at least MTsocketAPI 5.21 version"); + // } + //} + //else + //{ + // throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + //} + } + catch (Exception ex) + { + throw new Exception(ex.Message); + } + + if (OnConnect != null) OnConnect(this, new EventArgs()); + return true; + } + + /// + /// Get MT5 Terminal Information + /// + /// Terminal Info object + public TerminalInfo GetTerminalInfo() + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "TERMINAL_INFO"; + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject(res.ToString()); + } + else + { + throw new Exception("Error with the GetTerminalInfo command. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Get MT5 Account Status Info + /// + /// AccountStatus object + public AccountStatus GetAccountStatus() + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "ACCOUNT_STATUS"; + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject(res.ToString()); + } + else + { + throw new Exception("Error with the GetAccountStatus command. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Get Pending Orders + /// + /// List of pending orders + public List GetPendingOrders() + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "ORDER_LIST"; + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + List pending = JsonConvert.DeserializeObject>(res["PENDING"].ToString()); + return pending; + } + else + { + throw new Exception("Error with the GetPendingOrders command. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + + } /// - /// Connect to MTsocketAPI + /// Get Information from an opened order /// - /// Hostname or IP Address - /// MTsocketAPI command port - /// MTsocketAPI data port - /// True = connect successful, False = connect fail - public bool Connect(string host = "localhost", int cmd_port = 77, int data_port = 78) - { + /// Opened order + public Position getOrderInfo(long ticket) + { try { - tcpClient_cmd = new TcpClient(host, cmd_port); - tcpClient_data = new TcpClient(host, data_port); - - ListenMTData(); - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "VERSION"; - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - Version = res["NUMBER"].ToString(); - - if (Convert.ToDouble(Version) < 5.21) - { - throw new Exception("This API version needs at least MTsocketAPI 5.21 version"); - } - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception ex) - { - throw new Exception(ex.Message); - } - - if (OnConnect != null) OnConnect(this, new EventArgs()); - return true; - } - - /// - /// Get MT5 Terminal Information - /// - /// Terminal Info object - public TerminalInfo GetTerminalInfo() - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "TERMINAL_INFO"; - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject(res.ToString()); - } - else - { - throw new Exception("Error with the GetTerminalInfo command. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Get MT5 Account Status Info - /// - /// AccountStatus object - public AccountStatus GetAccountStatus() - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "ACCOUNT_STATUS"; - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject(res.ToString()); - } - else - { - throw new Exception("Error with the GetAccountStatus command. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Get Pending Orders - /// - /// List of pending orders - public List GetPendingOrders() - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "ORDER_LIST"; - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - List pending = JsonConvert.DeserializeObject>(res["PENDING"].ToString()); - return pending; - } - else - { - throw new Exception("Error with the GetPendingOrders command. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - - } - - /// - /// Get Opened Positions - /// - /// List of opened positions - public List GetOpenedOrders() - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "ORDER_LIST"; + json_cmd["MSG"] = "ORDER_INFO"; + json_cmd["TICKET"] = ticket; JObject res = SendCommand(json_cmd); if (res["ERROR_ID"].ToString() == "0") { List opened = JsonConvert.DeserializeObject>(res["OPENED"].ToString()); - //List pending = JsonConvert.DeserializeObject>(res["PENDING"].ToString()); - return opened; + if (opened.Count > 0) + { + return opened.First(); + } + else return new Position(); } else { @@ -345,648 +449,871 @@ public List GetOpenedOrders() } } - /// - /// Get Moving Average values - /// - /// Symbol - /// TimeFrame - /// Moving Average period - /// Moving Average shift - /// Moving Average method - /// Appliced Price - /// Shift - /// Number of elements - /// List of MA values - /// - public List MA_Indicator(string Symbol, TimeFrame tf, int MA_Period, int MA_Shift, MA_Method MA_Method, Applied_Price Applied_Price, int Shift, int Num = 1) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "MA_INDICATOR"; - json_cmd["SYMBOL"] = Symbol; - json_cmd["TIMEFRAME"] = tf.ToString(); - json_cmd["MA_PERIOD"] = MA_Period; - json_cmd["MA_SHIFT"] = MA_Shift; - json_cmd["MA_METHOD"] = MA_Method.ToString(); - json_cmd["APPLIED_PRICE"] = Applied_Price.ToString(); - json_cmd["SHIFT"] = Shift; - json_cmd["NUM"] = Num; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject>(res["DATA_VALUES"].ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Get data from a the ATR indicator using the iATR function. More info: - /// - /// Symbol name - /// TimeFrame - /// ATR Period - /// Shift - /// Number of elements - public List ATR_Indicator(string Symbol, TimeFrame tf, int Period, int Shift, int Num = 1) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "ATR_INDICATOR"; - json_cmd["SYMBOL"] = Symbol; - json_cmd["TIMEFRAME"] = tf.ToString(); - json_cmd["PERIOD"] = Period; - json_cmd["SHIFT"] = Shift; - json_cmd["NUM"] = Num; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject>(res["DATA_VALUES"].ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Get data from a custom indicator using the Metatrader iCustom function. More Info: - /// - /// Symbol name - /// TimeFrame - /// Indicator Name - /// Mode - /// Shift - /// Number of elements - /// Parameters - public List Custom_Indicator(string Symbol, TimeFrame tf, string Indicator_Name, int Mode, int Shift, int Num = 1, List Params = null) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "CUSTOM_INDICATOR"; - json_cmd["SYMBOL"] = Symbol; - json_cmd["TIMEFRAME"] = tf.ToString(); - json_cmd["INDICATOR_NAME"] = Indicator_Name; - json_cmd["MODE"] = Mode; - json_cmd["SHIFT"] = Shift; - json_cmd["NUM"] = Num; - - int i = 1; - - foreach (var param in Params) - { - double valorD; - int valorI; - if (int.TryParse(param, out valorI)) - json_cmd["PARAM" + i.ToString()] = valorI; - else if (double.TryParse(param, out valorD)) - json_cmd["PARAM" + i.ToString()] = valorD; - else - json_cmd["PARAM" + i.ToString()] = param.ToString(); - - i++; - } - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - //return Convert.ToDouble(res["DATA_VALUES"]); - return JsonConvert.DeserializeObject>(res["DATA_VALUES"].ToString()); - } - else - { - throw new Exception("Error with the Custom_Indicator command. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - - } - - /// - /// Get Position History - /// - /// From date - /// To date - /// List of positions - public List GetTradeHistoryPositions(DateTime FromDate, DateTime ToDate) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "TRADE_HISTORY"; - json_cmd["MODE"] = TradeHistoryMode.POSITIONS.ToString(); - json_cmd["FROM_DATE"] = FromDate.ToString("yyyy.MM.dd HH:mm:ss"); - json_cmd["TO_DATE"] = ToDate.ToString("yyyy.MM.dd HH:mm:ss"); + /// + /// Get Opened Positions + /// + /// List of opened positions + public List GetOpenedOrders() + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "ORDER_LIST"; + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + List opened = JsonConvert.DeserializeObject>(res["OPENED"].ToString()); + return opened; + } + else + { + throw new Exception("Error with the GetOpenedOrders command. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Get Moving Average values + /// + /// Symbol + /// TimeFrame + /// Moving Average period + /// Moving Average shift + /// Moving Average method + /// Appliced Price + /// Shift + /// Number of elements + /// List of MA values + /// + public List MA_Indicator(string Symbol, TimeFrame tf, int MA_Period, int MA_Shift, MA_Method MA_Method, Applied_Price Applied_Price, int Shift, int Num = 1) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "MA_INDICATOR"; + json_cmd["SYMBOL"] = Symbol; + json_cmd["TIMEFRAME"] = tf.ToString(); + json_cmd["MA_PERIOD"] = MA_Period; + json_cmd["MA_SHIFT"] = MA_Shift; + json_cmd["MA_METHOD"] = MA_Method.ToString(); + json_cmd["APPLIED_PRICE"] = Applied_Price.ToString(); + json_cmd["SHIFT"] = Shift; + json_cmd["NUM"] = Num; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject>(res["DATA_VALUES"].ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Get data from a the ATR indicator using the iATR function. More info: + /// + /// Symbol name + /// TimeFrame + /// ATR Period + /// Shift + /// Number of elements + public List ATR_Indicator(string Symbol, TimeFrame tf, int Period, int Shift, int Num = 1) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "ATR_INDICATOR"; + json_cmd["SYMBOL"] = Symbol; + json_cmd["TIMEFRAME"] = tf.ToString(); + json_cmd["PERIOD"] = Period; + json_cmd["SHIFT"] = Shift; + json_cmd["NUM"] = Num; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject>(res["DATA_VALUES"].ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Get data from a custom indicator using the Metatrader iCustom function. More Info: + /// + /// Symbol name + /// TimeFrame + /// Indicator Name + /// Buffer Index + /// Number of elements + /// Parameters + public List Custom_Indicator(string Symbol, TimeFrame tf, string Indicator_Name, int Index, int Num = 1, List Params = null) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "CUSTOM_INDICATOR"; + json_cmd["SYMBOL"] = Symbol; + json_cmd["TIMEFRAME"] = tf.ToString(); + json_cmd["INDICATOR_NAME"] = Indicator_Name; + json_cmd["INDEX"] = Index; + json_cmd["NUM"] = Num; + + int i = 1; + + foreach (var param in Params) + { + double valorD; + int valorI; + if (int.TryParse(param, out valorI)) + json_cmd["PARAM" + i.ToString()] = valorI; + else if (double.TryParse(param, out valorD)) + json_cmd["PARAM" + i.ToString()] = valorD; + else + json_cmd["PARAM" + i.ToString()] = param.ToString(); + + i++; + } + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject>(res["DATA_VALUES"].ToString()); + } + else + { + throw new Exception("Error with the Custom_Indicator command. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + + } + + /// + /// Get Position History + /// + /// From date + /// To date + /// List of positions + public List GetTradeHistoryPositions(DateTime FromDate, DateTime ToDate) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "TRADE_HISTORY"; + json_cmd["MODE"] = TradeHistoryMode.POSITIONS.ToString(); + json_cmd["FROM_DATE"] = FromDate.ToString("yyyy.MM.dd HH:mm:ss"); + json_cmd["TO_DATE"] = ToDate.ToString("yyyy.MM.dd HH:mm:ss"); + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject>(res[TradeHistoryMode.POSITIONS.ToString()].ToString()); + } + else + { + throw new Exception("Error with the command TRADE_HISTORY. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Get the Deals History + /// + /// + /// + /// List of deals + public List GetTradeHistoryDeals(DateTime FromDate, DateTime ToDate) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "TRADE_HISTORY"; + json_cmd["MODE"] = TradeHistoryMode.DEALS.ToString(); + json_cmd["FROM_DATE"] = FromDate.ToString("yyyy.MM.dd HH:mm:ss"); + json_cmd["TO_DATE"] = ToDate.ToString("yyyy.MM.dd HH:mm:ss"); + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject>(res[TradeHistoryMode.DEALS.ToString()].ToString()); + } + else + { + throw new Exception("Error with the command TRADE_HISTORY. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Get the Order History + /// + /// From date + /// To date + /// List of orders + public List GetTradeHistoryOrders(DateTime FromDate, DateTime ToDate) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "TRADE_HISTORY"; + json_cmd["MODE"] = TradeHistoryMode.ORDERS.ToString(); + json_cmd["FROM_DATE"] = FromDate.ToString("yyyy.MM.dd HH:mm:ss"); + json_cmd["TO_DATE"] = ToDate.ToString("yyyy.MM.dd HH:mm:ss"); + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject>(res[TradeHistoryMode.ORDERS.ToString()].ToString()); + } + else + { + throw new Exception("Error with the command TRADE_HISTORY. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Get the Orders & Deals History + /// + /// From date + /// To date + /// List of Orders & Deals + public List GetTradeHistoryOrdersDeals(DateTime FromDate, DateTime ToDate) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "TRADE_HISTORY"; + json_cmd["MODE"] = TradeHistoryMode.ORDERS_DEALS.ToString(); + json_cmd["FROM_DATE"] = FromDate.ToString("yyyy.MM.dd HH:mm:ss"); + json_cmd["TO_DATE"] = ToDate.ToString("yyyy.MM.dd HH:mm:ss"); + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject>(res[TradeHistoryMode.ORDERS_DEALS.ToString()].ToString()); + } + else + { + throw new Exception("Error with the command TRADE_HISTORY. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Get the price history (Open, High, Low, Close) for a specified Symbol and TimeFrame. + /// + /// Symbol + /// TimeFrame + /// From date + /// To date + public List PriceHistory(string Symbol, TimeFrame tf, DateTime FromDate, DateTime ToDate) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "PRICE_HISTORY"; + json_cmd["SYMBOL"] = Symbol; + json_cmd["TIMEFRAME"] = tf.ToString(); + json_cmd["FROM_DATE"] = FromDate.ToString("yyyy.MM.dd HH:mm"); + json_cmd["TO_DATE"] = ToDate.ToString("yyyy.MM.dd HH:mm"); + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject>(res["RATES"].ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Send market or limit orders. + /// + /// Symbol + /// Volume size + /// OrderType enum + /// Desired price. 0 for broker's best price (optional) + /// Stop Loss price. 0 for no Stop Loss (optional) + /// Take Profit price. 0 for no Take Profit (optional) + /// Slippage. 0 for default broker's Slippage (optional) + /// Order Comment (optional) + /// Magic Number (optional) + /// Order Expiration Date. Only for limit or stop orders (optional) + public TradeResult SendOrder(string Symbol, double Volume, OrderType Type, double Price = 0, double SL = 0, double TP = 0, double Slippage = 0, string Comment = "", int MagicNr = 0, string Expiration = "1970/01/01 00:00", bool Async = false) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "ORDER_SEND"; + json_cmd["SYMBOL"] = Symbol; + json_cmd["VOLUME"] = Volume; + json_cmd["TYPE"] = Type.ToString(); + if (SL > 0) json_cmd["SL"] = SL; + if (TP > 0) json_cmd["TP"] = TP; + if (Price > 0) json_cmd["PRICE"] = Price; + if (Slippage > 0) json_cmd["SLIPPAGE"] = Slippage; + if (Comment != "") json_cmd["COMMENT"] = Comment; + if (MagicNr > 0) json_cmd["MAGICNR"] = MagicNr; + if (Expiration != "1970/01/01 00:00") json_cmd["EXPIRATION"] = Expiration; + if (Async != false) json_cmd["ASYNC"] = true; JObject res = SendCommand(json_cmd); - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject>(res[TradeHistoryMode.POSITIONS.ToString()].ToString()); - } - else - { - throw new Exception("Error with the command TRADE_HISTORY. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Get the Deals History - /// - /// - /// - /// List of deals - public List GetTradeHistoryDeals(DateTime FromDate, DateTime ToDate) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "TRADE_HISTORY"; - json_cmd["MODE"] = TradeHistoryMode.DEALS.ToString(); - json_cmd["FROM_DATE"] = FromDate.ToString("yyyy.MM.dd HH:mm:ss"); - json_cmd["TO_DATE"] = ToDate.ToString("yyyy.MM.dd HH:mm:ss"); + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject(res.ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Change SL or TP for market or limit orders. More Info: + /// + /// Ticket Number + /// Stop loss price (optional) + /// Take profit price (optional) + public TradeResult OrderModify(long Ticket, double SL = 0, double TP = 0, bool Async = false) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "ORDER_MODIFY"; + json_cmd["TICKET"] = Ticket; + if (SL > 0) json_cmd["SL"] = SL; + if (TP != 0) json_cmd["TP"] = TP; + if (Async != false) json_cmd["ASYNC"] = true; JObject res = SendCommand(json_cmd); - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject>(res[TradeHistoryMode.DEALS.ToString()].ToString()); - } - else - { - throw new Exception("Error with the command TRADE_HISTORY. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Get the Order History - /// - /// From date - /// To date - /// List of orders - public List GetTradeHistoryOrders(DateTime FromDate, DateTime ToDate) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "TRADE_HISTORY"; - json_cmd["MODE"] = TradeHistoryMode.ORDERS.ToString(); - json_cmd["FROM_DATE"] = FromDate.ToString("yyyy.MM.dd HH:mm:ss"); - json_cmd["TO_DATE"] = ToDate.ToString("yyyy.MM.dd HH:mm:ss"); + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject(res.ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Close partially or fully an order using the ticket number. + /// Also it closes stop or limit orders. More Info: + /// + /// Ticket Number + /// Volume size (optional) + /// Desired Price (optional) + /// Max lippage (optional) + public TradeResult OrderClose(long Ticket, double Volume = 0, double Price = 0, double Slippage = 0, bool Async = false) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "ORDER_CLOSE"; + json_cmd["TICKET"] = Ticket; + if (Volume > 0) json_cmd["VOLUME"] = Volume; + if (Price != 0) json_cmd["PRICE"] = Price; + if (Slippage != 0) json_cmd["SLIPPAGE"] = Slippage; + if (Async != false) json_cmd["ASYNC"] = true; JObject res = SendCommand(json_cmd); - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject>(res[TradeHistoryMode.ORDERS.ToString()].ToString()); - } - else - { - throw new Exception("Error with the command TRADE_HISTORY. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Get the Orders & Deals History - /// - /// From date - /// To date - /// List of Orders & Deals - public List GetTradeHistoryOrdersDeals(DateTime FromDate, DateTime ToDate) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "TRADE_HISTORY"; - json_cmd["MODE"] = TradeHistoryMode.ORDERS_DEALS.ToString(); - json_cmd["FROM_DATE"] = FromDate.ToString("yyyy.MM.dd HH:mm:ss"); - json_cmd["TO_DATE"] = ToDate.ToString("yyyy.MM.dd HH:mm:ss"); - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject>(res[TradeHistoryMode.ORDERS_DEALS.ToString()].ToString()); - } - else - { - throw new Exception("Error with the command TRADE_HISTORY. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Get the price history (Open, High, Low, Close) for a specified Symbol and TimeFrame. - /// - /// Symbol - /// TimeFrame - /// From date - /// To date - public List PriceHistory(string Symbol, TimeFrame tf, DateTime FromDate, DateTime ToDate) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "PRICE_HISTORY"; - json_cmd["SYMBOL"] = Symbol; - json_cmd["TIMEFRAME"] = tf.ToString(); - json_cmd["FROM_DATE"] = FromDate.ToString("yyyy.MM.dd HH:mm"); - json_cmd["TO_DATE"] = ToDate.ToString("yyyy.MM.dd HH:mm"); - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject>(res["RATES"].ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Send market or limit orders. - /// - /// Symbol - /// Volume size - /// OrderType enum - /// Desired price. 0 for broker's best price (optional) - /// Stop Loss price. 0 for no Stop Loss (optional) - /// Take Profit price. 0 for no Take Profit (optional) - /// Slippage. 0 for default broker's Slippage (optional) - /// Order Comment (optional) - /// Magic Number (optional) - /// Order Expiration Date. Only for limit or stop orders (optional) - public TradeResult SendOrder(string Symbol, double Volume, OrderType Type, double Price = 0, double SL = 0, double TP = 0, double Slippage = 0, string Comment = "", int MagicNr = 0, string Expiration = "1970/01/01 00:00") - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "ORDER_SEND"; - json_cmd["SYMBOL"] = Symbol; - json_cmd["VOLUME"] = Volume; - json_cmd["TYPE"] = Type.ToString(); - if (SL > 0) json_cmd["SL"] = SL; - if (TP > 0) json_cmd["TP"] = TP; - if (Price > 0) json_cmd["PRICE"] = Price; - if (Slippage > 0) json_cmd["SLIPPAGE"] = Slippage; - if (Comment != "") json_cmd["COMMENT"] = Comment; - if (MagicNr > 0) json_cmd["MAGICNR"] = MagicNr; - if (Expiration != "1970/01/01 00:00") json_cmd["EXPIRATION"] = Expiration; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject(res.ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Change SL or TP for market or limit orders. More Info: - /// - /// Ticket Number - /// Stop loss price (optional) - /// Take profit price (optional) - public TradeResult OrderModify(long Ticket, double SL = 0, double TP = 0) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "ORDER_MODIFY"; - json_cmd["TICKET"] = Ticket; - if (SL > 0) json_cmd["SL"] = SL; - if (TP != 0) json_cmd["TP"] = TP; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject(res.ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Close partially or fully an order using the ticket number. - /// Also it closes stop or limit orders. More Info: - /// - /// Ticket Number - /// Volume size (optional) - /// Desired Price (optional) - /// Max lippage (optional) - public TradeResult OrderClose(long Ticket, double Volume = 0, double Price = 0, double Slippage = 0) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "ORDER_CLOSE"; - json_cmd["TICKET"] = Ticket; - if (Volume > 0) json_cmd["VOLUME"] = Volume; - if (Price != 0) json_cmd["PRICE"] = Price; - if (Slippage != 0) json_cmd["SLIPPAGE"] = Slippage; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject(res.ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Get MT5 Symbol List - /// - /// Asset List - public List GetSymbolList() - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "SYMBOL_LIST"; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject>(res["SYMBOLS"].ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Get detailed information from a symbol - /// - /// Symbol - /// Asset object - /// - public Asset GetSymbolInfo(string Symbol) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "SYMBOL_INFO"; - json_cmd["SYMBOL"] = Symbol; - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject(res.ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Get last quote from a symbol - /// - /// Symbol - /// Quote object - /// - public Quote GetQuote(string Symbol) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "QUOTE"; - json_cmd["SYMBOL"] = Symbol; - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return JsonConvert.DeserializeObject(res.ToString()); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Start streaming prices from a list of symbols - /// - /// Symbol List - /// True if the command was executed successfully. Streaming data will be received on the data port - /// - public bool TrackPrices(List symbols) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "TRACK_PRICES"; - - JArray ja = new JArray(); - foreach (string symbol in symbols) - ja.Add(symbol); - - json_cmd["SYMBOLS"] = ja; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return true; - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Start streaming OHLC data from a list of symbols - /// - /// Symbol list - /// TimeFrame - /// True if the command was executed successfully - /// - public bool TrackOHLC(List symbols, TimeFrame tf) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "TRACK_OHLC"; - json_cmd["TIMEFRAME"] = tf.ToString(); - - JArray ja = new JArray(); - foreach (string symbol in symbols) - ja.Add(symbol); - - json_cmd["SYMBOLS"] = ja; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return true; - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Start streaming order events - /// - /// True to start streaming order events. False to disable streaming order events - /// - /// - public bool TrackOrderEvent(bool enable) - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "TRACK_TRADE_EVENTS"; - json_cmd["ENABLED"] = enable; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return true; - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - - /// - /// Get the status of the order events - /// - /// True if the streaming of order events is enabled. False if is disabled - public bool TrackOrderEvent() - { - try - { - JObject json_cmd = new JObject(); - json_cmd["MSG"] = "TRACK_TRADE_EVENTS"; - - JObject res = SendCommand(json_cmd); - - if (res["ERROR_ID"].ToString() == "0") - { - return Convert.ToBoolean(res["ENABLED"]); - } - else - { - throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); - } - } - catch (Exception) - { - throw; - } - } - } + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject(res.ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Get MT5 Symbol List + /// + /// Asset List + public List GetSymbolList() + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "SYMBOL_LIST"; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject>(res["SYMBOLS"].ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Get detailed information from a symbol + /// + /// Symbol + /// Asset object + /// + public Asset GetSymbolInfo(string Symbol) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "SYMBOL_INFO"; + json_cmd["SYMBOL"] = Symbol; + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject(res.ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Get last quote from a symbol + /// + /// Symbol + /// Quote object + /// + public Quote GetQuote(string Symbol) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "QUOTE"; + json_cmd["SYMBOL"] = Symbol; + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject(res.ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// + /// + /// The date from which you want to request news + /// The date to which you want to request news + /// (Optional) Country currency code name. For example: EUR, USD and so on + /// (Optional) Country code name (ISO 3166-1 alpha-2). “US”, “FR” and so on. + /// + public CalendarList CalendarList(DateTime FromDate, DateTime ToDate, string Currency = "", string Country_code = "") + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "CALENDAR_LIST"; + json_cmd["FROM_DATE"] = FromDate.ToString("yyyy.MM.dd HH:mm:ss"); + json_cmd["TO_DATE"] = ToDate.ToString("yyyy.MM.dd HH:mm:ss"); + if (Currency != "") json_cmd["CURRENCY"] = Currency; + if (Country_code != "") json_cmd["COUNTRY_CODE"] = Country_code; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return JsonConvert.DeserializeObject(res.ToString()); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Start streaming prices from a list of symbols + /// + /// Symbol List + /// True if the command was executed successfully. Streaming data will be received on the data port + /// + public bool TrackPrices(List symbols) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "TRACK_PRICES"; + + JArray ja = new JArray(); + foreach (string symbol in symbols) + ja.Add(symbol); + + json_cmd["SYMBOLS"] = ja; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return true; + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Start streaming DOM data from a list of symbols + /// + /// Symbol List + /// True if the command was executed successfully. Streaming data will be received on the data port + /// + public bool TrackMarketDepth(List symbols) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "TRACK_MBOOK"; + + JArray ja = new JArray(); + foreach (string symbol in symbols) + ja.Add(symbol); + + json_cmd["SYMBOLS"] = ja; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return true; + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Start streaming prices from a list of symbols + /// + /// Asset List + /// True if the command was executed successfully. Streaming data will be received on the data port + /// + public bool TrackPrices(List symbols) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "TRACK_PRICES"; + + symbols = symbols.Where(x => x.TRADE_MODE > 0).ToList(); //Avoid disabled symbols + + JArray ja = new JArray(); + foreach (Asset symbol in symbols) + ja.Add(symbol.NAME); + + json_cmd["SYMBOLS"] = ja; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return true; + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Start streaming OHLC data from a list of symbols + /// + /// Symbol list + /// TimeFrame + /// True if the command was executed successfully + /// + public bool TrackOHLC(List ohlc_request) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "TRACK_OHLC"; + + JArray ja = new JArray(); + foreach (OHLC_Req item in ohlc_request) + { + JObject jo = new JObject(); + jo["SYMBOL"] = item.SYMBOL; + jo["TIMEFRAME"] = item.TIMEFRAME.ToString(); + if (item.DEPTH != null) jo["DEPTH"] = item.DEPTH; + ja.Add(jo); + } + + json_cmd["OHLC"] = ja; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return true; + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Start streaming OHLC data from a list of symbols + /// + /// Asset list + /// TimeFrame + /// True if the command was executed successfully + /// + public bool TrackOHLC(List symbols, TimeFrame tf) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "TRACK_OHLC"; + json_cmd["TIMEFRAME"] = tf.ToString(); + + JArray ja = new JArray(); + + symbols = symbols.Where(x => x.TRADE_MODE > 0).ToList(); + + foreach (Asset symbol in symbols) + ja.Add(symbol.NAME); + + json_cmd["SYMBOLS"] = ja; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return true; + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Start streaming order events + /// + /// True to start streaming order events. False to disable streaming order events + /// + /// + public bool TrackOrderEvent(bool enable) + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "TRACK_TRADE_EVENTS"; + json_cmd["ENABLED"] = enable; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return true; + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// Get the status of the order events + /// + /// True if the streaming of order events is enabled. False if is disabled + public bool TrackOrderEvent() + { + try + { + JObject json_cmd = new JObject(); + json_cmd["MSG"] = "TRACK_TRADE_EVENTS"; + + JObject res = SendCommand(json_cmd); + + if (res["ERROR_ID"].ToString() == "0") + { + return Convert.ToBoolean(res["ENABLED"]); + } + else + { + throw new Exception("Error with the command sent. ERROR_ID: " + res["ERROR_ID"] + " ERROR_DESCRIPTION: " + res["ERROR_DESCRIPTION"]); + } + } + catch (Exception) + { + throw; + } + } + } + + public interface ITerminal + { + string Version { get; set; } + + event EventHandler OnConnect; + event EventHandler OnDisconnect; + event EventHandler OnOHLC; + event EventHandler OnOrderEvent; + event EventHandler OnPrice; + + List ATR_Indicator(string Symbol, TimeFrame tf, int Period, int Shift, int Num = 1); + CalendarList CalendarList(DateTime FromDate, DateTime ToDate, string Currency = "", string Country_code = ""); + bool Connect(string host = "127.0.0.1", int cmd_port = 71, int data_port = 72); + List Custom_Indicator(string Symbol, TimeFrame tf, string Indicator_Name, int Index, int Num = 1, List Params = null); + AccountStatus GetAccountStatus(); + List GetOpenedOrders(); + List GetPendingOrders(); + Quote GetQuote(string Symbol); + Asset GetSymbolInfo(string Symbol); + List GetSymbolList(); + TerminalInfo GetTerminalInfo(); + List GetTradeHistoryDeals(DateTime FromDate, DateTime ToDate); + List GetTradeHistoryOrders(DateTime FromDate, DateTime ToDate); + List GetTradeHistoryOrdersDeals(DateTime FromDate, DateTime ToDate); + List GetTradeHistoryPositions(DateTime FromDate, DateTime ToDate); + List MA_Indicator(string Symbol, TimeFrame tf, int MA_Period, int MA_Shift, MA_Method MA_Method, Applied_Price Applied_Price, int Shift, int Num = 1); + TradeResult OrderClose(long Ticket, double Volume = 0, double Price = 0, double Slippage = 0, bool Async = false); + TradeResult OrderModify(long Ticket, double SL = 0, double TP = 0, bool Async = false); + List PriceHistory(string Symbol, TimeFrame tf, DateTime FromDate, DateTime ToDate); + JObject SendCommand(JObject cmd); + Task SendCommandAsync(string host, int port, JObject cmd); + TradeResult SendOrder(string Symbol, double Volume, OrderType Type, double Price = 0, double SL = 0, double TP = 0, double Slippage = 0, string Comment = "", int MagicNr = 0, string Expiration = "1970/01/01 00:00", bool Async = false); + bool TrackOHLC(List ohlc_request); + bool TrackOrderEvent(); + bool TrackOrderEvent(bool enable); + bool TrackPrices(List symbols); + bool TrackPrices(List symbols); + } } \ No newline at end of file diff --git a/Test/Program.cs b/Test/Program.cs index d33f5cf..1beb89e 100644 --- a/Test/Program.cs +++ b/Test/Program.cs @@ -1,5 +1,4 @@ using MTsocketAPI.MT5; -using System.Security.Cryptography; namespace Test { @@ -7,23 +6,83 @@ internal class Program { static void Main(string[] args) { + try { - Console.WriteLine("#### MTsocketAPI C# Library ####"); + //Console.WriteLine("#### MTsocketAPI C# Library ####"); + + MTsocketAPI.MT5.Terminal mt5 = new MTsocketAPI.MT5.Terminal(); + mt5.Connect(); + + + + List ohlc_list = new List(); + MTsocketAPI.MT5.OHLC_Req req = new MTsocketAPI.MT5.OHLC_Req(); + req.SYMBOL = "EURUSD"; + req.TIMEFRAME = TimeFrame.PERIOD_M1; + ohlc_list.Add(req); + MTsocketAPI.MT5.OHLC_Req req2 = new MTsocketAPI.MT5.OHLC_Req(); + req2.SYMBOL = "GBPUSD"; + req2.TIMEFRAME = TimeFrame.PERIOD_M1; + req2.DEPTH = 3; + ohlc_list.Add(req2); + + bool result = mt5.TrackOHLC(ohlc_list); + //double valor = mt4.Custom_Indicator("EURUSD", MTsocketAPI.MT4.TimeFrame.PERIOD_M5, "Momentum", 0, 0, new List { "14", "0" }); + //var history = mt4.GetOrderHistory(DateTime.Now.AddDays(-10), DateTime.Now.AddDays(1)); + + /* + Terminal mt5 = new Terminal(); + //mt5.OnPrice += Mt5_OnPrice; + mt5.OnMarketDepth += Mt5_OnMarketDepth; + if (!mt5.Connect()) + { + Console.WriteLine("Connect failed. Please check that MTsocketAPI is running"); + return; + } - MTsocketAPI.MT5.Terminal mt5 = new MTsocketAPI.MT5.Terminal(); + mt5.TrackMarketDepth(new List() { "EURUSD", "GBPUSD" }); + */ + //var result = mt5.GetSymbolInfo("EURUSD"); - mt5.OnConnect += Tt_OnConnect; - mt5.OnPrice += Tt_OnPrice; - mt5.OnOHLC += Tt_OnOHLC; - mt5.OnOrderEvent += Tt_OnOrderEvent; + //CalendarList pepito = mt5.CalendarList(DateTime.Now.AddDays(-3), DateTime.Now.AddDays(-2)); - if (!mt5.Connect()) + //List AlligatorLine1 = mt5.Custom_Indicator("EURUSD", TimeFrame.PERIOD_M15, "Examples\\Alligator", 0, 1, new List { "13", "8", "8", "5", "5", "3", "MODE_SMMA", "PRICE_MEDIAN" }); + //List AlligatorLine2 = mt5.Custom_Indicator("EURUSD", TimeFrame.PERIOD_M15, "Examples\\Alligator", 1, 1, new List { "13", "8", "8", "5", "5", "3", "MODE_SMMA", "PRICE_MEDIAN" }); + //List AlligatorLine3 = mt5.Custom_Indicator("EURUSD", TimeFrame.PERIOD_M15, "Examples\\Alligator", 2, 1, new List { "13", "8", "8", "5", "5", "3", "MODE_SMMA", "PRICE_MEDIAN" }); + + // Console.WriteLine("AlligatorLine1: " + AlligatorLine1[0]); + //Console.WriteLine("AlligatorLine2: " + AlligatorLine2[0]); + //Console.WriteLine("AlligatorLine3: " + AlligatorLine3[0]); + + //mt5.TrackPrices(new List() { "EURUSD","GBPUSD" }); + + //Console.ReadKey(); + //List list = mt5.GetSymbolList(); + //List symbols = mt5.GetSymbolList().Where(x => x.TRADE_MODE > 0).Select(x => x.NAME.ToString()).ToList(); + //mt5.TrackPrices(symbols); + //mt5.TrackPrices(mt5.GetSymbolList()); + + /* + mt5Master.OnConnect += Tt_OnConnect; + mt5Master.OnPrice += Tt_OnPrice; + mt5Master.OnOHLC += Tt_OnOHLC; + mt5Master.OnOrderEvent += Tt_OnOrderEvent; + + if (!mt5Master.Connect()) + { + Console.WriteLine("Error connecting to MTsocketAPI. Please check if MT5 is running and MTsocketAPI started successfully"); + return; + } + + if (!mt5Slave.Connect("localhost",70,71)) { Console.WriteLine("Error connecting to MTsocketAPI. Please check if MT5 is running and MTsocketAPI started successfully"); return; } + mt5Master.TrackOrderEvent(true); + /* List list = mt5.GetSymbolList(); List symbols = new List(); @@ -79,11 +138,13 @@ static void Main(string[] args) Console.ReadKey(true); TradeResult close = mt5.OrderClose(buy.ORDER); Console.WriteLine("Result:" + close.ToString()); - + */ //bool result = mt5.TrackOHLC(new List() { asset.NAME },TimeFrame.PERIOD_M1); //bool result2 = mt5.TrackPrices(new List() { asset.NAME }); //bool result3 = mt5.TrackOrderEvent(true); + Console.ReadKey(); + Console.WriteLine("Finished!"); } catch (Exception ex) @@ -98,24 +159,67 @@ static void Main(string[] args) //} while (true); } - private static void Tt_OnOrderEvent(object? sender, OrderEvent e) - { - Console.WriteLine(e.TRADE_TRANSACTION.ToString()); - } + private static void Mt5_OnMarketDepth(object? sender, MarketDepth e) + { + Console.WriteLine("Market Depth: " + e.ToString()); + } - private static void Tt_OnOHLC(object? sender, OHLC_Msg e) + private static void Mt5_OnPrice(object? sender, Quote e) { - Console.WriteLine($"OHLC: {e.OHLC[0].TIME} {e.SYMBOL} Open: {e.OHLC[0].OPEN} High: {e.OHLC[0].HIGH} Low: {e.OHLC[0].LOW} Close:{e.OHLC[0].CLOSE}"); + Console.WriteLine("Quote: " + e.ToString()); } + /* +private static void Mt5_OnPrice(object? sender, Quote e) +{ + Console.WriteLine("Quote: " + e.ToString()); +} - private static void Tt_OnPrice(object? sender, Quote e) - { - Console.WriteLine($"Time: {e.TIME} Symbol: {e.SYMBOL} Ask: {e.ASK} Bid: {e.BID}"); - } +static Dictionary opened = new Dictionary(); - private static void Tt_OnConnect(object? sender, EventArgs e) - { - Console.WriteLine($"Connected!"); - } +private static void Tt_OnOrderEvent(object? sender, OrderEvent e) +{ + if (e.TRADE_RESULT != null) + { + //Console.WriteLine(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.fff") + " - " + e.ToString()); + + if (e.TRADE_REQUEST != null) + { + if (e.TRADE_REQUEST.ACTION == "TRADE_ACTION_DEAL") //Open or close position + { + if (e.TRADE_REQUEST.POSITION == 0) + { + TradeResult tr = mt5Slave.SendOrder(e.TRADE_REQUEST.SYMBOL, e.TRADE_REQUEST.VOLUME, Enum.Parse( e.TRADE_REQUEST.TYPE)); + opened.Add(e.TRADE_REQUEST.ORDER, tr.ORDER); + Console.WriteLine("New position: " + e.TRADE_REQUEST.ORDER + " Symbol: " + e.TRADE_REQUEST.SYMBOL + " Volume: " + e.TRADE_REQUEST.VOLUME); + } + else + { + mt5Slave.OrderClose(opened.FirstOrDefault(t => t.Key == e.TRADE_REQUEST.POSITION).Value); + Console.WriteLine("Position closed: " + e.TRADE_REQUEST.POSITION + " Symbol: " + e.TRADE_REQUEST.SYMBOL + " Volume: " + e.TRADE_REQUEST.VOLUME); + } + } + else if (e.TRADE_REQUEST.ACTION == "TRADE_ACTION_SLTP") //Update SL or TP + { + mt5Slave.OrderModify(opened.FirstOrDefault(t => t.Key == e.TRADE_REQUEST.POSITION).Value, e.TRADE_REQUEST.SL, e.TRADE_REQUEST.TP); + Console.WriteLine("SL or TP updated!"); + } + } + } +} + +private static void Tt_OnOHLC(object? sender, OHLC_Msg e) +{ + Console.WriteLine($"OHLC: {e.OHLC[0].TIME} {e.SYMBOL} Open: {e.OHLC[0].OPEN} High: {e.OHLC[0].HIGH} Low: {e.OHLC[0].LOW} Close:{e.OHLC[0].CLOSE}"); +} + +private static void Tt_OnPrice(object? sender, Quote e) +{ + Console.WriteLine($"Time: {e.TIME} Symbol: {e.SYMBOL} Ask: {e.ASK} Bid: {e.BID}"); +} + +private static void Tt_OnConnect(object? sender, EventArgs e) +{ + Console.WriteLine($"Connected!"); +}*/ } } \ No newline at end of file diff --git a/Test/Test.csproj b/Test/Test.csproj index 5edeb7b..99a6b1c 100644 --- a/Test/Test.csproj +++ b/Test/Test.csproj @@ -2,7 +2,7 @@ Exe - net7.0 + net8.0 enable enable