Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1a0ce7af3a | |||
| 08b83713af | |||
| 775a962d38 |
+1542
-1137
File diff suppressed because it is too large
Load Diff
+191
-147
@@ -40,29 +40,29 @@ bool debug = true;
|
||||
bool first = false;
|
||||
int activeBufferCount = 0;
|
||||
|
||||
int activeBufferCount = 0;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
|
||||
{
|
||||
// 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(1000); // TODO confirm settings
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
chartSubscriptionSocket.setLinger(10000);
|
||||
// Number of messages to buffer in RAM.
|
||||
chartSubscriptionSocket.setReceiveHighWaterMark(5); // TODO confirm settings
|
||||
}
|
||||
|
||||
|
||||
//--- indicator buffers mapping;
|
||||
ArraySetAsSeries(B0,true);
|
||||
ArraySetAsSeries(B1,true);
|
||||
@@ -108,22 +108,26 @@ int OnInit()
|
||||
SetIndexBuffer(19,B19,INDICATOR_DATA);
|
||||
SetIndexBuffer(20,alive,INDICATOR_CALCULATIONS); // If the buffer index changes, the line starting with "CopyBuffer(chartWindowIndicators[i].indicatorHandle," in JsonAPI.mq5 has to be updated
|
||||
|
||||
|
||||
|
||||
//---
|
||||
IndicatorSetString(INDICATOR_SHORTNAME,ShortName);
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
|
||||
void SetStyle(int bufferIdx, string linelabel, color colorstyle, int linetype, int linestyle, int linewidth) {
|
||||
PlotIndexSetString(bufferIdx,PLOT_LABEL,linelabel);
|
||||
PlotIndexSetInteger(bufferIdx,PLOT_LINE_COLOR,0,colorstyle);
|
||||
PlotIndexSetInteger(bufferIdx,PLOT_DRAW_TYPE,linetype);
|
||||
PlotIndexSetInteger(bufferIdx,PLOT_LINE_STYLE,linestyle);
|
||||
PlotIndexSetInteger(bufferIdx,PLOT_LINE_WIDTH,linewidth);
|
||||
}
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void SetStyle(int bufferIdx, string linelabel, color colorstyle, int linetype, int linestyle, int linewidth)
|
||||
{
|
||||
PlotIndexSetString(bufferIdx,PLOT_LABEL,linelabel);
|
||||
PlotIndexSetInteger(bufferIdx,PLOT_LINE_COLOR,0,colorstyle);
|
||||
PlotIndexSetInteger(bufferIdx,PLOT_DRAW_TYPE,linetype);
|
||||
PlotIndexSetInteger(bufferIdx,PLOT_LINE_STYLE,linestyle);
|
||||
PlotIndexSetInteger(bufferIdx,PLOT_LINE_WIDTH,linewidth);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator iteration function |
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -138,151 +142,190 @@ int OnCalculate(const int rates_total,
|
||||
const long &volume[],
|
||||
const int &spread[])
|
||||
{
|
||||
// While a new candle is forming, set the current value to be empty
|
||||
// While a new candle is forming, set the current value to be empty
|
||||
|
||||
if(rates_total>prev_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);
|
||||
|
||||
if(rates_total>prev_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);
|
||||
|
||||
//--- 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["indicatorChartId"]==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);
|
||||
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();
|
||||
|
||||
//aa = true;}
|
||||
*/
|
||||
|
||||
SetStyle(activeBufferCount, linelabel, colorstyle, linetype, linestyle, linewidth);
|
||||
activeBufferCount = activeBufferCount + 1;
|
||||
}
|
||||
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);;}
|
||||
|
||||
//aa = true;}
|
||||
*/
|
||||
|
||||
SetStyle(activeBufferCount, linelabel, colorstyle, linetype, linestyle, linewidth);
|
||||
activeBufferCount = activeBufferCount + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update indicator buffer function |
|
||||
//+------------------------------------------------------------------+
|
||||
void WriteToBuffer(CJAVal &message, double &buffer[]) {
|
||||
|
||||
int bufferSize = ArraySize(buffer);
|
||||
void WriteToBuffer(CJAVal &message, double &buffer[])
|
||||
{
|
||||
|
||||
int messageDataSize = message["data"].Size();
|
||||
// TODO check if this is working as expected. Seems to
|
||||
if(first==false) {
|
||||
for(int i=0;i<activeBufferCount;i++) {
|
||||
//Print("BUFF ",bufferSize-messageDataSize, " ",ArraySize(B2)," ", ArraySize(B3), " ",messageDataSize);
|
||||
PlotIndexSetInteger(i,PLOT_DRAW_BEGIN,bufferSize-messageDataSize);
|
||||
}
|
||||
first = true;
|
||||
}
|
||||
int bufferSize = ArraySize(buffer);
|
||||
|
||||
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[i+1] = message["data"][messageDataSize-1-i].ToDbl();
|
||||
}
|
||||
int messageDataSize = message["data"].Size();
|
||||
// TODO check if this is working as expected. Seems to
|
||||
if(first==false)
|
||||
{
|
||||
for(int i=0; i<activeBufferCount; i++)
|
||||
{
|
||||
//Print("BUFF ",bufferSize-messageDataSize, " ",ArraySize(B2)," ", ArraySize(B3), " ",messageDataSize);
|
||||
PlotIndexSetInteger(i,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[i+1] = message["data"][messageDataSize-1-i].ToDbl();
|
||||
}
|
||||
}
|
||||
// Set the most recent plotted value to nothing, as we do not have any data for yet unformed candles
|
||||
buffer[0] = EMPTY_VALUE;
|
||||
}
|
||||
// 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 +336,7 @@ void OnChartEvent(const int id,
|
||||
const double &dparam,
|
||||
const string &sparam)
|
||||
{
|
||||
if(id==CHARTEVENT_CUSTOM+222) CheckMessages();
|
||||
if(id==CHARTEVENT_CUSTOM+222)
|
||||
CheckMessages();
|
||||
}
|
||||
//+----------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user