diff --git a/.gitignore b/.gitignore index 9bea433..40d9456 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,10 @@ .DS_Store + +*.mq5:CursorPos:$DATA + +*.mq5:LineFlags:$DATA + +*.mqh:CursorPos:$DATA + +*.mqh:LineFlags:$DATA diff --git a/Experts/JsonAPI.ex5 b/Experts/JsonAPI.ex5 new file mode 100644 index 0000000..36f0178 Binary files /dev/null and b/Experts/JsonAPI.ex5 differ diff --git a/Experts/JsonAPI.mq5 b/Experts/JsonAPI.mq5 index bc1576c..4f8f7b2 100644 --- a/Experts/JsonAPI.mq5 +++ b/Experts/JsonAPI.mq5 @@ -23,7 +23,7 @@ #property link "https://github.com/khramkov" #property version "2.00" #property description "MQL5 JSON API" -#property description "See github link for documentation" +#property description "See github link for documentation" #include #include @@ -39,9 +39,13 @@ int SYS_PORT=15555; int DATA_PORT=15556; int LIVE_PORT=15557; int STR_PORT=15558; +/* int INDICATOR_DATA_PORT=15559; +*/ +/* int CHART_DATA_PORT=15560; int CHART_INDICATOR_DATA_PORT=15562; +*/ // ZeroMQ Cnnections Context context("MQL5 JSON API"); @@ -49,9 +53,14 @@ Socket sysSocket(context,ZMQ_REP); Socket dataSocket(context,ZMQ_PUSH); Socket liveSocket(context,ZMQ_PUSH); Socket streamSocket(context,ZMQ_PUSH); +/* Socket indicatorDataSocket(context,ZMQ_PUSH); Socket chartDataSocket(context,ZMQ_PULL); Socket chartIndicatorDataSocket(context,ZMQ_PUB); +*/ +#include +#include +#include // Global variables \\ bool debug = false; @@ -61,45 +70,52 @@ int deInitReason = -1; double chartAttached = ChartID(); // Chart id where the expert is attached to // Variables for handling price data stream -struct SymbolSubscription { - string symbol; - string chartTf; - datetime lastBar; -}; +struct SymbolSubscription + { + string symbol; + string chartTf; + datetime lastBar; + }; SymbolSubscription symbolSubscriptions[]; int symbolSubscriptionCount = 0; +/* // Variables for controlling indicators -struct Indicator { - long id; // Internal id - string indicatorId; // UUID - int indicatorHandle; // Internal id/handle - int indicatorParamCount; // Number of parameters to be passed to the indicator - int indicatorBufferCount; // Numnber of buffers to be returned bythe indicator -}; +struct Indicator + { + long id; // Internal id + string indicatorId; // UUID + int indicatorHandle; // Internal id/handle + int indicatorParamCount; // Number of parameters to be passed to the indicator + int indicatorBufferCount; // Numnber of buffers to be returned bythe indicator + }; + Indicator indicators[]; int indicatorCount = 0; // Variables for controlling chart -struct ChartWindow { - long id; // Internal id - string chartId; // UUID -}; +struct ChartWindow + { + long id; // Internal id + string chartId; // UUID + }; +*/ + +/* ChartWindow chartWindows[]; int chartWindowCount = 0; -struct ChartWindowIndicator { - long id; // Internal id - string indicatorId; // UUID - int indicatorHandle; // Internal id/handle -}; +struct ChartWindowIndicator + { + long id; // Internal id + string indicatorId; // UUID + int indicatorHandle; // Internal id/handle + }; ChartWindowIndicator chartWindowIndicators[]; int chartWindowIndicatorCount = 0; -// Refresh chart window interval for JsonAPIIndicator -int chartWindowTimerInterval = 100; // Cycles of the globally set EventSetMillisecondTimer interval -int chartWindowTimerCounter = 0; // Keeps track of the current cycle +*/ // Error handling ControlErrors mControl; @@ -107,96 +123,164 @@ ControlErrors mControl; //+------------------------------------------------------------------+ //| Bind ZMQ sockets to ports | //+------------------------------------------------------------------+ -bool BindSockets(){ - bool result = false; - result = sysSocket.bind(StringFormat("tcp://%s:%d", HOST,SYS_PORT)); - if (result == false) { return result; } else {Print("Bound 'System' socket on port ", SYS_PORT);} - result = dataSocket.bind(StringFormat("tcp://%s:%d", HOST,DATA_PORT)); - if (result == false) { return result; } else {Print("Bound 'Data' socket on port ", DATA_PORT);} - result = liveSocket.bind(StringFormat("tcp://%s:%d", HOST,LIVE_PORT)); - if (result == false) { return result; } else {Print("Bound 'Live' socket on port ", LIVE_PORT);} - result = streamSocket.bind(StringFormat("tcp://%s:%d", HOST,STR_PORT)); - if (result == false) { return result; } else {Print("Bound 'Streaming' socket on port ", STR_PORT);} - result = indicatorDataSocket.bind(StringFormat("tcp://%s:%d", HOST,INDICATOR_DATA_PORT)); - if (result == false) { return result; } else {Print("Bound 'Indicator Data' socket on port ", INDICATOR_DATA_PORT);} - result = chartDataSocket.bind(StringFormat("tcp://%s:%d", HOST,CHART_DATA_PORT)); - if (result == false) { return result; } else {Print("Bound 'Chart Data' socket on port ", CHART_DATA_PORT);} - result = chartIndicatorDataSocket.bind(StringFormat("tcp://%s:%d", HOST,CHART_INDICATOR_DATA_PORT)); - if (result == false) { return result; } else {Print("Bound 'JsonAPIIndicator Data' socket on port ", CHART_INDICATOR_DATA_PORT);} - - sysSocket.setLinger(1000); - dataSocket.setLinger(1000); - liveSocket.setLinger(1000); - streamSocket.setLinger(1000); - indicatorDataSocket.setLinger(1000); - chartDataSocket.setLinger(1000); - chartIndicatorDataSocket.setLinger(1000); - - // Number of messages to buffer in RAM. - sysSocket.setSendHighWaterMark(1); - dataSocket.setSendHighWaterMark(5); - liveSocket.setSendHighWaterMark(1); - streamSocket.setSendHighWaterMark(50); - indicatorDataSocket.setSendHighWaterMark(5); - chartDataSocket.setReceiveHighWaterMark(1); // TODO confirm settings - chartIndicatorDataSocket.setReceiveHighWaterMark(1); +bool BindSockets() + { + sysSocket.setLinger(1000); + dataSocket.setLinger(1000); + liveSocket.setLinger(1000); + streamSocket.setLinger(1000); +#ifdef START_INDICATOR + indicatorDataSocket.setLinger(1000); +#endif +#ifdef CHART_CONTROL + chartDataSocket.setLinger(1000); + chartIndicatorDataSocket.setLinger(1000); +#endif - return result; -} +// Number of messages to buffer in RAM. + sysSocket.setSendHighWaterMark(1000); + dataSocket.setSendHighWaterMark(1000); + liveSocket.setSendHighWaterMark(1000); + streamSocket.setSendHighWaterMark(1000); +#ifdef START_INDICATOR + indicatorDataSocket.setSendHighWaterMark(1000); +#endif +#ifdef CHART_CONTROL + chartDataSocket.setReceiveHighWaterMark(1000); // TODO confirm settings + chartIndicatorDataSocket.setReceiveHighWaterMark(1000); +#endif + + bool result = false; + result = sysSocket.bind(StringFormat("tcp://%s:%d", HOST,SYS_PORT)); + if(result == false) + { + return result; + } + else + { + Print("Bound 'System' socket on port ", SYS_PORT); + } + result = dataSocket.bind(StringFormat("tcp://%s:%d", HOST,DATA_PORT)); + if(result == false) + { + return result; + } + else + { + Print("Bound 'Data' socket on port ", DATA_PORT); + } + result = liveSocket.bind(StringFormat("tcp://%s:%d", HOST,LIVE_PORT)); + if(result == false) + { + return result; + } + else + { + Print("Bound 'Live' socket on port ", LIVE_PORT); + } + result = streamSocket.bind(StringFormat("tcp://%s:%d", HOST,STR_PORT)); + if(result == false) + { + return result; + } + else + { + Print("Bound 'Streaming' socket on port ", STR_PORT); + } +#ifdef START_INDICATOR + result = indicatorDataSocket.bind(StringFormat("tcp://%s:%d", HOST,INDICATOR_DATA_PORT)); + if(result == false) + { + return result; + } + else + { + Print("Bound 'Indicator Data' socket on port ", INDICATOR_DATA_PORT); + } +#endif +#ifdef CHART_CONTROL + result = chartDataSocket.bind(StringFormat("tcp://%s:%d", HOST,CHART_DATA_PORT)); + if(result == false) + { + return result; + } + else + { + Print("Bound 'Chart Data' socket on port ", CHART_DATA_PORT); + } + result = chartIndicatorDataSocket.bind(StringFormat("tcp://%s:%d", HOST,CHART_INDICATOR_DATA_PORT)); + if(result == false) + { + return result; + } + else + { + Print("Bound 'JsonAPIIndicator Data' socket on port ", CHART_INDICATOR_DATA_PORT); + } +#endif + return result; + } //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ -int OnInit(){ +int OnInit() + { - // Setting up error reporting - mControl.SetAlert(true); - mControl.SetSound(false); - mControl.SetWriteFlag(false); - - /* Bindinig ZMQ ports on init */ - // Skip reloading of the EA script when the reason to reload is a chart timeframe change - if (deInitReason != REASON_CHARTCHANGE){ - - EventSetMillisecondTimer(1); +// Setting up error reporting + mControl.SetAlert(true); + mControl.SetSound(false); + mControl.SetWriteFlag(false); - int bindSocketsDelay = 65; // Seconds to wait if binding of sockets fails. - int bindAttemtps = 2; // Number of binding attemtps - - Print("Binding sockets..."); - - for(int i=0;i0){ - // Pull request to RequestHandler(). - RequestHandler(request); - } - - // Publish indicator values for the JsonAPIIndicator indicator - ZmqMsg chartMsg; - chartDataSocket.recv(chartMsg, true); - if(chartMsg.size()>0){ +// Stream live price data + StreamPriceData(); + + ZmqMsg request; + +// Get request from client via System socket. + sysSocket.recv(request,true); + +// Request recived + if(request.size()>0) + { + // Pull request to RequestHandler(). + RequestHandler(request); + } +#ifdef CHART_CONTROL +// Publish indicator values for the JsonAPIIndicator indicator + ZmqMsg chartMsg; + chartDataSocket.recv(chartMsg, true); + if(chartMsg.size()>0) + { double values[]; // Ensure that all indicators have finished intitailisation - for(int i=0;i= chartWindowTimerInterval) { - for(int i=0;i= 0) { - if(CopyBuffer(indicators[idx].indicatorHandle, i, fromDate, 1, values) < 0) { - if(mControl.mGetLastError()) - { - CJAVal message; - int lastError = mControl.mGetLastError(); - string desc = mControl.mGetDesc(); - mControl.Check(); + datetime fromDate=dataObject["fromDate"].ToInt(); + string id=dataObject["id"].ToStr(); + string indicatorName=dataObject["indicatorName"].ToStr(); + + int idx = GetIndicatorIdxByIndicatorId(id); + + double values[2]; + + CJAVal results; +// Cycle through all avaliable buffer positions + for(int i=0; i= 0) + { + if(CopyBuffer(indicators[idx].indicatorHandle, i, fromDate, 1, values) < 0) + { + if(mControl.mGetLastError()) + { + CJAVal message; + int lastError = mControl.mGetLastError(); + string desc = mControl.mGetDesc(); + mControl.Check(); + + message["error"]=(bool) true; + message["lastError"]=(string) lastError; + message["description"]=desc; + message["function"]=(string) __FUNCTION__; + string t=message.Serialize(); + if(debug) + Print(t); + InformClientSocket(indicatorDataSocket,t); + } + } + results[i] = DoubleToString(values[0]); + } + } + + CJAVal message; + message["error"]=(bool) false; + message["id"] = (string) id; + message["data"].Set(results); + + string t=message.Serialize(); + if(debug) + Print(t); + InformClientSocket(indicatorDataSocket,t); - message["error"]=(bool) true; - message["lastError"]=(string) lastError; - message["description"]=desc; - message["function"]=(string) __FUNCTION__; - string t=message.Serialize(); - if(debug) Print(t); - InformClientSocket(indicatorDataSocket,t); - } - } - results[i] = DoubleToString(values[0]); - } } +*/ - CJAVal message; - message["error"]=(bool) false; - message["id"] = (string) id; - message["data"].Set(results); - - string t=message.Serialize(); - if(debug) Print(t); - InformClientSocket(indicatorDataSocket,t); - -} - +/* //+------------------------------------------------------------------+ //| Open new chart or add indicator to chart | //+------------------------------------------------------------------+ -void ChartControl(CJAVal &dataObject){ +void ChartControl(CJAVal &dataObject) + { - string actionType=dataObject["actionType"].ToStr(); + string actionType=dataObject["actionType"].ToStr(); - if(actionType=="ADDINDICATOR") { - AddChartIndicator(dataObject); + if(actionType=="ADDINDICATOR") + { + AddChartIndicator(dataObject); + } + else + if(actionType=="OPEN") + { + OpenChart(dataObject); + } } - else if(actionType=="OPEN") { - OpenChart(dataObject); - } -} //+------------------------------------------------------------------+ //| Open new chart | //+------------------------------------------------------------------+ -void OpenChart(CJAVal &dataObject){ +void OpenChart(CJAVal &dataObject) + { - string chartId=dataObject["chartId"].ToStr(); - string symbol=dataObject["symbol"].ToStr(); - string chartTF=dataObject["chartTF"].ToStr(); - - chartWindowCount++; - ArrayResize(chartWindows,chartWindowCount); - - int idx = chartWindowCount-1; - - chartWindows[idx].chartId = chartId; + string chartId=dataObject["chartId"].ToStr(); + string symbol=dataObject["symbol"].ToStr(); + string chartTF=dataObject["chartTF"].ToStr(); - ENUM_TIMEFRAMES period = GetTimeframe(chartTF); - chartWindows[idx].id = ChartOpen(symbol, period); - ChartSetInteger(chartWindows[idx].id, CHART_AUTOSCROLL, false); - - CJAVal message; - message["error"]=(bool) false; - message["chartId"] = (string) chartId; - - string t=message.Serialize(); - if(debug) Print(t); - InformClientSocket(dataSocket,t); -} + chartWindowCount++; + ArrayResize(chartWindows,chartWindowCount); + + int idx = chartWindowCount-1; + + chartWindows[idx].chartId = chartId; + + ENUM_TIMEFRAMES period = GetTimeframe(chartTF); + chartWindows[idx].id = ChartOpen(symbol, period); + ChartSetInteger(chartWindows[idx].id, CHART_AUTOSCROLL, false); + + CJAVal message; + message["error"]=(bool) false; + message["chartId"] = (string) chartId; + message["mtChartId"] = (string) chartWindows[idx].id; + + string t=message.Serialize(); + if(debug) + Print(t); + InformClientSocket(dataSocket,t); + } //+------------------------------------------------------------------+ //| Add JsonAPIIndicator indicator to chart | //+------------------------------------------------------------------+ -void AddChartIndicator(CJAVal &dataObject){ +void AddChartIndicator(CJAVal &dataObject) + { - string chartIdStr=dataObject["chartId"].ToStr(); - string chartIndicatorId=dataObject["indicatorChartId"].ToStr(); - int chartIndicatorSubWindow=dataObject["chartIndicatorSubWindow"].ToInt(); - //string shortname = dataObject["style"]["shortname"].ToStr(); + string chartIdStr=dataObject["chartId"].ToStr(); + string chartIndicatorId=dataObject["chartIndicatorId"].ToStr(); + int chartIndicatorSubWindow=dataObject["chartIndicatorSubWindow"].ToInt(); + string shortName = dataObject["shortName"].ToStr(); - int chartIdx = GetChartWindowIdxByChartWindowId(chartIdStr); - long ChartId = chartWindows[chartIdx].id; + int chartIdx = GetChartWindowIdxByChartWindowId(chartIdStr); + long chartId = chartWindows[chartIdx].id; - double chartIndicatorHandle = iCustom(ChartSymbol(ChartId),ChartPeriod(ChartId),"JsonAPIIndicator",chartIndicatorId,"JsonAPI"); //linelabel,colorstyle,linetype,linestyle,linewidth); - - if(ChartIndicatorAdd(ChartId, chartIndicatorSubWindow, chartIndicatorHandle)) { - chartWindowIndicatorCount++; - ArrayResize(chartWindowIndicators,chartWindowIndicatorCount); - int indicatorIdx = chartWindowIndicatorCount-1; - chartWindowIndicators[indicatorIdx].indicatorId = chartIndicatorId; - chartWindowIndicators[indicatorIdx].indicatorHandle = chartIndicatorHandle; + double chartIndicatorHandle = iCustom(ChartSymbol(chartId),ChartPeriod(chartId),"JsonAPIIndicator",chartIndicatorId,shortName); //linelabel,colorstyle,linetype,linestyle,linewidth); + + if(ChartIndicatorAdd(chartId, chartIndicatorSubWindow, chartIndicatorHandle)) + { + chartWindowIndicatorCount++; + ArrayResize(chartWindowIndicators,chartWindowIndicatorCount); + int indicatorIdx = chartWindowIndicatorCount-1; + chartWindowIndicators[indicatorIdx].indicatorId = chartIndicatorId; + chartWindowIndicators[indicatorIdx].indicatorHandle = chartIndicatorHandle; + } + if(!CheckError(__FUNCTION__)) + { + CJAVal message; + message["error"]=(bool) false; + message["chartId"] = (string) chartIdStr; + + string t=message.Serialize(); + if(debug) + Print(t); + InformClientSocket(dataSocket,t); + } } - if(!CheckError(__FUNCTION__)) { - CJAVal message; - message["error"]=(bool) false; - message["chartId"] = (string) chartIdStr; - - string t=message.Serialize(); - if(debug) Print(t); - InformClientSocket(dataSocket,t); - } -} - +*/ //+------------------------------------------------------------------+ //| Account information | //+------------------------------------------------------------------+ -void GetAccountInfo(){ - - CJAVal info; - - info["error"] = false; - info["broker"] = AccountInfoString(ACCOUNT_COMPANY); - info["currency"] = AccountInfoString(ACCOUNT_CURRENCY); - info["server"] = AccountInfoString(ACCOUNT_SERVER); - info["trading_allowed"] = TerminalInfoInteger(TERMINAL_TRADE_ALLOWED); - info["bot_trading"] = AccountInfoInteger(ACCOUNT_TRADE_EXPERT); - info["balance"] = AccountInfoDouble(ACCOUNT_BALANCE); - info["equity"] = AccountInfoDouble(ACCOUNT_EQUITY); - info["margin"] = AccountInfoDouble(ACCOUNT_MARGIN); - info["margin_free"] = AccountInfoDouble(ACCOUNT_MARGIN_FREE); - info["margin_level"] = AccountInfoDouble(ACCOUNT_MARGIN_LEVEL); - - string t=info.Serialize(); - if(debug) Print(t); - InformClientSocket(dataSocket,t); -} +void GetAccountInfo() + { + + CJAVal info; + + info["error"] = false; + info["broker"] = AccountInfoString(ACCOUNT_COMPANY); + info["currency"] = AccountInfoString(ACCOUNT_CURRENCY); + info["server"] = AccountInfoString(ACCOUNT_SERVER); + info["trading_allowed"] = TerminalInfoInteger(TERMINAL_TRADE_ALLOWED); + info["bot_trading"] = AccountInfoInteger(ACCOUNT_TRADE_EXPERT); + info["balance"] = AccountInfoDouble(ACCOUNT_BALANCE); + info["equity"] = AccountInfoDouble(ACCOUNT_EQUITY); + info["margin"] = AccountInfoDouble(ACCOUNT_MARGIN); + info["margin_free"] = AccountInfoDouble(ACCOUNT_MARGIN_FREE); + info["margin_level"] = AccountInfoDouble(ACCOUNT_MARGIN_LEVEL); + + string t=info.Serialize(); + if(debug) + Print(t); + InformClientSocket(dataSocket,t); + } //+------------------------------------------------------------------+ //| Balance information | //+------------------------------------------------------------------+ -void GetBalanceInfo(){ - - CJAVal info; - info["balance"] = AccountInfoDouble(ACCOUNT_BALANCE); - info["equity"] = AccountInfoDouble(ACCOUNT_EQUITY); - info["margin"] = AccountInfoDouble(ACCOUNT_MARGIN); - info["margin_free"] = AccountInfoDouble(ACCOUNT_MARGIN_FREE); - - string t=info.Serialize(); - if(debug) Print(t); - InformClientSocket(dataSocket,t); -} +void GetBalanceInfo() + { + + CJAVal info; + info["balance"] = AccountInfoDouble(ACCOUNT_BALANCE); + info["equity"] = AccountInfoDouble(ACCOUNT_EQUITY); + info["margin"] = AccountInfoDouble(ACCOUNT_MARGIN); + info["margin_free"] = AccountInfoDouble(ACCOUNT_MARGIN_FREE); + + string t=info.Serialize(); + if(debug) + Print(t); + InformClientSocket(dataSocket,t); + } //+------------------------------------------------------------------+ //| Push historical data to ZMQ socket | //+------------------------------------------------------------------+ -bool PushHistoricalData(CJAVal &data){ - string t=data.Serialize(); - if(debug) Print(t); - InformClientSocket(dataSocket,t); - return true; -} +bool PushHistoricalData(CJAVal &data) + { + string t=data.Serialize(); + if(debug) + Print(t); + InformClientSocket(dataSocket,t); + return true; + } +/* +//+------------------------------------------------------------------+ +//| Correct historical tick data | +//+------------------------------------------------------------------+ +// Some brokers (markets.com) deliver incorrect historical tick data +// with an incorrect spread. +// This attempts to automatically adjust the +// historical tick data. +// Live bar data is also represented with the same, incorrect spread so we attempt +// to adjust historical tick data by that same amount. +void CorrectTicks(string symbol, MqlTick ©TicksArray[]) + { + MqlTick symbolInfoTick; + double offsetBid, offsetAsk; + int tickCount = ArraySize(copyTicksArray); + SymbolInfoTick(symbol,symbolInfoTick); + + offsetBid = copyTicksArray[tickCount-1].bid - symbolInfoTick.bid; + offsetAsk = copyTicksArray[tickCount-1].ask - symbolInfoTick.ask; + + for(int i=0; i0) { - tradeInfo.Ticket(ticket); - data["ticket"]=(long) tradeInfo.Ticket(); - data["time"]=(long) tradeInfo.Time(); - data["price"]=(double) tradeInfo.Price(); - data["volume"]=(double) tradeInfo.Volume(); - data["symbol"]=(string) tradeInfo.Symbol(); - data["type"]=(string) tradeInfo.TypeDescription(); - data["entry"]=(long) tradeInfo.Entry(); - data["profit"]=(double) tradeInfo.Profit(); - - trades["trades"].Add(data); + tickCount=CopyTicksRange(symbol,tickArray,COPY_TICKS_ALL,1000*(ulong)fromDateM,1000*(ulong)toDateM); + if(tickCount < 0) + { + mControl.mSetUserError(65541, GetErrorID(65541)); } - } - } - else {trades["trades"].Add(data);} - - string t=trades.Serialize(); - if(debug) Print(t); - InformClientSocket(dataSocket,t); - } - else { - mControl.mSetUserError(65538, GetErrorID(65538)); - CheckError(__FUNCTION__); - } -} + CheckError(__FUNCTION__); + Print("Preparing data of ", tickCount, " ticks for ", symbol); + //if(correctTickHistory) + // CorrectTicks(symbol,tickArray); + + int file_handle=FileOpen(outputFile, FILE_WRITE | FILE_CSV); + if(file_handle!=INVALID_HANDLE) + { + msg["status"] = (string) "CONNECTED"; + msg["type"] = (string) "NORMAL"; + msg["data"] = (string) StringFormat("Writing to: %s\\%s", TerminalInfoString(TERMINAL_DATA_PATH), outputFile); + if(liveStream) + InformClientSocket(liveSocket, msg.Serialize()); + ActionDoneOrError(ERR_SUCCESS, __FUNCTION__, "ERR_SUCCESS"); + //ActionDoneOrError(ERR_SUCCESS , __FUNCTION__, dataSocket); + // Inform client that file is avalable for writing + + PrintFormat("%s file is available for writing",fileName); + PrintFormat("File path: %s\\Files\\",TerminalInfoString(TERMINAL_DATA_PATH)); + //--- write the time and values of signals to the file + for(int i=0; i0) + { + tradeInfo.Ticket(ticket); + data["ticket"]=(long) tradeInfo.Ticket(); + data["time"]=(long) tradeInfo.Time(); + data["price"]=(double) tradeInfo.Price(); + data["volume"]=(double) tradeInfo.Volume(); + data["symbol"]=(string) tradeInfo.Symbol(); + data["type"]=(string) tradeInfo.TypeDescription(); + data["entry"]=(long) tradeInfo.Entry(); + data["profit"]=(double) tradeInfo.Profit(); + + trades["trades"].Add(data); + } + } + } + else + { + trades["trades"].Add(data); + } + + string t=trades.Serialize(); + if(debug) + Print(t); + InformClientSocket(dataSocket,t); + } + else + { + mControl.mSetUserError(65538, GetErrorID(65538)); + CheckError(__FUNCTION__); + } + } +*/ //+------------------------------------------------------------------+ //| Fetch positions information | //+------------------------------------------------------------------+ -void GetPositions(CJAVal &dataObject){ - CPositionInfo myposition; - CJAVal data, position; +void GetPositions(CJAVal &dataObject) + { + CPositionInfo myposition; + CJAVal data, position; - // Get positions - int positionsTotal=PositionsTotal(); - // Create empty array if no positions - if(!positionsTotal) data["positions"].Add(position); - // Go through positions in a loop - for(int i=0;i0) + { + tradeInfo.Ticket(ticket); + data["ticket"]=(long) tradeInfo.Ticket(); + data["time"]=(long) tradeInfo.Time(); + data["price"]=(double) tradeInfo.Price(); + data["volume"]=(double) tradeInfo.Volume(); + data["symbol"]=(string) tradeInfo.Symbol(); + data["type"]=(string) tradeInfo.TypeDescription(); + data["entry"]=(long) tradeInfo.Entry(); + data["profit"]=(double) tradeInfo.Profit(); + + trades["trades"].Add(data); + } + } + } + else + { + trades["trades"].Add(data); + } + + string t=trades.Serialize(); + if(debug) + Print(t); + InformClientSocket(dataSocket,t); + } + else + { + mControl.mSetUserError(65538, GetErrorID(65538)); + CheckError(__FUNCTION__); + } + } +//+------------------------------------------------------------------+ diff --git a/Include/MQL5-JSON_API/StartIndicator.mqh b/Include/MQL5-JSON_API/StartIndicator.mqh new file mode 100644 index 0000000..c4e50ce --- /dev/null +++ b/Include/MQL5-JSON_API/StartIndicator.mqh @@ -0,0 +1,244 @@ +//+------------------------------------------------------------------+ +//| StartIndicator.mqh | +//| Gunther Schulz | +//| https://github.com/khramkov/MQL5-JSON-API | +//+------------------------------------------------------------------+ +#property copyright "Gunther Schulz" +#property link "https://github.com/khramkov/MQL5-JSON-API" + +#define START_INDICATOR true + +int INDICATOR_DATA_PORT=15559; + +Socket indicatorDataSocket(context,ZMQ_PUSH); + +struct Indicator + { + long id; // Internal id + string indicatorId; // UUID + int indicatorHandle; // Internal id/handle + int indicatorParamCount; // Number of parameters to be passed to the indicator + int indicatorBufferCount; // Numnber of buffers to be returned bythe indicator + }; + +Indicator indicators[]; +int indicatorCount = 0; + +//+------------------------------------------------------------------+ +//| Check if string is a representation of a number | +//+------------------------------------------------------------------+ +bool IsNumberAsString(string str) + { +// MQL5 seems to return true if the values are the same, no matter the data type, in this case comparing str and dbl/int. +// (str "2.1" == double 2.1) will return true. + double dbl = StringToDouble(str); + int integer = StringToInteger(str); +// Compaing to both int and double to cover both cases + if(str==dbl || str==integer) + return true; + else + return false; + } + +//+------------------------------------------------------------------+ +//| Get index of indicator handler array by indicator id string | +//+------------------------------------------------------------------+ +int GetIndicatorIdxByIndicatorId(string indicatorId) + { + for(int i=0; i= 0) + { + if(CopyBuffer(indicators[idx].indicatorHandle, i, fromDate, 1, values) < 0) + { + if(mControl.mGetLastError()) + { + CJAVal message; + int lastError = mControl.mGetLastError(); + string desc = mControl.mGetDesc(); + mControl.Check(); + + message["error"]=(bool) true; + message["lastError"]=(string) lastError; + message["description"]=desc; + message["function"]=(string) __FUNCTION__; + string t=message.Serialize(); + if(debug) + Print(t); + InformClientSocket(indicatorDataSocket,t); + } + } + results[i] = DoubleToString(values[0]); + } + } + + CJAVal message; + message["error"]=(bool) false; + message["id"] = (string) id; + message["data"].Set(results); + + string t=message.Serialize(); + if(debug) + Print(t); + InformClientSocket(indicatorDataSocket,t); + + } +//+------------------------------------------------------------------+