add indicator
control any mt5 indicator
This commit is contained in:
+164
-18
@@ -36,6 +36,7 @@ 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;
|
||||||
|
|
||||||
// ZeroMQ Cnnections
|
// ZeroMQ Cnnections
|
||||||
Context context("MQL5 JSON API");
|
Context context("MQL5 JSON API");
|
||||||
@@ -43,6 +44,7 @@ Socket sysSocket(context,ZMQ_REP);
|
|||||||
Socket dataSocket(context,ZMQ_PUSH);
|
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);
|
||||||
|
|
||||||
// Global variables
|
// Global variables
|
||||||
bool debug = false;
|
bool debug = false;
|
||||||
@@ -53,6 +55,10 @@ string chartSymbols[];
|
|||||||
int chartSymbolCount = 0;
|
int chartSymbolCount = 0;
|
||||||
string chartSymbolSettings[][3];
|
string chartSymbolSettings[][3];
|
||||||
|
|
||||||
|
int indicatorCount = 0;
|
||||||
|
double indicators[];
|
||||||
|
string indicatorIds[];
|
||||||
|
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
//| Bind ZMQ sockets to ports |
|
//| Bind ZMQ sockets to ports |
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
@@ -66,22 +72,27 @@ bool BindSockets(){
|
|||||||
if (result == false) return result;
|
if (result == false) return result;
|
||||||
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;
|
if (result == false) return result;
|
||||||
|
result = indicatorDataSocket.bind(StringFormat("tcp://%s:%d", HOST,IND_DATA_PORT));
|
||||||
|
if (result == false) return result;
|
||||||
|
|
||||||
Print("Bound 'System' socket on port ", SYS_PORT);
|
Print("Bound 'System' socket on port ", SYS_PORT);
|
||||||
Print("Bound 'Data' socket on port ", DATA_PORT);
|
Print("Bound 'Data' socket on port ", DATA_PORT);
|
||||||
Print("Bound 'Live' socket on port ", LIVE_PORT);
|
Print("Bound 'Live' socket on port ", LIVE_PORT);
|
||||||
Print("Bound 'Streaming' socket on port ", STR_PORT);
|
Print("Bound 'Streaming' socket on port ", STR_PORT);
|
||||||
|
Print("Bound 'Indicator Data' socket on port ", IND_DATA_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);
|
||||||
|
|
||||||
// Number of messages to buffer in RAM.
|
// Number of messages to buffer in RAM.
|
||||||
sysSocket.setSendHighWaterMark(1);
|
sysSocket.setSendHighWaterMark(1);
|
||||||
dataSocket.setSendHighWaterMark(5);
|
dataSocket.setSendHighWaterMark(5);
|
||||||
liveSocket.setSendHighWaterMark(1);
|
liveSocket.setSendHighWaterMark(1);
|
||||||
streamSocket.setSendHighWaterMark(50);
|
streamSocket.setSendHighWaterMark(50);
|
||||||
|
indicatorDataSocket.setSendHighWaterMark(5);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -159,17 +170,31 @@ void OnTick(){
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
//| Check if subscribed to symbol and timeframe combination |
|
//| Check if subscribed to symbol and timeframe combination |
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
bool hasChartSymbol(string symbol, string chartTF)
|
bool HasChartSymbol(string symbol, string chartTF)
|
||||||
{
|
{
|
||||||
for(int i=0;i<ArraySize(chartSymbols);i++)
|
for(int i=0;i<ArraySize(chartSymbols);i++)
|
||||||
{
|
{
|
||||||
if(chartSymbolSettings[i][0] == symbol && chartSymbolSettings[i][1] == chartTF ){
|
if(chartSymbolSettings[i][0] == symbol && chartSymbolSettings[i][1] == chartTF){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Get index of indicator handler array by indicator id string |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
int GetIndicatorIdxByIndicatorId(string indicatorId)
|
||||||
|
{
|
||||||
|
for(int i=0;i<indicatorCount;i++)
|
||||||
|
{
|
||||||
|
if(indicatorIds[i] == indicatorId){
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
//| Stream live price data |
|
//| Stream live price data |
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
@@ -264,6 +289,7 @@ void OnTimer(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
//| ChartEvent function |
|
//| ChartEvent function |
|
||||||
//| This function must be declared, even if it empty. |
|
//| This function must be declared, even if it empty. |
|
||||||
@@ -277,6 +303,7 @@ void OnChartEvent(const int id, // event id
|
|||||||
{
|
{
|
||||||
//--- Add your code here...
|
//--- Add your code here...
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
//| Request handler |
|
//| Request handler |
|
||||||
@@ -304,14 +331,15 @@ void RequestHandler(ZmqMsg &request){
|
|||||||
// Process action command
|
// Process action command
|
||||||
string action = message["action"].ToStr();
|
string action = message["action"].ToStr();
|
||||||
|
|
||||||
if(action=="CONFIG") {ScriptConfiguration(message);}
|
if(action=="CONFIG") ScriptConfiguration(message);
|
||||||
else if(action=="ACCOUNT") {GetAccountInfo();}
|
else if(action=="ACCOUNT") GetAccountInfo();
|
||||||
else if(action=="BALANCE") {GetBalanceInfo();}
|
else if(action=="BALANCE") GetBalanceInfo();
|
||||||
else if(action=="HISTORY") {HistoryInfo(message);}
|
else if(action=="HISTORY") HistoryInfo(message);
|
||||||
else if(action=="TRADE") {TradingModule(message);}
|
else if(action=="TRADE") TradingModule(message);
|
||||||
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") {ResetSubscriptions(message);}
|
else if(action=="RESET") ResetSubscriptionsAndIndicators();
|
||||||
|
else if(action=="INDICATOR") StartIndicator(message);
|
||||||
// Action command error processing
|
// Action command error processing
|
||||||
else ActionDoneOrError(65538, __FUNCTION__);
|
else ActionDoneOrError(65538, __FUNCTION__);
|
||||||
|
|
||||||
@@ -329,7 +357,7 @@ void ScriptConfiguration(CJAVal &dataObject){
|
|||||||
string symbArr[1];
|
string symbArr[1];
|
||||||
symbArr[0]= symbol;
|
symbArr[0]= symbol;
|
||||||
|
|
||||||
if (!hasChartSymbol(symbol, chartTF)) {
|
if (!HasChartSymbol(symbol, chartTF)) {
|
||||||
ArrayInsert(chartSymbols,symbArr,0);
|
ArrayInsert(chartSymbols,symbArr,0);
|
||||||
ArrayResize(chartSymbolSettings,chartSymbolCount+1);
|
ArrayResize(chartSymbolSettings,chartSymbolCount+1);
|
||||||
chartSymbolSettings[chartSymbolCount][0]=symbol;
|
chartSymbolSettings[chartSymbolCount][0]=symbol;
|
||||||
@@ -346,6 +374,116 @@ void ScriptConfiguration(CJAVal &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();
|
||||||
|
|
||||||
|
indicatorCount++;
|
||||||
|
ArrayResize(indicators,indicatorCount);
|
||||||
|
ArrayResize(indicatorIds,indicatorCount);
|
||||||
|
int idx = indicatorCount-1;
|
||||||
|
indicatorIds[idx] = id;
|
||||||
|
|
||||||
|
double params[];
|
||||||
|
int paramsCount = dataObject["indicatorParams"].Size();
|
||||||
|
for(int i=0;i<paramsCount;i++){
|
||||||
|
ArrayResize(params, i+1);
|
||||||
|
params[i] = dataObject["indicatorParams"][i].ToDbl();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[0]);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[1], params[2]);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[1], params[2], params[3]);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[1], params[2], params[3], params[4]);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[1], params[2], params[3], params[4], params[5]);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[1], params[2], params[3], params[4], params[5], params[6]);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
indicators[idx] = iCustom(symbol,GetTimeframe(chartTF),indicatorName, params[1], params[2], params[3], params[4], params[5], params[6], params[7]);
|
||||||
|
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]);
|
||||||
|
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]);
|
||||||
|
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]);
|
||||||
|
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__);
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Get indicator results |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
void GetIndicatorResult(CJAVal &dataObject) {
|
||||||
|
|
||||||
|
datetime fromDate=StringToTime(dataObject["fromDate"].ToStr());
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (liveStream) {
|
||||||
|
CJAVal data;
|
||||||
|
data["id"] = (string) id;
|
||||||
|
data["data"].Set(results);
|
||||||
|
|
||||||
|
string t=data.Serialize();
|
||||||
|
if(debug) Print(t);
|
||||||
|
InformClientSocket(indicatorDataSocket,t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
//| Account information |
|
//| Account information |
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
@@ -709,18 +847,26 @@ void GetOrders(CJAVal &dataObject){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
//| Clear symbol subscriptions |
|
//| Clear symbol subscriptions and indicators |
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
|
|
||||||
void ResetSubscriptions(CJAVal &dataObject){
|
void ResetSubscriptionsAndIndicators(){
|
||||||
|
|
||||||
ArrayFree(chartSymbols);
|
ArrayFree(chartSymbols);
|
||||||
chartSymbolCount=0;
|
|
||||||
ArrayFree(chartSymbolSettings);
|
ArrayFree(chartSymbolSettings);
|
||||||
|
chartSymbolCount=0;
|
||||||
|
|
||||||
if(ArraySize(chartSymbols)!=0 ||ArraySize(chartSymbolSettings)!=0){
|
bool error = false;
|
||||||
|
for(int i=0;i<chartSymbolCount;i++){
|
||||||
|
if(!IndicatorRelease(indicators[i])) error = true;
|
||||||
|
}
|
||||||
|
ArrayFree(indicators);
|
||||||
|
ArrayFree(indicatorIds);
|
||||||
|
indicatorCount = 0;
|
||||||
|
|
||||||
|
if(ArraySize(chartSymbols)!=0 || ArraySize(chartSymbolSettings)!=0 || ArraySize(indicators)!=0 || ArraySize(indicatorIds)!=0 || error){
|
||||||
// TODO Implement propery error codes and descriptions
|
// TODO Implement propery error codes and descriptions
|
||||||
ActionDoneOrError(65540, __FUNCTION__);
|
ActionDoneOrError(GetLastError(), __FUNCTION__);
|
||||||
}
|
}
|
||||||
else ActionDoneOrError(ERR_SUCCESS, __FUNCTION__);
|
else ActionDoneOrError(ERR_SUCCESS, __FUNCTION__);
|
||||||
}
|
}
|
||||||
@@ -1045,7 +1191,7 @@ string GetErrorID(int error){
|
|||||||
case 65537: return("ERR_DESERIALIZATION"); break;
|
case 65537: return("ERR_DESERIALIZATION"); break;
|
||||||
case 65538: return("ERR_WRONG_ACTION"); break;
|
case 65538: return("ERR_WRONG_ACTION"); break;
|
||||||
case 65539: return("ERR_WRONG_ACTION_TYPE"); break;
|
case 65539: return("ERR_WRONG_ACTION_TYPE"); break;
|
||||||
case 65540: return("ERR_CLEAR_SUBSCRIPTIONS_FAILED"); break;
|
//case 65540: return("ERR_CLEAR_SUBSCRIPTIONS_FAILED"); break;
|
||||||
case 65541: return("ERR_RETRIEVE_DATA_FAILED"); break;
|
case 65541: return("ERR_RETRIEVE_DATA_FAILED"); break;
|
||||||
case 65542: return("ERR_CFILE_CREATION_FAILED"); break;
|
case 65542: return("ERR_CFILE_CREATION_FAILED"); break;
|
||||||
|
|
||||||
@@ -1083,4 +1229,4 @@ string getUninitReasonText(int reasonCode)
|
|||||||
}
|
}
|
||||||
//---
|
//---
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user