diff --git a/MtApi/MtApi.csproj b/MtApi/MtApi.csproj index d9aba4da..ee9e53aa 100755 --- a/MtApi/MtApi.csproj +++ b/MtApi/MtApi.csproj @@ -78,11 +78,12 @@ + - + diff --git a/MtApi/MtApiClient.cs b/MtApi/MtApiClient.cs index 1e164773..13896b09 100755 --- a/MtApi/MtApiClient.cs +++ b/MtApi/MtApiClient.cs @@ -96,13 +96,30 @@ namespace MtApi #region Trading functions - public int OrderSend(string symbol, TradeOperation cmd, double volume, double price, int slippage, double stoploss, double takeprofit - , string comment, int magic, DateTime expiration, Color arrow_color) + private int InternalOrderSend(string symbol, TradeOperation cmd, double volume, double? price, int? slippage, double? stoploss, double? takeprofit + , string comment, int? magic, DateTime? expiration, Color? arrowColor) { - var commandParameters = new ArrayList { symbol, (int)cmd, volume, price, slippage, stoploss, takeprofit - , comment, magic, MtApiTimeConverter.ConvertToMtTime(expiration), MtApiColorConverter.ConvertToMtColor(arrow_color) }; + var response = SendRequest(new OrderSendRequest + { + Symbol = symbol, + Cmd = (int)cmd, + Volume = volume, + Price = price, + Slippage = slippage, + Stoploss = stoploss, + Takeprofit = takeprofit, + Comment = comment, + Magic = magic, + Expiration = expiration.HasValue ? MtApiTimeConverter.ConvertToMtTime(expiration.Value) : default(int?), + ArrowColor = arrowColor.HasValue ? MtApiColorConverter.ConvertToMtColor(arrowColor.Value) : default(int?) + }); + return response != null ? response.Ticket : -1; + } - return sendCommand(MtCommandType.OrderSend, commandParameters); + public int OrderSend(string symbol, TradeOperation cmd, double volume, double price, int slippage, double stoploss, double takeprofit + , string comment, int magic, DateTime expiration, Color arrowColor) + { + return InternalOrderSend(symbol, cmd, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrowColor); } public int OrderSend(string symbol, TradeOperation cmd, double volume, double price, int slippage, double stoploss, double takeprofit @@ -131,9 +148,8 @@ namespace MtApi public int OrderSend(string symbol, TradeOperation cmd, double volume, string price, int slippage, double stoploss, double takeprofit) { double dPrice = 0; - if (Double.TryParse(price, out dPrice)) - return OrderSend(symbol, cmd, volume, dPrice, slippage, stoploss, takeprofit, null, 0, DateTime.MinValue, Color.Empty); - return 0; + return double.TryParse(price, out dPrice) ? + OrderSend(symbol, cmd, volume, dPrice, slippage, stoploss, takeprofit, null, 0, DateTime.MinValue, Color.Empty) : 0; } public int OrderSendBuy(string symbol, double volume, int slippage) @@ -158,14 +174,14 @@ namespace MtApi public int OrderSendBuy(string symbol, double volume, int slippage, double stoploss, double takeprofit, string comment, int magic) { - var commandParameters = new ArrayList { symbol, volume, slippage, stoploss, takeprofit, comment, magic }; - return sendCommand(MtCommandType.OrderSendBuy, commandParameters); + return InternalOrderSend(symbol, TradeOperation.OP_BUY, volume, null, slippage, stoploss, takeprofit, comment, + magic, null, null); } public int OrderSendSell(string symbol, double volume, int slippage, double stoploss, double takeprofit, string comment, int magic) { - var commandParameters = new ArrayList { symbol, volume, slippage, stoploss, takeprofit, comment, magic }; - return sendCommand(MtCommandType.OrderSendSell, commandParameters); + return InternalOrderSend(symbol, TradeOperation.OP_SELL, volume, null, slippage, stoploss, takeprofit, comment, + magic, null, null); } public bool OrderClose(int ticket, double lots, double price, int slippage, Color color) @@ -1331,7 +1347,11 @@ namespace MtApi if (request == null) return default(T); - var serializer = RequestContainer.CreateNew(request).Serialize(); + var serializer = JsonConvert.SerializeObject(request, Newtonsoft.Json.Formatting.None, + new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore + }); var commandParameters = new ArrayList { serializer }; MtResponseString res; diff --git a/MtApi/MtCommandType.cs b/MtApi/MtCommandType.cs index ac23fb42..164044dd 100755 --- a/MtApi/MtCommandType.cs +++ b/MtApi/MtCommandType.cs @@ -10,9 +10,9 @@ namespace MtApi //NoCommand = 0 //trade operations - OrderSend = 1, - OrderSendBuy = 1001, - OrderSendSell = 1002, +// OrderSend = 1, +// OrderSendBuy = 1001, +// OrderSendSell = 1002, OrderClose = 2, OrderCloseByCurrentPrice = 152, OrderCloseBy = 3, diff --git a/MtApi/Requests/GetOrderRequest.cs b/MtApi/Requests/GetOrderRequest.cs index cb9138f2..bd0d10a2 100644 --- a/MtApi/Requests/GetOrderRequest.cs +++ b/MtApi/Requests/GetOrderRequest.cs @@ -5,5 +5,10 @@ public int Index { get; set; } public int Select { get; set; } public int Pool { get; set; } + + public override RequestType RequestType + { + get { return RequestType.GetOrder; } + } } } \ No newline at end of file diff --git a/MtApi/Requests/GetOrdersRequest.cs b/MtApi/Requests/GetOrdersRequest.cs index cd3f1ffb..41777ce4 100644 --- a/MtApi/Requests/GetOrdersRequest.cs +++ b/MtApi/Requests/GetOrdersRequest.cs @@ -3,5 +3,10 @@ public class GetOrdersRequest: RequestBase { public int Pool { get; set; } + + public override RequestType RequestType + { + get { return RequestType.GetOrders; } + } } } \ No newline at end of file diff --git a/MtApi/Requests/OrderSendRequest.cs b/MtApi/Requests/OrderSendRequest.cs new file mode 100644 index 00000000..001caec4 --- /dev/null +++ b/MtApi/Requests/OrderSendRequest.cs @@ -0,0 +1,23 @@ +namespace MtApi.Requests +{ + public class OrderSendRequest: RequestBase + { + public string Symbol { get; set; } + public int Cmd { get; set; } + public double Volume { get; set; } + + public double? Price { get; set; } + public int? Slippage { get; set; } + public double? Stoploss { get; set; } + public double? Takeprofit { get; set; } + public string Comment { get; set; } + public int? Magic { get; set; } + public int? Expiration { get; set; } + public int? ArrowColor { get; set; } + + public override RequestType RequestType + { + get { return RequestType.OrderSend; } + } + } +} \ No newline at end of file diff --git a/MtApi/Requests/RequestBase.cs b/MtApi/Requests/RequestBase.cs index fac684c9..666b2a1a 100644 --- a/MtApi/Requests/RequestBase.cs +++ b/MtApi/Requests/RequestBase.cs @@ -1,6 +1,9 @@ -namespace MtApi.Requests +using Newtonsoft.Json; + +namespace MtApi.Requests { public abstract class RequestBase - { + { + public abstract RequestType RequestType { get; } } } diff --git a/MtApi/Requests/RequestContainer.cs b/MtApi/Requests/RequestContainer.cs deleted file mode 100644 index 9075086f..00000000 --- a/MtApi/Requests/RequestContainer.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace MtApi.Requests -{ - public class RequestContainer - { - private static readonly Dictionary RequestTypes = new Dictionary(); - - static RequestContainer() - { - RequestTypes[typeof (GetOrderRequest)] = RequestType.GetOrder; - RequestTypes[typeof(GetOrdersRequest)] = RequestType.GetOrders; - } - - public RequestType RequestType { get; set; } - public RequestBase Request { get; set; } - - public virtual string Serialize() - { - return JsonConvert.SerializeObject(this); - } - - public static RequestContainer CreateNew(T request) where T: RequestBase - { - if (RequestTypes.ContainsKey(request.GetType()) == false) - throw new ArgumentException("Unknown request type"); - - return new RequestContainer { RequestType = RequestTypes[request.GetType()], Request = request }; - } - } -} \ No newline at end of file diff --git a/MtApi/Requests/RequestType.cs b/MtApi/Requests/RequestType.cs index dca2cd9f..a93ceb59 100644 --- a/MtApi/Requests/RequestType.cs +++ b/MtApi/Requests/RequestType.cs @@ -4,6 +4,7 @@ { Unknown = 0, GetOrder = 1, - GetOrders = 2 + GetOrders = 2, + OrderSend = 3 } } \ No newline at end of file diff --git a/MtApi/Responses/OrderSendResponse.cs b/MtApi/Responses/OrderSendResponse.cs new file mode 100644 index 00000000..fea4d10d --- /dev/null +++ b/MtApi/Responses/OrderSendResponse.cs @@ -0,0 +1,7 @@ +namespace MtApi.Responses +{ + public class OrderSendResponse: ResponseBase + { + public int Ticket { get; set; } + } +} \ No newline at end of file diff --git a/TestApiClientUI/Form1.Designer.cs b/TestApiClientUI/Form1.Designer.cs index 1541fa3b..d29bbcc4 100755 --- a/TestApiClientUI/Form1.Designer.cs +++ b/TestApiClientUI/Form1.Designer.cs @@ -45,6 +45,7 @@ this.colAsk = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.colFeedCount = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.listBoxEventLog = new System.Windows.Forms.ListBox(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); this.tabControl1 = new System.Windows.Forms.TabControl(); this.tabPage2 = new System.Windows.Forms.TabPage(); this.button17 = new System.Windows.Forms.Button(); @@ -120,7 +121,8 @@ this.button15 = new System.Windows.Forms.Button(); this.button14 = new System.Windows.Forms.Button(); this.button13 = new System.Windows.Forms.Button(); - this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.button18 = new System.Windows.Forms.Button(); + this.button19 = new System.Windows.Forms.Button(); this.groupBox1.SuspendLayout(); this.statusStrip1.SuspendLayout(); this.groupBox2.SuspendLayout(); @@ -207,7 +209,7 @@ // this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripStatusConnection}); - this.statusStrip1.Location = new System.Drawing.Point(0, 637); + this.statusStrip1.Location = new System.Drawing.Point(0, 668); this.statusStrip1.Name = "statusStrip1"; this.statusStrip1.Size = new System.Drawing.Size(713, 22); this.statusStrip1.TabIndex = 11; @@ -271,12 +273,18 @@ | System.Windows.Forms.AnchorStyles.Right))); this.listBoxEventLog.ContextMenuStrip = this.contextMenuStrip1; this.listBoxEventLog.FormattingEnabled = true; - this.listBoxEventLog.Location = new System.Drawing.Point(12, 543); + this.listBoxEventLog.Location = new System.Drawing.Point(12, 556); this.listBoxEventLog.Name = "listBoxEventLog"; - this.listBoxEventLog.Size = new System.Drawing.Size(690, 82); + this.listBoxEventLog.Size = new System.Drawing.Size(690, 95); this.listBoxEventLog.TabIndex = 14; this.listBoxEventLog.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.listBoxEventLog_MouseDoubleClick); // + // contextMenuStrip1 + // + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(61, 4); + this.contextMenuStrip1.Text = "Clear"; + // // tabControl1 // this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) @@ -290,7 +298,7 @@ this.tabControl1.Location = new System.Drawing.Point(12, 147); this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; - this.tabControl1.Size = new System.Drawing.Size(690, 388); + this.tabControl1.Size = new System.Drawing.Size(690, 403); this.tabControl1.TabIndex = 15; // // tabPage2 @@ -311,7 +319,7 @@ this.tabPage2.Location = new System.Drawing.Point(4, 22); this.tabPage2.Name = "tabPage2"; this.tabPage2.Padding = new System.Windows.Forms.Padding(3); - this.tabPage2.Size = new System.Drawing.Size(682, 362); + this.tabPage2.Size = new System.Drawing.Size(682, 377); this.tabPage2.TabIndex = 1; this.tabPage2.Text = "Trade Operations"; this.tabPage2.UseVisualStyleBackColor = true; @@ -405,7 +413,7 @@ "OrderTakeProfit", "OrderTicket", "OrderType"}); - this.comboBoxSelectedCommand.Location = new System.Drawing.Point(216, 313); + this.comboBoxSelectedCommand.Location = new System.Drawing.Point(216, 292); this.comboBoxSelectedCommand.Name = "comboBoxSelectedCommand"; this.comboBoxSelectedCommand.Size = new System.Drawing.Size(121, 21); this.comboBoxSelectedCommand.TabIndex = 6; @@ -440,7 +448,7 @@ // // button2 // - this.button2.Location = new System.Drawing.Point(343, 313); + this.button2.Location = new System.Drawing.Point(343, 292); this.button2.Name = "button2"; this.button2.Size = new System.Drawing.Size(87, 23); this.button2.TabIndex = 2; @@ -450,6 +458,8 @@ // // groupBox3 // + this.groupBox3.Controls.Add(this.button19); + this.groupBox3.Controls.Add(this.button18); this.groupBox3.Controls.Add(this.comboBoxOrderColor); this.groupBox3.Controls.Add(this.textBox2); this.groupBox3.Controls.Add(this.textBoxOrderMagic); @@ -475,7 +485,7 @@ this.groupBox3.Controls.Add(this.label9); this.groupBox3.Location = new System.Drawing.Point(6, 6); this.groupBox3.Name = "groupBox3"; - this.groupBox3.Size = new System.Drawing.Size(201, 335); + this.groupBox3.Size = new System.Drawing.Size(201, 365); this.groupBox3.TabIndex = 5; this.groupBox3.TabStop = false; this.groupBox3.Text = "Send Order"; @@ -546,9 +556,19 @@ // numericOrderSlippage // this.numericOrderSlippage.Location = new System.Drawing.Point(70, 122); + this.numericOrderSlippage.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); this.numericOrderSlippage.Name = "numericOrderSlippage"; this.numericOrderSlippage.Size = new System.Drawing.Size(120, 20); this.numericOrderSlippage.TabIndex = 9; + this.numericOrderSlippage.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); // // label19 // @@ -688,7 +708,7 @@ this.listBoxSendedOrders.Location = new System.Drawing.Point(213, 23); this.listBoxSendedOrders.Name = "listBoxSendedOrders"; this.listBoxSendedOrders.SelectionMode = System.Windows.Forms.SelectionMode.MultiSimple; - this.listBoxSendedOrders.Size = new System.Drawing.Size(463, 108); + this.listBoxSendedOrders.Size = new System.Drawing.Size(463, 121); this.listBoxSendedOrders.TabIndex = 1; // // tabPage1 @@ -1131,17 +1151,31 @@ this.button13.UseVisualStyleBackColor = true; this.button13.Click += new System.EventHandler(this.button13_Click); // - // contextMenuStrip1 + // button18 // - this.contextMenuStrip1.Name = "contextMenuStrip1"; - this.contextMenuStrip1.Size = new System.Drawing.Size(61, 4); - this.contextMenuStrip1.Text = "Clear"; + this.button18.Location = new System.Drawing.Point(6, 336); + this.button18.Name = "button18"; + this.button18.Size = new System.Drawing.Size(75, 23); + this.button18.TabIndex = 14; + this.button18.Text = "Buy"; + this.button18.UseVisualStyleBackColor = true; + this.button18.Click += new System.EventHandler(this.button18_Click); + // + // button19 + // + this.button19.Location = new System.Drawing.Point(87, 336); + this.button19.Name = "button19"; + this.button19.Size = new System.Drawing.Size(75, 23); + this.button19.TabIndex = 15; + this.button19.Text = "Sell"; + this.button19.UseVisualStyleBackColor = true; + this.button19.Click += new System.EventHandler(this.button19_Click); // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(713, 659); + this.ClientSize = new System.Drawing.Size(713, 690); this.ContextMenuStrip = this.contextMenuStrip1; this.Controls.Add(this.listBoxEventLog); this.Controls.Add(this.tabControl1); @@ -1270,6 +1304,8 @@ private System.Windows.Forms.ComboBox comboBox2; private System.Windows.Forms.Button button17; private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.Button button19; + private System.Windows.Forms.Button button18; } } diff --git a/TestApiClientUI/Form1.cs b/TestApiClientUI/Form1.cs index fe3ebf3f..0eea5392 100755 --- a/TestApiClientUI/Form1.cs +++ b/TestApiClientUI/Form1.cs @@ -219,17 +219,25 @@ namespace TestApiClientUI private void sendOrder(string symbol, TradeOperation command, double volume, double price, int slippage, double stoploss, double takeprofit , string comment, int magic, DateTime expiration, Color arrow_color) { - int orderId = apiClient.OrderSend(symbol, command, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrow_color); - RunOnUiThread(() => - { - if (orderId >= 0) - { - listBoxSendedOrders.Items.Add(orderId); - } + int ticket = 0; + try + { + ticket = apiClient.OrderSend(symbol, command, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrow_color); + } + catch (MtConnectionException ex) + { + addToLog("MtExecutionException: " + ex.Message); + return; + } + catch (MtExecutionException ex) + { + addToLog("MtExecutionException: " + ex.Message + "; ErrorCode = " + ex.ErrorCode); + return; + } - addToLog(string.Format("Sended order result: ticketId = {0}, volume - {1}", orderId, volume, slippage)); - }); + addToLog(string.Format("Sended order result: ticketId = {0}, symbol = {1}, volume = {2}, slippage = {3}", + ticket, symbol, volume, slippage)); } private void button1_Click(object sender, EventArgs e) @@ -981,5 +989,63 @@ namespace TestApiClientUI { listBoxEventLog.Items.Clear(); } + + private void button18_Click(object sender, EventArgs e) + { + var symbol = textBoxOrderSymbol.Text; + + double volume; + double.TryParse(textBoxOrderVolume.Text, out volume); + + var slippage = (int)numericOrderSlippage.Value; + + int ticket = 0; + try + { + ticket = apiClient.OrderSendBuy(symbol, volume, slippage); + } + catch (MtConnectionException ex) + { + addToLog("MtExecutionException: " + ex.Message); + return; + } + catch (MtExecutionException ex) + { + addToLog("MtExecutionException: " + ex.Message + "; ErrorCode = " + ex.ErrorCode); + return; + } + + addToLog(string.Format("Sended order result: ticketId = {0}, symbol = {1}, volume = {2}, slippage = {3}", + ticket, symbol, volume, slippage)); + } + + private void button19_Click(object sender, EventArgs e) + { + var symbol = textBoxOrderSymbol.Text; + + double volume; + double.TryParse(textBoxOrderVolume.Text, out volume); + + var slippage = (int)numericOrderSlippage.Value; + + int ticket = 0; + try + { + ticket = apiClient.OrderSendSell(symbol, volume, slippage); + } + catch (MtConnectionException ex) + { + addToLog("MtExecutionException: " + ex.Message); + return; + } + catch (MtExecutionException ex) + { + addToLog("MtExecutionException: " + ex.Message + "; ErrorCode = " + ex.ErrorCode); + return; + } + + addToLog(string.Format("Sended order result: ticketId = {0}, symbol = {1}, volume = {2}, slippage = {3}", + ticket, symbol, volume, slippage)); + } } } diff --git a/mq4/MtApi.ex4 b/mq4/MtApi.ex4 index 838f11fd..4974266d 100755 Binary files a/mq4/MtApi.ex4 and b/mq4/MtApi.ex4 differ diff --git a/mq4/MtApi.mq4 b/mq4/MtApi.mq4 index aa7c0f6d..44c62cbd 100755 --- a/mq4/MtApi.mq4 +++ b/mq4/MtApi.mq4 @@ -3627,31 +3627,24 @@ string OnRequest(string json) { JSONObject *jo = jv; int requestType = jo.getInt("RequestType"); - JSONObject *joRequest = jo.getObject("Request"); - - if (joRequest != NULL) + + Print("OnRequest: RequestType = ", requestType); + switch(requestType) { - Print("OnRequest: RequestType = ", requestType); - - switch(requestType) - { - case 1: //GetOrder - response = ExecuteRequestGetOrder(joRequest); - break; - case 2: //GetOrders - response = ExecuteRequestGetOrders(joRequest); - break; - default: - Print("OnRequest [WARNING]: Unknown request type ", requestType); - response = CreateErrorResponse(-1, "Unknown request type"); - break; - } + case 1: //GetOrder + response = ExecuteRequestGetOrder(jo); + break; + case 2: //GetOrders + response = ExecuteRequestGetOrders(jo); + break; + case 3: //OrderSend + response = ExecuteRequestOrderSend(jo); + break; + default: + Print("OnRequest [WARNING]: Unknown request type ", requestType); + response = CreateErrorResponse(-1, "Unknown request type"); + break; } - else - { - Print("OnRequest [WARNING]: Request field is not defined"); - response = CreateErrorResponse(-1, "Request field is not defined"); - } } delete jv; @@ -3735,3 +3728,67 @@ string ExecuteRequestGetOrders(JSONObject *jo) return CreateSuccessResponse("Orders", joOrders); } + +bool isLongOperation(int operation) +{ + if (operation == OP_BUY || operation == OP_BUYLIMIT || operation == OP_BUYSTOP) + return true; + return false; +} + +string ExecuteRequestOrderSend(JSONObject *jo) +{ + if (jo.getValue("Symbol") == NULL) + return CreateErrorResponse(-1, "Undefinded mandatory parameter Symbol"); + if (jo.getValue("Cmd") == NULL) + return CreateErrorResponse(-1, "Undefinded mandatory parameter Cmd"); + if (jo.getValue("Volume") == NULL) + return CreateErrorResponse(-1, "Undefinded mandatory parameter Volume"); + + string symbol = jo.getString("Symbol"); + int cmd = jo.getInt("Cmd"); + int volume = jo.getDouble("Volume"); + + double price; + + JSONValue *jvPrice = jo.getValue("Price"); + if (jvPrice != NULL) + { + price = jvPrice.getDouble(); + Print("Take price from request ", price); + } + else + { + int mode = isLongOperation(cmd) ? MODE_ASK : MODE_BID; + price = MarketInfo(symbol, mode); + Print("Take price by mode ", mode, " and choosen price ", price); + } + + JSONValue *jvSlippage = jo.getValue("Slippage"); + double slippage = (jvSlippage != NULL) ? jvSlippage.getDouble() : 1; + + JSONValue *jvStoploss = jo.getValue("Stoploss"); + double stoploss = (jvStoploss != NULL) ? jvStoploss.getDouble() : 0; + + JSONValue *jvTakeprofit = jo.getValue("Takeprofit"); + double takeprofit = (jvTakeprofit != NULL) ? jvTakeprofit.getDouble() : 0; + + JSONValue *jvComment = jo.getValue("Comment"); + string comment = (jvComment != NULL) ? jvComment.getString() : NULL; + + JSONValue *jvMagic = jo.getValue("Magic"); + int magic = (jvMagic != NULL) ? jvMagic.getInt() : 0; + + JSONValue *jvExpiration = jo.getValue("Expiration"); + int expiration = (jvExpiration != NULL) ? jvExpiration.getInt() : 0; + + JSONValue *jvArrowColor = jo.getValue("ArrowColor"); + int arrowcolor = (jvArrowColor != NULL) ? jvArrowColor.getInt() : clrNONE; + + int ticket = OrderSend(symbol, cmd, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrowcolor); + if(ticket < 0) + return CreateErrorResponse(GetLastError(), "OrderSend failed"); + + JSONValue* jvTicket = new JSONNumber(ticket); + return CreateSuccessResponse("Ticket", jvTicket); +}