This commit is contained in:
Gunther Schulz
2020-03-03 12:52:46 +01:00
parent cc0f9b7575
commit 37cb0fe738
3 changed files with 494 additions and 399 deletions
+121 -38
View File
@@ -44,9 +44,9 @@ int SYS_PORT=15555;
int DATA_PORT=15556; int DATA_PORT=15556;
int LIVE_PORT=15557; int LIVE_PORT=15557;
int STR_PORT=15558; int STR_PORT=15558;
int IND_DATA_PORT=15559; int INDICATOR_DATA_PORT=15559;
int CHART_LIVE_PORT=15560; int CHART_DATA_PORT=15560;
int PUB_CHART_LIVE_PORT=15562; int CHART_INDICATOR_PORT=15562;
// ZeroMQ Cnnections // ZeroMQ Cnnections
Context context("MQL5 JSON API"); Context context("MQL5 JSON API");
@@ -55,15 +55,15 @@ Socket dataSocket(context,ZMQ_PUSH);
Socket liveSocket(context,ZMQ_PUSH); Socket liveSocket(context,ZMQ_PUSH);
Socket streamSocket(context,ZMQ_PUSH); Socket streamSocket(context,ZMQ_PUSH);
Socket indicatorDataSocket(context,ZMQ_PUSH); Socket indicatorDataSocket(context,ZMQ_PUSH);
Socket chartLiveSocket(context,ZMQ_PULL); Socket chartDataSocket(context,ZMQ_PULL);
Socket pubChartLiveSocket(context,ZMQ_PUB); Socket chartIndicatorSocket(context,ZMQ_PUB);
// Global variables // Global variables \\
bool debug = false; bool debug = false;
bool liveStream = true; bool liveStream = true;
bool connectedFlag = true; bool connectedFlag = true;
int deInitReason = -1; int deInitReason = -1;
double chartAttached = ChartID(); double chartAttached = ChartID(); // Chart id where the expert is attached to
// Variables for handling price data stream // Variables for handling price data stream
struct SymbolSubscription { struct SymbolSubscription {
@@ -76,29 +76,30 @@ int symbolSubscriptionCount = 0;
// Variables for controlling indicators // Variables for controlling indicators
struct Indicator { struct Indicator {
long id; long id; // Internal id
string indicatorId; string indicatorId; // UUID
int indicatorHandle; int indicatorHandle; // Internal id/handle
int indicatorParamCount; int indicatorParamCount; // Number of parameters to be passed to the indicator
int indicatorBufferCount; int indicatorBufferCount; // Numnber of buffers to be returned bythe indicator
}; };
Indicator indicators[]; Indicator indicators[];
int indicatorCount = 0; int indicatorCount = 0;
// Variables for controlling chart // Variables for controlling chart
struct ChartWindow { struct ChartWindow {
long id; long id; // Internal id
string chartId; string chartId; // UUID
string indicatorId; string indicatorId; // UUID
int indicatorHandle; int indicatorHandle; // Internal id/handle
}; };
ChartWindow chartWindows[]; ChartWindow chartWindows[];
int chartWindowCount = 0; int chartWindowCount = 0;
// Refresh chart windows interval. OnTimer function of indicatore JsonAPIIndicator gets triggered on each interval // Refresh chart window interval for JsonAPIIndicator
int chartWindowTimerInterval = 100; int chartWindowTimerInterval = 100; // Cycles of the globally set EventSetMillisecondTimer interval
int chartWindowTimerCounter = 0; int chartWindowTimerCounter = 0; // Keeps track of the current cycle
// Error handling
ControlErrors mControl; ControlErrors mControl;
//string chartWindowObjects[]; //string chartWindowObjects[];
@@ -119,20 +120,20 @@ bool BindSockets(){
if (result == false) { return result; } else {Print("Bound 'Live' socket on port ", 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)); result = streamSocket.bind(StringFormat("tcp://%s:%d", HOST,STR_PORT));
if (result == false) { return result; } else {Print("Bound 'Streaming' socket on port ", STR_PORT);} if (result == false) { return result; } else {Print("Bound 'Streaming' socket on port ", STR_PORT);}
result = indicatorDataSocket.bind(StringFormat("tcp://%s:%d", HOST,IND_DATA_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 ", IND_DATA_PORT);} if (result == false) { return result; } else {Print("Bound 'Indicator Data' socket on port ", INDICATOR_DATA_PORT);}
result = chartLiveSocket.bind(StringFormat("tcp://%s:%d", HOST,CHART_LIVE_PORT)); result = chartDataSocket.bind(StringFormat("tcp://%s:%d", HOST,CHART_DATA_PORT));
if (result == false) { return result; } else {Print("Bound 'Chart Live' socket on port ", CHART_LIVE_PORT);} if (result == false) { return result; } else {Print("Bound 'Chart Data' socket on port ", CHART_DATA_PORT);}
result = pubChartLiveSocket.bind(StringFormat("tcp://%s:%d", HOST,PUB_CHART_LIVE_PORT)); result = chartIndicatorSocket.bind(StringFormat("tcp://%s:%d", HOST,CHART_INDICATOR_PORT));
if (result == false) { return result; } else {Print("Bound 'PUB Chart Live' socket on port ", PUB_CHART_LIVE_PORT);} if (result == false) { return result; } else {Print("Bound 'JsonAPIIndicator Data' socket on port ", CHART_INDICATOR_PORT);}
sysSocket.setLinger(1000); sysSocket.setLinger(1000);
dataSocket.setLinger(1000); dataSocket.setLinger(1000);
liveSocket.setLinger(1000); liveSocket.setLinger(1000);
streamSocket.setLinger(1000); streamSocket.setLinger(1000);
indicatorDataSocket.setLinger(1000); indicatorDataSocket.setLinger(1000);
chartLiveSocket.setLinger(1000); chartDataSocket.setLinger(1000);
pubChartLiveSocket.setLinger(1000); chartIndicatorSocket.setLinger(1000);
// Number of messages to buffer in RAM. // Number of messages to buffer in RAM.
sysSocket.setSendHighWaterMark(1); sysSocket.setSendHighWaterMark(1);
@@ -140,8 +141,8 @@ bool BindSockets(){
liveSocket.setSendHighWaterMark(1); liveSocket.setSendHighWaterMark(1);
streamSocket.setSendHighWaterMark(50); streamSocket.setSendHighWaterMark(50);
indicatorDataSocket.setSendHighWaterMark(5); indicatorDataSocket.setSendHighWaterMark(5);
chartLiveSocket.setReceiveHighWaterMark(1); // TODO confirm settings chartDataSocket.setReceiveHighWaterMark(1); // TODO confirm settings
pubChartLiveSocket.setReceiveHighWaterMark(1); chartIndicatorSocket.setReceiveHighWaterMark(1);
return result; return result;
} }
@@ -209,10 +210,10 @@ void OnDeinit(const int reason){
liveSocket.unbind(StringFormat("tcp://%s:%d", HOST, LIVE_PORT)); liveSocket.unbind(StringFormat("tcp://%s:%d", HOST, LIVE_PORT));
Print("Unbinding 'Streaming' socket on port ", STR_PORT, ".."); Print("Unbinding 'Streaming' socket on port ", STR_PORT, "..");
streamSocket.unbind(StringFormat("tcp://%s:%d", HOST, STR_PORT)); streamSocket.unbind(StringFormat("tcp://%s:%d", HOST, STR_PORT));
Print("Unbinding 'CHart' socket on port ", STR_PORT, ".."); Print("Unbinding 'Chart Data' socket on port ", STR_PORT, "..");
streamSocket.unbind(StringFormat("tcp://%s:%d", HOST,CHART_LIVE_PORT)); streamSocket.unbind(StringFormat("tcp://%s:%d", HOST, CHART_DATA_PORT));
Print("Unbinding 'pub chart' socket on port ", STR_PORT, ".."); Print("Unbinding 'JsonAPIIndicator Data' socket on port ", STR_PORT, "..");
streamSocket.unbind(StringFormat("tcp://%s:%d", HOST,PUB_CHART_LIVE_PORT)); streamSocket.unbind(StringFormat("tcp://%s:%d", HOST, CHART_INDICATOR_PORT));
// Shutdown ZeroMQ Context // Shutdown ZeroMQ Context
context.shutdown(); context.shutdown();
@@ -374,11 +375,11 @@ void OnTimer(){
// Publish indicator values for the JsonAPIIndicator indicator // Publish indicator values for the JsonAPIIndicator indicator
ZmqMsg chartMsg; ZmqMsg chartMsg;
chartLiveSocket.recv(chartMsg, true); chartDataSocket.recv(chartMsg, true);
if(chartMsg.size()>0){ if(chartMsg.size()>0){
Print(chartMsg.getData()); Print(chartMsg.getData());
pubChartLiveSocket.send(chartMsg,true); chartIndicatorSocket.send(chartMsg,true);
ResetLastError(); //ResetLastError();
} }
// Trigger the indicator JsonAPIIndicator to check for new Messages // Trigger the indicator JsonAPIIndicator to check for new Messages
@@ -674,6 +675,7 @@ void OpenChart(CJAVal &dataObject){
chartWindows[idx].id = ChartOpen(symbol, period); chartWindows[idx].id = ChartOpen(symbol, period);
CJAVal message; CJAVal message;
message["error"]=(bool) false;
message["chartId"] = (string) chartId; message["chartId"] = (string) chartId;
string t=message.Serialize(); string t=message.Serialize();
@@ -682,7 +684,7 @@ void OpenChart(CJAVal &dataObject){
} }
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
//| Add JsonAPIIndicator indicator chart to chart | //| Add JsonAPIIndicator indicator to chart |
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
void AddIndicatorChartToChart(CJAVal &dataObject){ void AddIndicatorChartToChart(CJAVal &dataObject){
@@ -706,6 +708,7 @@ void AddIndicatorChartToChart(CJAVal &dataObject){
} }
if(!CheckError(__FUNCTION__)) { if(!CheckError(__FUNCTION__)) {
CJAVal message; CJAVal message;
message["error"]=(bool) false;
message["chartId"] = (string) chartIdStr; message["chartId"] = (string) chartIdStr;
string t=message.Serialize(); string t=message.Serialize();
@@ -717,7 +720,7 @@ void AddIndicatorChartToChart(CJAVal &dataObject){
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
//| Draw on chart | //| Draw on chart |
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
void ChartDraw(CJAVal &dataObject){ void ChartDrawY(CJAVal &dataObject){
/* /*
Print("drawchart"); Print("drawchart");
@@ -866,6 +869,86 @@ void ChartDrawX(CJAVal &dataObject){
//ChartRedraw(chart_id); //ChartRedraw(chart_id);
} }
//+------------------------------------------------------------------+
//| Draw on chart |
//+------------------------------------------------------------------+
void ChartDraw(CJAVal &dataObject){
// DONT DRAW, if chartid noes not exist any more
string id=dataObject["id"].ToStr();
string graphicsType=dataObject["data"]["graphicstype"].ToStr();
if (graphicsType=="line") {
string objectId=dataObject["data"]["objectId"].ToStr();
datetime fromDate=dataObject["data"]["fromDate"].ToInt();
datetime toDate=dataObject["data"]["toDate"].ToInt();
double fromPrice=dataObject["data"]["fromPrice"].ToDbl();
double toPrice=dataObject["data"]["toPrice"].ToDbl();
/*
double params[];
for(int i=0;i<dataObject["params"].Size();i++){
ArrayResize(params, i+1);
params[i] = dataObject["params"][i].ToDbl();
}
*/
//int paramColor = dataObject["params"]["color"]
int idx = GetChartWindowIdxByChartWindowId(id);
//int thisChartWindowObjectsCount = ArraySize(chartWindowObjects);
//ArrayResize(chartWindowObjects, thisChartWindowObjectsCount+1);
//chartWindowObjects[thisChartWindowObjectsCount] = objectId; // do I need this for deinit/reset? Probably Closing chart is sufficient
long chart_id = chartWindows[idx].id;
int window = 0;
//CChartObject object;
//bool success = ObjectCreate(chart_id,objectId,OBJ_TREND,window,fromDate,fromPrice,toDate,toPrice); // add color param
// ChartRedraw(chart_id);
}
// datetime time1 = 1581891300;
// double price1 = 1.08346;
// datetime time2 = 1581891600;
// double price2 = 1.08354;
//chart_id = ChartOpen("EURUSD",PERIOD_M5);
//Print(chart_id);
/*
bool CChartObjectTrend::Create(long chart_id,string name,int window,
datetime time1,double price1,datetime time2,double price2)
{
bool result=ObjectCreate(chart_id,name,OBJ_TREND,window,time1,price1,time2,price2);
if(result) result&=Attach(chart_id,name,window,2);
//---
return(result);
}
*/
// CChartObject object;
//ObjectCreate(chart_id,"ellipse",OBJ_ELLIPSE,window,time1,price1,time2,price2,time2,price2+0.00005);
//ObjectCreate(chart_id,"ellipse",OBJ_ELLIPSE,window,time1-100,price1,time1,price1+0.00010,time1+200,price1);
//ObjectCreate(chart_id,"trend",OBJ_TREND,window,time1,price1,time2,price2);
// ObjectCreate(chart_id,"reactangle",OBJ_TREND,window,time1,price1+0.00010,time2,price2+0.00020);
//--- attach chart object
/*
if(!object.Attach(ChartID(),"MyObject",0,2))
{
printf("Object attach error");
}
*/
//ChartSetSymbolPeriod(ChartID(), Symbol(),PERIOD_M5);
//ChartRedraw(chart_id);
}
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
//| Account information | //| Account information |
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
+2 -2
View File
@@ -33,8 +33,8 @@ int StringToEnum(string in,ENUM &out)
} }
int StringToEnumInt(string indicatorConstantString, bool debug=1){ int StringToEnumInt(string indicatorConstantString)
{
int r = -1; int r = -1;
ENUM_ACCOUNT_INFO_DOUBLE a1; ENUM_ACCOUNT_INFO_DOUBLE a1;
+20 -8
View File
@@ -8,7 +8,7 @@
#property link "https://www.guntherschulz.de" #property link "https://www.guntherschulz.de"
#property version "1.00" #property version "1.00"
#include <StringToEnumInt.mqh> #include <EnumStringToInt.mqh>
#include <Zmq/Zmq.mqh> #include <Zmq/Zmq.mqh>
#include <Json.mqh> #include <Json.mqh>
@@ -18,7 +18,7 @@ int CHART_SUB_PORT=15562;
// ZeroMQ Cnnections // ZeroMQ Cnnections
Context context("MQL5 JSON API"); Context context("MQL5 JSON API");
Socket chartLiveSocket(context,ZMQ_SUB); Socket chartSubscriptionSocket(context,ZMQ_SUB);
//#property indicator_separate_window //#property indicator_separate_window
//#property indicator_buffers 1 //#property indicator_buffers 1
@@ -52,14 +52,16 @@ bool first = false;
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
int OnInit() int OnInit()
{ {
bool result = chartLiveSocket.connect(StringFormat("tcp://%s:%d", HOST, CHART_SUB_PORT)); bool result = chartSubscriptionSocket.connect(StringFormat("tcp://%s:%d", HOST, CHART_SUB_PORT));
if (result == false) {Print("Failed to subscrbe on port ", CHART_SUB_PORT);} if (result == false) {Print("Failed to subscrbe on port ", CHART_SUB_PORT);}
else { else {
Print("Accepting Chart Indicator data on port ", CHART_SUB_PORT); Print("Accepting Chart Indicator data on port ", CHART_SUB_PORT);
chartLiveSocket.setSubscribe(""); // TODO subscribe only to own IndicatorId topic
chartLiveSocket.setLinger(1000); // Subscribe to all topics
chartSubscriptionSocket.setSubscribe("");
chartSubscriptionSocket.setLinger(1000);
// Number of messages to buffer in RAM. // Number of messages to buffer in RAM.
chartLiveSocket.setReceiveHighWaterMark(5); // TODO confirm settings chartSubscriptionSocket.setReceiveHighWaterMark(5); // TODO confirm settings
} }
//--- indicator buffers mapping; //--- indicator buffers mapping;
@@ -130,6 +132,9 @@ void SubscriptionHandler(ZmqMsg &chartMsg){
if(message["indicatorChartId"]==IndicatorId) WriteToBuffer(message); if(message["indicatorChartId"]==IndicatorId) WriteToBuffer(message);
} }
//+------------------------------------------------------------------+
//| Update indicator buffer function |
//+------------------------------------------------------------------+
void WriteToBuffer(CJAVal &message) { void WriteToBuffer(CJAVal &message) {
int bufferSize = ArraySize(Buffer); int bufferSize = ArraySize(Buffer);
int messageDataSize = message["data"].Size(); int messageDataSize = message["data"].Size();
@@ -172,13 +177,16 @@ dependable redraw after calling timer
*/ */
//+------------------------------------------------------------------+
//| Check for new indicator data function |
//+------------------------------------------------------------------+
void CheckMessages(){ void CheckMessages(){
// Timer() works, when the indicator is manually added to a chart, but not with ChartIndicatorAdd() // This is a workaround for Timer(). It is needed, because Timer() works, when 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. // Recieve chart instructions stream from client via live Chart socket.
chartLiveSocket.recv(chartMsg,true); chartSubscriptionSocket.recv(chartMsg,true);
// Request recived // Request recived
if(chartMsg.size()>0){ if(chartMsg.size()>0){
@@ -189,6 +197,10 @@ void CheckMessages(){
} }
} }
//+------------------------------------------------------------------+
//| OnTimer() workaround function |
//+------------------------------------------------------------------+
// Gets triggered by the OnTimer() function of the JsonAPI Expert script
void OnChartEvent(const int id, void OnChartEvent(const int id,
const long &lparam, const long &lparam,
const double &dparam, const double &dparam,