add indicator control

This commit is contained in:
Gunther Schulz
2020-02-17 14:55:30 +01:00
parent 1bad67048f
commit 820329307f
+204 -55
View File
@@ -1,4 +1,4 @@
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//
// Copyright (C) 2019 Nikolai Khramkov
//
@@ -30,7 +30,9 @@
#include <Trade/Trade.mqh>
#include <Zmq/Zmq.mqh>
#include <Json.mqh>
#include <ChartObjects\ChartObject.mqh>
// Set ports and host for ZeroMQ
string HOST="*";
int SYS_PORT=15555;
int DATA_PORT=15556;
@@ -51,13 +53,18 @@ bool debug = false;
bool liveStream = true;
bool connectedFlag= true;
int deInitReason = -1;
// Variables for handling price data stream
string chartSymbols[];
int chartSymbolCount = 0;
string chartSymbolSettings[][3];
// Variables for controlling indicators
int indicatorCount = 0;
double indicators[];
string indicatorIds[];
int indicatorParamCount[];
int indicatorBufferCount[];
//+------------------------------------------------------------------+
//| Bind ZMQ sockets to ports |
@@ -102,7 +109,7 @@ bool BindSockets(){
//+------------------------------------------------------------------+
int OnInit(){
/* 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
if (deInitReason != REASON_CHARTCHANGE){
@@ -125,9 +132,54 @@ int OnInit(){
return(INIT_FAILED);
}
//testDraw();
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 |
//+------------------------------------------------------------------+
@@ -342,7 +394,7 @@ void RequestHandler(ZmqMsg &request){
else if(action=="POSITIONS") GetPositions(message);
else if(action=="ORDERS") GetOrders(message);
else if(action=="RESET") ResetSubscriptionsAndIndicators();
else if(action=="INDICATOR") StartIndicator(message);
else if(action=="INDICATOR") IndicatorControl(message);
// Action command error processing
else ActionDoneOrError(65538, __FUNCTION__);
@@ -352,7 +404,7 @@ void RequestHandler(ZmqMsg &request){
//| Reconfigure the script params |
//+------------------------------------------------------------------+
void ScriptConfiguration(CJAVal &dataObject){
//testDraw();
string symbol=dataObject["symbol"].ToStr();
string chartTF=dataObject["chartTF"].ToStr();
string actionType=dataObject["actionType"].ToStr();
@@ -377,114 +429,152 @@ 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 |
//+------------------------------------------------------------------+
void StartIndicator(CJAVal &dataObject){
string symbol=dataObject["symbol"].ToStr();
string chartTF=dataObject["chartTF"].ToStr();
string id=dataObject["id"].ToStr();
string indicatorName=dataObject["indicatorName"].ToStr();
string indicatorName=dataObject["name"].ToStr();
indicatorCount++;
indicatorCount++;
ArrayResize(indicators,indicatorCount);
ArrayResize(indicatorIds,indicatorCount);
ArrayResize(indicatorParamCount,indicatorCount);
ArrayResize(indicatorBufferCount,indicatorCount);
int idx = indicatorCount-1;
indicatorIds[idx] = id;
indicatorBufferCount[idx] = dataObject["linecount"].ToInt();
double params[];
int paramsCount = dataObject["indicatorParams"].Size();
for(int i=0;i<paramsCount;i++){
indicatorParamCount[idx] = dataObject["params"].Size();
for(int i=0;i<indicatorParamCount[idx];i++){
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
switch(paramsCount)
switch(indicatorParamCount[idx])
{
case 0:
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName);
indicators[idx] = iCustom(symbol,period,indicatorName);
break;
case 1:
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[0]);
indicators[idx] = iCustom(symbol,period,indicatorName, params[0]);
break;
case 2:
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[1], params[2]);
indicators[idx] = iCustom(symbol,period,indicatorName, params[0], params[1]);
break;
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;
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;
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;
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;
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;
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;
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;
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;
default:
// TODO error handling
break;
}
GetIndicatorResult(dataObject);
// TODO more error handling
if(SymbolInfoInteger(symbol, SYMBOL_EXIST)){
ActionDoneOrError(ERR_SUCCESS, __FUNCTION__);
}
else ActionDoneOrError(ERR_MARKET_UNKNOWN_SYMBOL, __FUNCTION__);
CJAVal message;
message["id"] = (string) id;
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__);
}
//+------------------------------------------------------------------+
//| Get indicator results |
//| Get indicator results |
//+------------------------------------------------------------------+
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 indicatorName=dataObject["indicatorName"].ToStr();
int idx = GetIndicatorIdxByIndicatorId(id);
double values[10];
CJAVal results[10];
for(int i=0;i<10;i++){
values[i] = 0.0;
results[i] = 0.0;
if(idx >= 0) {
if(CopyBuffer(indicators[idx], i, fromDate, 1, values) < 0) values[0] = 0.0;
results[i] = DoubleToString(values[0]);
}
else {
// TODO error handling
}
double values[2];
ArrayResize(values, indicatorBufferCount[idx]);
CJAVal results;
// Cycle through all avaliable buffer positions
for(int i=0;i<indicatorBufferCount[idx];i++){
values[0] = 0.0;
values[1] = 0.0;
results[i] = 0.0;
if(idx >= 0) {
if(CopyBuffer(indicators[idx], i, fromDate, 1, values) < 0) {/* Error handling */}
results[i] = DoubleToString(values[0]);
}
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__);
}
//+------------------------------------------------------------------+
@@ -1077,7 +1167,66 @@ ENUM_TIMEFRAMES GetTimeframe(string chartTF){
else tf=NULL;
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 |
//+------------------------------------------------------------------+