add indicator control

This commit is contained in:
Gunther Schulz
2020-02-23 14:03:25 +01:00
parent 1bad67048f
commit 820329307f
+199 -50
View File
@@ -1,4 +1,4 @@
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
// //
// Copyright (C) 2019 Nikolai Khramkov // Copyright (C) 2019 Nikolai Khramkov
// //
@@ -30,7 +30,9 @@
#include <Trade/Trade.mqh> #include <Trade/Trade.mqh>
#include <Zmq/Zmq.mqh> #include <Zmq/Zmq.mqh>
#include <Json.mqh> #include <Json.mqh>
#include <ChartObjects\ChartObject.mqh>
// Set ports and host for ZeroMQ
string HOST="*"; string HOST="*";
int SYS_PORT=15555; int SYS_PORT=15555;
int DATA_PORT=15556; int DATA_PORT=15556;
@@ -51,13 +53,18 @@ bool debug = false;
bool liveStream = true; bool liveStream = true;
bool connectedFlag= true; bool connectedFlag= true;
int deInitReason = -1; int deInitReason = -1;
// Variables for handling price data stream
string chartSymbols[]; string chartSymbols[];
int chartSymbolCount = 0; int chartSymbolCount = 0;
string chartSymbolSettings[][3]; string chartSymbolSettings[][3];
// Variables for controlling indicators
int indicatorCount = 0; int indicatorCount = 0;
double indicators[]; double indicators[];
string indicatorIds[]; string indicatorIds[];
int indicatorParamCount[];
int indicatorBufferCount[];
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
//| Bind ZMQ sockets to ports | //| Bind ZMQ sockets to ports |
@@ -102,7 +109,7 @@ bool BindSockets(){
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
int OnInit(){ int OnInit(){
/* Bindinig ZMQ ports on init */ /* Bindinig ZMQ ports on init */
Print(GetIndicatorConstantValue("VOLUME_TICK"), " ",VOLUME_TICK);
// Skip reloading of the EA script when the reason to reload is a chart timeframe change // Skip reloading of the EA script when the reason to reload is a chart timeframe change
if (deInitReason != REASON_CHARTCHANGE){ if (deInitReason != REASON_CHARTCHANGE){
@@ -125,9 +132,54 @@ int OnInit(){
return(INIT_FAILED); return(INIT_FAILED);
} }
//testDraw();
return(INIT_SUCCEEDED); return(INIT_SUCCEEDED);
} }
void testDraw() {
// ChartSetSymbolPeriod(ChartID(), Symbol(),PERIOD_M1);
// long chart_id;
// chart_id = ChartOpen("EURUSD",PERIOD_M1);
// Print(chart_id);
long chart_id = 0;
int window = 0;
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);
}
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
//| Expert deinitialization function | //| Expert deinitialization function |
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
@@ -342,7 +394,7 @@ void RequestHandler(ZmqMsg &request){
else if(action=="POSITIONS") GetPositions(message); else if(action=="POSITIONS") GetPositions(message);
else if(action=="ORDERS") GetOrders(message); else if(action=="ORDERS") GetOrders(message);
else if(action=="RESET") ResetSubscriptionsAndIndicators(); else if(action=="RESET") ResetSubscriptionsAndIndicators();
else if(action=="INDICATOR") StartIndicator(message); else if(action=="INDICATOR") IndicatorControl(message);
// Action command error processing // Action command error processing
else ActionDoneOrError(65538, __FUNCTION__); else ActionDoneOrError(65538, __FUNCTION__);
@@ -352,7 +404,7 @@ void RequestHandler(ZmqMsg &request){
//| Reconfigure the script params | //| Reconfigure the script params |
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
void ScriptConfiguration(CJAVal &dataObject){ void ScriptConfiguration(CJAVal &dataObject){
//testDraw();
string symbol=dataObject["symbol"].ToStr(); string symbol=dataObject["symbol"].ToStr();
string chartTF=dataObject["chartTF"].ToStr(); string chartTF=dataObject["chartTF"].ToStr();
string actionType=dataObject["actionType"].ToStr(); string actionType=dataObject["actionType"].ToStr();
@@ -377,6 +429,22 @@ void ScriptConfiguration(CJAVal &dataObject){
} }
//+------------------------------------------------------------------+
//| Start new indicator or request indicator data |
//+------------------------------------------------------------------+
void IndicatorControl(CJAVal &dataObject){
string actionType=dataObject["actionType"].ToStr();
if(actionType=="REQUEST") {
GetIndicatorResult(dataObject);
}
else if(actionType=="START") {
StartIndicator(dataObject);
}
}
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
//| Start new indicator instance | //| Start new indicator instance |
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
@@ -385,106 +453,128 @@ void StartIndicator(CJAVal &dataObject){
string symbol=dataObject["symbol"].ToStr(); string symbol=dataObject["symbol"].ToStr();
string chartTF=dataObject["chartTF"].ToStr(); string chartTF=dataObject["chartTF"].ToStr();
string id=dataObject["id"].ToStr(); string id=dataObject["id"].ToStr();
string indicatorName=dataObject["indicatorName"].ToStr(); string indicatorName=dataObject["name"].ToStr();
indicatorCount++; indicatorCount++;
ArrayResize(indicators,indicatorCount); ArrayResize(indicators,indicatorCount);
ArrayResize(indicatorIds,indicatorCount); ArrayResize(indicatorIds,indicatorCount);
ArrayResize(indicatorParamCount,indicatorCount);
ArrayResize(indicatorBufferCount,indicatorCount);
int idx = indicatorCount-1; int idx = indicatorCount-1;
indicatorIds[idx] = id; indicatorIds[idx] = id;
indicatorBufferCount[idx] = dataObject["linecount"].ToInt();
double params[]; double params[];
int paramsCount = dataObject["indicatorParams"].Size(); indicatorParamCount[idx] = dataObject["params"].Size();
for(int i=0;i<paramsCount;i++){ for(int i=0;i<indicatorParamCount[idx];i++){
ArrayResize(params, i+1); ArrayResize(params, i+1);
params[i] = dataObject["indicatorParams"][i].ToDbl(); params[i] = dataObject["params"][i].ToDbl();
} }
ENUM_TIMEFRAMES period = GetTimeframe(chartTF);
// Case construct for passing variable parameter count to the iCustom function is used, because MQL5 does not seem to support expanding an array to a function parameter list // Case construct for passing variable parameter count to the iCustom function is used, because MQL5 does not seem to support expanding an array to a function parameter list
switch(paramsCount) switch(indicatorParamCount[idx])
{ {
case 0: case 0:
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName); indicators[idx] = iCustom(symbol,period,indicatorName);
break; break;
case 1: case 1:
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[0]); indicators[idx] = iCustom(symbol,period,indicatorName, params[0]);
break; break;
case 2: case 2:
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[1], params[2]); indicators[idx] = iCustom(symbol,period,indicatorName, params[0], params[1]);
break; break;
case 3: case 3:
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[1], params[2], params[3]); indicators[idx] = iCustom(symbol,period,indicatorName, params[0], params[1], params[2]);
break; break;
case 4: case 4:
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[1], params[2], params[3], params[4]); indicators[idx] = iCustom(symbol,period,indicatorName, params[0], params[1], params[2], params[3]);
break; break;
case 5: case 5:
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[1], params[2], params[3], params[4], params[5]); indicators[idx] = iCustom(symbol,period,indicatorName, params[0], params[1], params[2], params[3], params[4]);
break; break;
case 6: case 6:
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[1], params[2], params[3], params[4], params[5], params[6]); indicators[idx] = iCustom(symbol,period,indicatorName, params[0], params[1], params[2], params[3], params[4], params[5]);
break; break;
case 7: case 7:
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[1], params[2], params[3], params[4], params[5], params[6], params[7]); indicators[idx] = iCustom(symbol,period,indicatorName, params[0], params[1], params[2], params[3], params[4], params[5], params[6]);
break; break;
case 8: case 8:
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8]); indicators[idx] = iCustom(symbol,period,indicatorName, params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7]);
break; break;
case 9: case 9:
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8], params[9]); indicators[idx] = iCustom(symbol,period,indicatorName, params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8]);
break; break;
case 10: case 10:
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8], params[9], params[10]); indicators[idx] = iCustom(symbol,period,indicatorName, params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8], params[9]);
break; break;
default: default:
// TODO error handling // TODO error handling
break; break;
} }
GetIndicatorResult(dataObject);
CJAVal message;
message["id"] = (string) id;
string t=message.Serialize();
if(debug) Print(t);
InformClientSocket(indicatorDataSocket,t);
// TODO more error handling // TODO more error handling
if(SymbolInfoInteger(symbol, SYMBOL_EXIST)){ //if(SymbolInfoInteger(symbol, SYMBOL_EXIST)){
ActionDoneOrError(ERR_SUCCESS, __FUNCTION__); // ActionDoneOrError(ERR_SUCCESS, __FUNCTION__);
} //}
else ActionDoneOrError(ERR_MARKET_UNKNOWN_SYMBOL, __FUNCTION__); //else ActionDoneOrError(ERR_MARKET_UNKNOWN_SYMBOL, __FUNCTION__);
} }
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
//| Get indicator results | //| Get indicator results |
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
void GetIndicatorResult(CJAVal &dataObject) { void GetIndicatorResult(CJAVal &dataObject) {
datetime fromDate=StringToTime(dataObject["fromDate"].ToStr()); // TODO map Indicators Constants https://www.mql5.com/en/docs/constants/indicatorconstants
datetime fromDate=dataObject["fromDate"].ToInt();
string id=dataObject["id"].ToStr(); string id=dataObject["id"].ToStr();
string indicatorName=dataObject["indicatorName"].ToStr(); string indicatorName=dataObject["indicatorName"].ToStr();
int idx = GetIndicatorIdxByIndicatorId(id); int idx = GetIndicatorIdxByIndicatorId(id);
double values[10]; double values[2];
CJAVal results[10]; ArrayResize(values, indicatorBufferCount[idx]);
CJAVal results;
for(int i=0;i<10;i++){ // Cycle through all avaliable buffer positions
values[i] = 0.0; for(int i=0;i<indicatorBufferCount[idx];i++){
results[i] = 0.0; values[0] = 0.0;
if(idx >= 0) { values[1] = 0.0;
if(CopyBuffer(indicators[idx], i, fromDate, 1, values) < 0) values[0] = 0.0; results[i] = 0.0;
results[i] = DoubleToString(values[0]); if(idx >= 0) {
} if(CopyBuffer(indicators[idx], i, fromDate, 1, values) < 0) {/* Error handling */}
else { results[i] = DoubleToString(values[0]);
// TODO error handling }
} else {
// TODO error handling
} }
if (liveStream) {
CJAVal data;
data["id"] = (string) id;
data["data"].Set(results);
string t=data.Serialize();
if(debug) Print(t);
InformClientSocket(indicatorDataSocket,t);
} }
CJAVal message;
message["id"] = (string) id;
message["data"].Set(results);
string t=message.Serialize();
if(debug) Print(t);
InformClientSocket(indicatorDataSocket,t);
// TODO more error handling
//if(SymbolInfoInteger(symbol, SYMBOL_EXIST)){
// ActionDoneOrError(ERR_SUCCESS, __FUNCTION__);
//}
//else ActionDoneOrError(ERR_MARKET_UNKNOWN_SYMBOL, __FUNCTION__);
} }
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
@@ -1078,6 +1168,65 @@ ENUM_TIMEFRAMES GetTimeframe(string chartTF){
return(tf); return(tf);
} }
//+------------------------------------------------------------------+
//| Convert indicator constants from string to int |
//+------------------------------------------------------------------+
int GetIndicatorConstantValue(string indicatorConstantString){
int r = -1;
ENUM_APPLIED_PRICE ap;
r = StringToEnum(indicatorConstantString,ap);
if(r>=0)return r;
ENUM_APPLIED_VOLUME av;
r = StringToEnum(indicatorConstantString,av);
if(r>=0)return r;
ENUM_STO_PRICE sp;
r = StringToEnum(indicatorConstantString,sp);
if(r>=0)return r;
ENUM_MA_METHOD mm;
r = StringToEnum(indicatorConstantString,mm);
if(r>=0)return r;
return(-1);
}
#define MIN_ENUM_VALUES 0
#define MAX_ENUM_VALUES 255
//+------------------------------------------------------------------+
//| StringToEnum : Convert a string to an ENUM value, |
//| it loop between min(0) and max(255), adjustable if needed. |
//| Non existing enum value defined as -1. If -1 is used as an |
//| enum value, code need to be adjusted to an other default. |
//| Parameters : |
//| in - string to convert |
//| out - ENUM value |
//| @return - int if conversion succeed, false otherwise |
//| |
//| Based on: |
//| https://www.mql5.com/en/forum/61741/page3#comment_5491344 |
//+------------------------------------------------------------------+
template<typename ENUM>
int StringToEnum(string in,ENUM &out)
{
out=-1;
//---
for(int i=MIN_ENUM_VALUES;i<=MAX_ENUM_VALUES;i++)
{
ENUM enumValue=(ENUM)i;
if(in==EnumToString(enumValue))
{
out=enumValue;
break;
}
}
//---
return(out);
}
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+
//| Trade confirmation | //| Trade confirmation |
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+