diff --git a/Experts/JsonAPI.ex5 b/Experts/JsonAPI.ex5 deleted file mode 100644 index 36f0178..0000000 Binary files a/Experts/JsonAPI.ex5 and /dev/null differ diff --git a/Experts/JsonAPI.mq5 b/Experts/JsonAPI.mq5 index 4f8f7b2..1d9ebf8 100644 --- a/Experts/JsonAPI.mq5 +++ b/Experts/JsonAPI.mq5 @@ -39,28 +39,21 @@ 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 +// ZeroMQ Connections Context context("MQL5 JSON API"); 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 + +// Load MQL5-JSON-API includes +// Required: +#include +#include +// Optional: +#include +#include // Global variables \\ bool debug = false; @@ -79,44 +72,6 @@ struct SymbolSubscription 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 - }; - -Indicator indicators[]; -int indicatorCount = 0; - -// Variables for controlling chart -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 - }; - -ChartWindowIndicator chartWindowIndicators[]; -int chartWindowIndicatorCount = 0; - -*/ - // Error handling ControlErrors mControl; @@ -259,7 +214,6 @@ int OnInit() return(INIT_FAILED); } -//testDraw(); return(INIT_SUCCEEDED); } @@ -289,10 +243,14 @@ void OnDeinit(const int reason) liveSocket.unbind(StringFormat("tcp://%s:%d", HOST, LIVE_PORT)); Print("Unbinding 'Streaming' socket on port ", STR_PORT, ".."); streamSocket.unbind(StringFormat("tcp://%s:%d", HOST, STR_PORT)); +#ifdef START_INDICATOR + Print("Unbinding 'Indicator Data' socket on port ", INDICATOR_DATA_PORT, ".."); + streamSocket.unbind(StringFormat("tcp://%s:%d", HOST, INDICATOR_DATA_PORT)); +#endif #ifdef CHART_CONTROL - Print("Unbinding 'Chart Data' socket on port ", STR_PORT, ".."); + Print("Unbinding 'Chart Data' socket on port ", CHART_DATA_PORT, ".."); streamSocket.unbind(StringFormat("tcp://%s:%d", HOST, CHART_DATA_PORT)); - Print("Unbinding 'JsonAPIIndicator Data' socket on port ", STR_PORT, ".."); + Print("Unbinding 'JsonAPIIndicator Data' socket on port ", CHART_INDICATOR_DATA_PORT, ".."); streamSocket.unbind(StringFormat("tcp://%s:%d", HOST, CHART_INDICATOR_DATA_PORT)); #endif @@ -321,55 +279,6 @@ bool HasChartSymbol(string symbol, string chartTF) } 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); - - } -*/ - -/* -//+------------------------------------------------------------------+ -//| Open new chart or add indicator to chart | -//+------------------------------------------------------------------+ - -void ChartControl(CJAVal &dataObject) - { - - string actionType=dataObject["actionType"].ToStr(); - - if(actionType=="ADDINDICATOR") - { - AddChartIndicator(dataObject); - } - else - if(actionType=="OPEN") - { - OpenChart(dataObject); - } - } - -//+------------------------------------------------------------------+ -//| Open new chart | -//+------------------------------------------------------------------+ -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; - - 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) - { - - 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; - - 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); - } - } -*/ //+------------------------------------------------------------------+ //| Account information | //+------------------------------------------------------------------+ @@ -952,643 +564,6 @@ bool PushHistoricalData(CJAVal &data) 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); - } - } - } - 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; - -// 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; iprev_calculated){ - B0[0] = EMPTY_VALUE; - B1[0] = EMPTY_VALUE; - B2[0] = EMPTY_VALUE; - B3[0] = EMPTY_VALUE; - B4[0] = EMPTY_VALUE; - B5[0] = EMPTY_VALUE; - B6[0] = EMPTY_VALUE; - B7[0] = EMPTY_VALUE; - B8[0] = EMPTY_VALUE; - B9[0] = EMPTY_VALUE; - B10[0] = EMPTY_VALUE; - B11[0] = EMPTY_VALUE; - B12[0] = EMPTY_VALUE; - B13[0] = EMPTY_VALUE; - B14[0] = EMPTY_VALUE; - B15[0] = EMPTY_VALUE; - B16[0] = EMPTY_VALUE; - B17[0] = EMPTY_VALUE; - B18[0] = EMPTY_VALUE; - B19[0] = EMPTY_VALUE; - } - if(first==false) alive[0] = 1; - // ChartRedraw(0); - +// While a new candle is forming, set the current value to be empty + + + if(rates_total>prev_calculated && setFormingCandleBlank) + { + B0[0] = EMPTY_VALUE; + B1[0] = EMPTY_VALUE; + B2[0] = EMPTY_VALUE; + B3[0] = EMPTY_VALUE; + B4[0] = EMPTY_VALUE; + B5[0] = EMPTY_VALUE; + B6[0] = EMPTY_VALUE; + B7[0] = EMPTY_VALUE; + B8[0] = EMPTY_VALUE; + B9[0] = EMPTY_VALUE; + B10[0] = EMPTY_VALUE; + B11[0] = EMPTY_VALUE; + B12[0] = EMPTY_VALUE; + B13[0] = EMPTY_VALUE; + B14[0] = EMPTY_VALUE; + B15[0] = EMPTY_VALUE; + B16[0] = EMPTY_VALUE; + B17[0] = EMPTY_VALUE; + B18[0] = EMPTY_VALUE; + B19[0] = EMPTY_VALUE; + B20[0] = EMPTY_VALUE; + B21[0] = EMPTY_VALUE; + B22[0] = EMPTY_VALUE; + B23[0] = EMPTY_VALUE; + B24[0] = EMPTY_VALUE; + B25[0] = EMPTY_VALUE; + B26[0] = EMPTY_VALUE; + B27[0] = EMPTY_VALUE; + B28[0] = EMPTY_VALUE; + B29[0] = EMPTY_VALUE; + } + //--- return value of prev_calculated for next call return(rates_total); } -void SubscriptionHandler(ZmqMsg &chartMsg){ - CJAVal message; - // Get data from request - string msg=chartMsg.getData(); - if(debug) Print("Processing:"+msg); - // Deserialize msg to CJAVal array - if(!message.Deserialize(msg)){ - Alert("Deserialization Error"); - ExpertRemove(); - } - if(message["indicatorChartId"]==IndicatorId) { +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +void SubscriptionHandler(ZmqMsg &chartMsg) + { + CJAVal message; +// Get data from request + string msg=chartMsg.getData(); + if(debug) + Print("Processing:"+msg); +// Deserialize msg to CJAVal array + if(!message.Deserialize(msg)) + { + Alert("Deserialization Error"); + ExpertRemove(); + } + if(message["chartIndicatorId"]==IndicatorId) + { - if(message["action"]=="PLOT" && message["actionType"]=="DATA") { - int bufferIdx = message["indicatorBufferId"].ToInt(); - if (bufferIdx == 0) WriteToBuffer(message, B0); - if (bufferIdx == 1) WriteToBuffer(message, B1); - if (bufferIdx == 2) WriteToBuffer(message, B2); - if (bufferIdx == 3) WriteToBuffer(message, B3); - if (bufferIdx == 4) WriteToBuffer(message, B4); - if (bufferIdx == 5) WriteToBuffer(message, B5); - if (bufferIdx == 6) WriteToBuffer(message, B6); - if (bufferIdx == 7) WriteToBuffer(message, B7); - if (bufferIdx == 8) WriteToBuffer(message, B8); - if (bufferIdx == 9) WriteToBuffer(message, B9); - if (bufferIdx == 10) WriteToBuffer(message, B10); - if (bufferIdx == 11) WriteToBuffer(message, B11); - if (bufferIdx == 12) WriteToBuffer(message, B12); - if (bufferIdx == 13) WriteToBuffer(message, B13); - if (bufferIdx == 14) WriteToBuffer(message, B14); - if (bufferIdx == 15) WriteToBuffer(message, B15); - if (bufferIdx == 16) WriteToBuffer(message, B16); - if (bufferIdx == 17) WriteToBuffer(message, B17); - if (bufferIdx == 18) WriteToBuffer(message, B18); - if (bufferIdx == 19) WriteToBuffer(message, B19); - } - else if(message["action"]=="PLOT" && message["actionType"]=="ADDBUFFER") { - string linelabel = message["style"]["linelabel"].ToStr(); - string colorstyleStr = message["style"]["color"].ToStr(); - string linetypeStr = message["style"]["linetype"].ToStr(); - string linestyleStr = message["style"]["linestyle"].ToStr(); - int linewidth = message["style"]["linewidth"].ToInt(); - - color colorstyle = StringToColor(colorstyleStr); - int linetype = StringToEnumInt(linetypeStr); - int linestyle = StringToEnumInt(linestyleStr); - - /* - //if (aa == false) { - Print("SETBUFF ActCount ",activeBufferCount); - if (activeBufferCount == 0) {SetIndexBuffer(0,B1,INDICATOR_DATA);} // Two semicolons ar required! No idea why. Seems to be a timing problem, better to keep it in init() - - if (activeBufferCount == 1) {SetIndexBuffer(1,B2,INDICATOR_DATA);;} - if (activeBufferCount == 2) {SetIndexBuffer(2,B3,INDICATOR_DATA);;} - if (activeBufferCount == 3) {SetIndexBuffer(3,B4,INDICATOR_DATA);;} - if (activeBufferCount == 4) {SetIndexBuffer(4,B5,INDICATOR_DATA);;} + if(message["action"]=="PLOT" && message["actionType"]=="DATA") + { + int bufferIdx = message["indicatorBufferId"].ToInt(); + if(bufferIdx == 0) + { + WriteToBuffer(message, B0); + SetIndexBuffer(0,B0,INDICATOR_DATA); + } + if(bufferIdx == 1) + { + WriteToBuffer(message, B1); + SetIndexBuffer(1,B1,INDICATOR_DATA); + } + if(bufferIdx == 2) + { + WriteToBuffer(message, B2); + SetIndexBuffer(2,B2,INDICATOR_DATA); + } + if(bufferIdx == 3) + { + WriteToBuffer(message, B3); + SetIndexBuffer(3,B3,INDICATOR_DATA); + } + if(bufferIdx == 4) + { + WriteToBuffer(message, B4); + SetIndexBuffer(4,B4,INDICATOR_DATA); + } + if(bufferIdx == 5) + { + WriteToBuffer(message, B5); + SetIndexBuffer(5,B5,INDICATOR_DATA); + } + if(bufferIdx == 6) + { + WriteToBuffer(message, B6); + SetIndexBuffer(6,B6,INDICATOR_DATA); + } + if(bufferIdx == 7) + { + WriteToBuffer(message, B7); + SetIndexBuffer(7,B7,INDICATOR_DATA); + } + if(bufferIdx == 8) + { + WriteToBuffer(message, B8); + SetIndexBuffer(8,B8,INDICATOR_DATA); + } + if(bufferIdx == 9) + { + WriteToBuffer(message, B9); + SetIndexBuffer(9,B9,INDICATOR_DATA); + } + if(bufferIdx == 10) + { + WriteToBuffer(message, B10); + SetIndexBuffer(10,B10,INDICATOR_DATA); + } + if(bufferIdx == 11) + { + WriteToBuffer(message, B11); + SetIndexBuffer(11,B11,INDICATOR_DATA); + } + if(bufferIdx == 12) + { + WriteToBuffer(message, B12); + SetIndexBuffer(12,B12,INDICATOR_DATA); + } + if(bufferIdx == 13) + { + WriteToBuffer(message, B13); + SetIndexBuffer(13,B13,INDICATOR_DATA); + } + if(bufferIdx == 14) + { + WriteToBuffer(message, B14); + SetIndexBuffer(14,B14,INDICATOR_DATA); + } + if(bufferIdx == 15) + { + WriteToBuffer(message, B15); + SetIndexBuffer(15,B15,INDICATOR_DATA); + } + if(bufferIdx == 16) + { + WriteToBuffer(message, B16); + SetIndexBuffer(16,B16,INDICATOR_DATA); + } + if(bufferIdx == 17) + { + WriteToBuffer(message, B17); + SetIndexBuffer(17,B17,INDICATOR_DATA); + } + if(bufferIdx == 18) + { + WriteToBuffer(message, B18); + SetIndexBuffer(18,B18,INDICATOR_DATA); + } + if(bufferIdx == 19) + { + WriteToBuffer(message, B19); + SetIndexBuffer(19,B19,INDICATOR_DATA); + } + if(bufferIdx == 20) + { + WriteToBuffer(message, B20); + SetIndexBuffer(20,B20,INDICATOR_DATA); + } + if(bufferIdx == 21) + { + WriteToBuffer(message, B21); + SetIndexBuffer(21,B21,INDICATOR_DATA); + } + if(bufferIdx == 22) + { + WriteToBuffer(message, B22); + SetIndexBuffer(22,B22,INDICATOR_DATA); + } + if(bufferIdx == 23) + { + WriteToBuffer(message, B23); + SetIndexBuffer(23,B23,INDICATOR_DATA); + } + if(bufferIdx == 24) + { + WriteToBuffer(message, B24); + SetIndexBuffer(24,B24,INDICATOR_DATA); + } + if(bufferIdx == 25) + { + WriteToBuffer(message, B25); + SetIndexBuffer(25,B25,INDICATOR_DATA); + } + if(bufferIdx == 26) + { + WriteToBuffer(message, B26); + SetIndexBuffer(26,B26,INDICATOR_DATA); + } + if(bufferIdx == 27) + { + WriteToBuffer(message, B27); + SetIndexBuffer(27,B27,INDICATOR_DATA); + } + if(bufferIdx == 28) + { + WriteToBuffer(message, B28); + SetIndexBuffer(28,B28,INDICATOR_DATA); + } + if(bufferIdx == 29) + { + WriteToBuffer(message, B29); + SetIndexBuffer(29,B29,INDICATOR_DATA); + } + ChartRedraw(mtChartId); + } + else + if(message["action"]=="PLOT" && message["actionType"]=="ADDBUFFER") + { + string linelabel = message["style"]["linelabel"].ToStr(); + string colorstyleStr = message["style"]["color"].ToStr(); + string linetypeStr = message["style"]["linetype"].ToStr(); + string linestyleStr = message["style"]["linestyle"].ToStr(); + int linewidth = message["style"]["linewidth"].ToInt(); + setFormingCandleBlank = message["style"]["blankforming"].ToBool(); - //aa = true;} - */ - - SetStyle(activeBufferCount, linelabel, colorstyle, linetype, linestyle, linewidth); - activeBufferCount = activeBufferCount + 1; - } + color colorstyle = StringToColor(colorstyleStr); + int linetype = StringToEnumInt(linetypeStr); + int linestyle = StringToEnumInt(linestyleStr); + + SetStyle(activeBufferCount, linelabel, colorstyle, linetype, linestyle, linewidth); + activeBufferCount = activeBufferCount + 1; + + ClearBuffer(activeBufferCount-1); + } + } + } + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +void Clear(double &buffer[]) + { + int bufferSize = ArraySize(buffer); + for(int i=0; i= EMPTY_VALUE) + val = EMPTY_VALUE; + buffer[i+offset] = val; + } + } } - // Set the most recent plotted value to nothing, as we do not have any data for yet unformed candles - buffer[0] = EMPTY_VALUE; -} //+------------------------------------------------------------------+ //| Check for new indicator data function | //+------------------------------------------------------------------+ -void CheckMessages(){ - // This is a workaround for Timer(). It is needed, because OnTimer() works if the indicator is manually added to a chart, but not with ChartIndicatorAdd() +void CheckMessages() + { +// This is a workaround for Timer(). It is needed, because OnTimer() works if the indicator is manually added to a chart, but not with ChartIndicatorAdd() - ZmqMsg chartMsg; + ZmqMsg chartMsg; - // Recieve chart instructions stream from client via live Chart socket. - chartSubscriptionSocket.recv(chartMsg,true); +// Recieve chart instructions stream from client via live Chart socket. + chartSubscriptionSocket.recv(chartMsg,true); - // Request recieved - if(chartMsg.size()>0){ - // Handle subscription SubscriptionHandler() - SubscriptionHandler(chartMsg); - ChartRedraw(ChartID()); +// Request recieved + if(chartMsg.size()>0) + { + // Handle subscription SubscriptionHandler() + SubscriptionHandler(chartMsg); + ChartRedraw(ChartID()); + } } -} //+------------------------------------------------------------------+ //| OnTimer() workaround function | @@ -293,6 +613,7 @@ void OnChartEvent(const int id, const double &dparam, const string &sparam) { - if(id==CHARTEVENT_CUSTOM+222) CheckMessages(); + if(id==CHARTEVENT_CUSTOM+222) + CheckMessages(); } //+----------------------------------------------------