cleanup
This commit is contained in:
+121
-38
@@ -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 |
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user