Files
MQL5-JSON-API-2/Indicators/JsonAPIIndicator.mq5
T
Gunther Schulz 99ea77ebfe cleanup
2020-04-30 10:49:01 +02:00

167 lines
5.9 KiB
Plaintext

//+------------------------------------------------------------------+
//| JsonAPIIndicator.mq5 |
//| Copyright 2020, Gunther Schulz |
//| https://www.guntherschulz.de |
//+------------------------------------------------------------------+
#property copyright "2020 Gunther Schulz"
#property link "https://www.guntherschulz.de"
#property version "1.00"
#include <EnumStringToInt.mqh>
#include <Zmq/Zmq.mqh>
#include <Json.mqh>
// Set ports and host for ZeroMQ
string HOST="localhost";
int CHART_SUB_PORT=15562;
// ZeroMQ Cnnections
Context context("MQL5 JSON API");
Socket chartSubscriptionSocket(context,ZMQ_SUB);
//--- input parameters
input string IndicatorId="";
input string ShortName="JsonAPI";
input string ColorSyle = "clrRed";
input string LineType = "DRAW_LINE";
input string LineStyle = "STYLE_SOLID";
input int LineWidth = 1;
//--- indicator settings
double Buffer[];
bool debug = false;
bool first = false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
bool result = chartSubscriptionSocket.connect(StringFormat("tcp://%s:%d", HOST, CHART_SUB_PORT));
if (result == false) {Print("Failed to subscrbe on port ", CHART_SUB_PORT);}
else {
Print("Accepting Chart Indicator data on port ", CHART_SUB_PORT);
// TODO subscribe only to own IndicatorId topic
// Subscribe to all topics
chartSubscriptionSocket.setSubscribe("");
chartSubscriptionSocket.setLinger(1000);
// Number of messages to buffer in RAM.
chartSubscriptionSocket.setReceiveHighWaterMark(5); // TODO confirm settings
}
//--- indicator buffers mapping;
ArraySetAsSeries(Buffer,true);
SetIndexBuffer(0,Buffer,INDICATOR_DATA);
color colorstyle = StringToColor(ColorSyle);
int linetype = StringToEnumInt(LineType);
int linestyle = StringToEnumInt(LineStyle);
SetStyle(ShortName, colorstyle, linetype, linestyle, LineWidth);
//---
return(INIT_SUCCEEDED);
}
void SetStyle(string shortname, color colorstyle, int linetype, int linestyle, int linewidth) {
IndicatorSetString(INDICATOR_SHORTNAME,shortname);
PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,colorstyle);
PlotIndexSetInteger(0,PLOT_DRAW_TYPE,linetype);
PlotIndexSetInteger(0,PLOT_LINE_STYLE,linestyle);
PlotIndexSetInteger(0,PLOT_LINE_WIDTH,linewidth);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
// While a new candle is forming, set the current value to the previous value
if(rates_total>prev_calculated){
Buffer[0] = EMPTY_VALUE;
}
//--- return value of prev_calculated for next call
return(rates_total);
}
void SubscriptionHandler(ZmqMsg &chartMsg){
CJAVal message;
// Get data from reguest
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) WriteToBuffer(message);
}
//+------------------------------------------------------------------+
//| Update indicator buffer function |
//+------------------------------------------------------------------+
void WriteToBuffer(CJAVal &message) {
int bufferSize = ArraySize(Buffer);
int messageDataSize = message["data"].Size();
if(first==false) {
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,bufferSize-messageDataSize);
first = true;
}
for(int i=0;i<messageDataSize;i++){
// don't add more elements than the automatically sized buffer array can hold
if(i+1<bufferSize){
// the first element is the current unformed candle, so we start at index 1
// we reverse the order of the incoming values, which are expected to be ascending
Buffer[i+1] = message["data"][messageDataSize-1-i].ToDbl();
}
}
Buffer[0] = EMPTY_VALUE;
}
//+------------------------------------------------------------------+
//| Check for new indicator data function |
//+------------------------------------------------------------------+
void CheckMessages(){
// 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;
// Recieve chart instructions stream from client via live Chart socket.
chartSubscriptionSocket.recv(chartMsg,true);
// Request recived
if(chartMsg.size()>0){
// Handle subscription SubscriptionHandler().
Print(chartMsg.getData());
SubscriptionHandler(chartMsg);
ChartRedraw(ChartID());
}
}
//+------------------------------------------------------------------+
//| OnTimer() workaround function |
//+------------------------------------------------------------------+
// Gets triggered by the OnTimer() function of the JsonAPI Expert script
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
if(id==CHARTEVENT_CUSTOM+222) CheckMessages();
}
//+----------------------------------------------------