475 lines
16 KiB
MQL5
475 lines
16 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| Main.mqh |
|
|
//| Copyright 2026, Niquel Mendoza. |
|
|
//| https://www.mql5.com/ |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2026, Niquel Mendoza."
|
|
#property link "https://www.mql5.com/"
|
|
#property strict
|
|
|
|
#ifndef FULLMT5MCPBYLEO_SRC_IND_MAIN_MQH
|
|
#define FULLMT5MCPBYLEO_SRC_IND_MAIN_MQH
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Include |
|
|
//+------------------------------------------------------------------+
|
|
#include "..\\Def\\Def.mqh"
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
namespace TSN
|
|
{
|
|
|
|
#define MCPFUNCIND_MASK_HANDLE (0xFFFFFFFF)
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| indicator_manage |
|
|
//+------------------------------------------------------------------+
|
|
class CMcpFuncInd : public CMcpFunction
|
|
{
|
|
private:
|
|
CHashMapFast(string, long) m_indicators;
|
|
double m_buffer[];
|
|
|
|
public:
|
|
CMcpFuncInd(void) : CMcpFunction(0, false, "indicator_manage") { ArraySetAsSeries(m_buffer, true); }
|
|
~CMcpFuncInd(void)
|
|
{
|
|
long meta[];
|
|
const int t = m_indicators.GetValues(meta, 0);
|
|
for(int i = 0; i < t; i++)
|
|
{
|
|
IndicatorRelease(int(meta[i] & MCPFUNCIND_MASK_HANDLE));
|
|
}
|
|
}
|
|
|
|
//---
|
|
void Run(CJsonNode& param, CJsonBuilderStr* &out) override final;
|
|
};
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CMcpFuncInd::Run(CJsonNode ¶m, CJsonBuilderStr* &out)
|
|
{
|
|
//---
|
|
out = m_shared_builder;
|
|
const ENUM_MCPFUNC_IND_ACTION mode = CEnumRegFullMt5Mcp::GetValNoRef<ENUM_MCPFUNC_IND_ACTION>(param["mode"].ToString(""), WRONG_VALUE);;
|
|
switch(mode)
|
|
{
|
|
case MCPFUNC_IND_ACTION_CREATE:
|
|
{
|
|
const string name = param["indicator_alias_name"].ToString("");
|
|
if(m_indicators.Contains(name))
|
|
{
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(false);
|
|
m_shared_builder.KeyWV("result").ValS(StringFormat("Indicator with alias '%s' is register in dict", name));
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
return;
|
|
}
|
|
|
|
const ENUM_INDICATOR type = CEnumRegBasis::GetValNoRef<ENUM_INDICATOR>(param["ind_type"].ToString(""), WRONG_VALUE);
|
|
const string symbol = param["symbol"].ToString(_Symbol);
|
|
const ENUM_TIMEFRAMES tf = CEnumRegBasis::GetValNoRef<ENUM_TIMEFRAMES>(param["timeframe"].ToString(), _Period);
|
|
|
|
//---
|
|
MqlParam params[];
|
|
CJsonNode parametros = param["params"];
|
|
const int t = parametros.Size();
|
|
ArrayResize(params, t);
|
|
|
|
//---
|
|
if(t > 0)
|
|
{
|
|
CJsonIteratorArray it = parametros.BeginArr();
|
|
int k = 0;
|
|
|
|
//---
|
|
while(it.IsValid())
|
|
{
|
|
CJsonNode parametro = it.Val();
|
|
if(!parametro["value"].ToMqlParam(params[k], parametro["data_type"].ToString("TYPE_STRING")))
|
|
{
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(false);
|
|
m_shared_builder.KeyWV("result").ValSWV(StringFormat("Failed convert param = %d to mql param", k));
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
return;
|
|
}
|
|
|
|
//---
|
|
k++;
|
|
it.Next();
|
|
}
|
|
}
|
|
|
|
::ResetLastError();
|
|
const int handle = IndicatorCreate(symbol, tf, type, t, params);
|
|
if(handle == INVALID_HANDLE)
|
|
{
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(false);
|
|
if(type == IND_CUSTOM)
|
|
{
|
|
m_shared_builder.KeyWV("result").ValS(StringFormat("Indicator with alias '%s' cannot created, last mql5 error = %d, Since it is custom, verify that the first parameter contains the path of the indicator for its relative loading to the folder. Indicators\\\\",
|
|
name, ::GetLastError()));
|
|
}
|
|
else
|
|
{
|
|
m_shared_builder.KeyWV("result").ValS(StringFormat("Indicator with alias '%s' cannot created, last mql5 error = %d",
|
|
name, ::GetLastError()));
|
|
}
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
}
|
|
else
|
|
{
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(true);
|
|
m_shared_builder.KeyWV("result").ValS(StringFormat("Indicator %s successfully created, with handle = %d", name, handle));
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
long meta = long(handle) | long(type) << 32;
|
|
m_indicators.Add(name, meta);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case MCPFUNC_IND_ACTION_TOTAL:
|
|
{
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(true);
|
|
m_shared_builder.KeyWV("result").Val(m_indicators.Count());
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
break;
|
|
}
|
|
|
|
case MCPFUNC_IND_ACTION_GET_HANDLES_NAMES:
|
|
{
|
|
long metas[];
|
|
string names[];
|
|
const int c = m_indicators.CopyTo(names, metas);
|
|
if(c < 1)
|
|
{
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(true);
|
|
m_shared_builder.KeyWV("result").Arr();
|
|
m_shared_builder.EndArr();
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
return;
|
|
}
|
|
|
|
//---
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(true);
|
|
m_shared_builder.KeyWV("result").Arr();
|
|
for(int i = 0; i < c; i++)
|
|
{
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.Key(names[i]).Val(int(metas[i] & MCPFUNCIND_MASK_HANDLE));
|
|
m_shared_builder.EndObj();
|
|
}
|
|
|
|
//---
|
|
m_shared_builder.EndArr();
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
break;
|
|
}
|
|
|
|
case MCPFUNC_IND_ACTION_REMOVE:
|
|
{
|
|
const string name = param["indicator_alias_name"].ToString("");
|
|
long meta;
|
|
if(!m_indicators.TryGet(name, meta))
|
|
{
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(false);
|
|
m_shared_builder.KeyWV("result").ValS(StringFormat("Indicator with alias = %s, It does not exist in the dict",
|
|
name));
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
return;
|
|
}
|
|
const int handle = int(meta & MCPFUNCIND_MASK_HANDLE);
|
|
|
|
if(!m_indicators.Remove(name))
|
|
{
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(false);
|
|
m_shared_builder.KeyWV("result").ValS(StringFormat("Indicator with alias = %s and handle = %d, failed to removed from dict",
|
|
name, handle));
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
return;
|
|
}
|
|
|
|
::ResetLastError();
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
if(IndicatorRelease(handle))
|
|
{
|
|
m_shared_builder.KeyWV("ok").Val(true);
|
|
m_shared_builder.KeyWV("result").ValS(StringFormat("Indicator with alias = %s and handle = %d, removed from dict and released",
|
|
name, handle));
|
|
}
|
|
else
|
|
{
|
|
m_shared_builder.KeyWV("ok").Val(true);
|
|
m_shared_builder.KeyWV("result").ValS(StringFormat("Indicator with alias = %s and handle = %d, removed from dict but IndicatorRelease failed, last mistake in MT5 = %d"
|
|
, name, handle, ::GetLastError()));
|
|
}
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
break;
|
|
}
|
|
|
|
case MCPFUNC_IND_ACTION_GET_HANDLE_BY_NAME:
|
|
{
|
|
const string name = param["indicator_alias_name"].ToString("");
|
|
long meta;
|
|
if(!m_indicators.TryGet(name, meta))
|
|
{
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(false);
|
|
m_shared_builder.KeyWV("result").ValS(StringFormat("Indicator with alias = %s, It does not exist in the dict",
|
|
name));
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
return;
|
|
}
|
|
const int handle = int(meta & MCPFUNCIND_MASK_HANDLE);
|
|
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(true);
|
|
m_shared_builder.KeyWV("result").Val(handle);
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
break;
|
|
}
|
|
|
|
case MCPFUNC_IND_ACTION_GET_PARAMETERS:
|
|
{
|
|
const string name = param["indicator_alias_name"].ToString("");
|
|
long meta;
|
|
if(!m_indicators.TryGet(name, meta))
|
|
{
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(false);
|
|
m_shared_builder.KeyWV("result").ValS(StringFormat("Indicator with alias = %s, It does not exist in the dict",
|
|
name));
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
return;
|
|
}
|
|
|
|
//---
|
|
const int handle = int(meta & MCPFUNCIND_MASK_HANDLE);
|
|
|
|
|
|
//---
|
|
MqlParam params[];
|
|
ENUM_INDICATOR type;
|
|
::ResetLastError();
|
|
const int t = IndicatorParameters(handle, type, params);
|
|
if(t == -1)
|
|
{
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(false);
|
|
m_shared_builder.KeyWV("result").ValS(StringFormat("Error get parameters of = %s, last mql5 error = %d", name, ::GetLastError()));
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
return;
|
|
}
|
|
|
|
//---
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok");
|
|
m_shared_builder.Val(true);
|
|
m_shared_builder.KeyWV("result");
|
|
m_shared_builder.Arr();
|
|
|
|
//---
|
|
for(int k = 0; k < t; k++)
|
|
{
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("data_type");
|
|
m_shared_builder.ValSWV(EnumToString(params[k].type));
|
|
m_shared_builder.KeyWV("value");
|
|
|
|
//---
|
|
switch(params[k].type)
|
|
{
|
|
case TYPE_BOOL:
|
|
m_shared_builder.Val(params[k].integer_value);
|
|
break;
|
|
case TYPE_CHAR:
|
|
m_shared_builder.Val(params[k].integer_value);
|
|
break;
|
|
case TYPE_UCHAR:
|
|
m_shared_builder.Val(params[k].integer_value);
|
|
break;
|
|
case TYPE_SHORT:
|
|
m_shared_builder.Val(params[k].integer_value);
|
|
break;
|
|
case TYPE_USHORT:
|
|
m_shared_builder.Val(params[k].integer_value);
|
|
break;
|
|
case TYPE_COLOR:
|
|
m_shared_builder.ValSNoRefWV(string(color(params[k].integer_value)));
|
|
break;
|
|
case TYPE_INT:
|
|
m_shared_builder.Val(params[k].integer_value);
|
|
break;
|
|
case TYPE_UINT:
|
|
m_shared_builder.Val(params[k].integer_value);
|
|
break;
|
|
case TYPE_DATETIME:
|
|
m_shared_builder.ValSNoRefWV(string(datetime(params[k].integer_value)));
|
|
break;
|
|
case TYPE_LONG:
|
|
case TYPE_ULONG:
|
|
m_shared_builder.Val(params[k].integer_value);
|
|
break;
|
|
case TYPE_FLOAT:
|
|
m_shared_builder.Val(params[k].double_value);
|
|
break;
|
|
case TYPE_DOUBLE:
|
|
m_shared_builder.Val(params[k].double_value);
|
|
break;
|
|
case TYPE_STRING:
|
|
m_shared_builder.ValS(params[k].string_value);
|
|
break;
|
|
default:
|
|
m_shared_builder.ValS(params[k].string_value);
|
|
break;
|
|
}
|
|
m_shared_builder.EndObj();
|
|
}
|
|
|
|
//---
|
|
m_shared_builder.EndArr();
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
break;
|
|
}
|
|
|
|
case MCPFUNC_IND_ACTION_ADD:
|
|
{
|
|
const int handle = (int)param["indicator_handle"].ToInt(-1);
|
|
const ENUM_INDICATOR type = CEnumRegBasis::GetValNoRef<ENUM_INDICATOR>(param["ind_type"].ToString(""), WRONG_VALUE);
|
|
const string name = param["indicator_alias_name"].ToString("");
|
|
const bool re = param["forze_add"].ToBool(false);
|
|
|
|
//---
|
|
if(m_indicators.Contains(name))
|
|
{
|
|
if(!re)
|
|
{
|
|
// Nota: en el código original este mensaje se calculaba pero luego
|
|
// siempre era sobrescrito por el resultado final de éxito (no había return).
|
|
// Se preserva ese comportamiento (posible bug preexistente) tal cual.
|
|
}
|
|
else
|
|
{
|
|
m_indicators.Remove(name);
|
|
}
|
|
}
|
|
|
|
//---
|
|
long meta = long(handle) | long(type) << 32;
|
|
m_indicators.Add(name, meta);
|
|
|
|
//---
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(true);
|
|
m_shared_builder.KeyWV("result").ValS(StringFormat("Indicator with alias = %s and handle = %d, added to dict",
|
|
name, handle));
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
break;
|
|
}
|
|
case MCPFUNC_IND_ACTION_COPYBUFFER:
|
|
{
|
|
const string name = param["indicator_alias_name"].ToString("");
|
|
long meta;
|
|
if(!m_indicators.TryGet(name, meta))
|
|
{
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(false);
|
|
m_shared_builder.KeyWV("result").ValS(StringFormat("Indicator with alias = %s, It does not exist in the dict",
|
|
name));
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
return;
|
|
}
|
|
const int handle = int(meta & MCPFUNCIND_MASK_HANDLE);
|
|
|
|
//---
|
|
::ResetLastError();
|
|
const int t = CopyBuffer(handle, (int)param["buffer_num"].ToInt(0),
|
|
(int)param["start_pos"].ToInt(0), (int)param["count"].ToInt(1), m_buffer);
|
|
if(t == -1)
|
|
{
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(false);
|
|
m_shared_builder.KeyWV("result").ValS(StringFormat("Indicator with alias = %s, Failed in copy buffer, last mt5 err = %d",
|
|
name, ::GetLastError()));
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
return;
|
|
}
|
|
|
|
//---
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(true);
|
|
m_shared_builder.KeyWV("result").Arr();
|
|
for(int i = 0; i < t; i++)
|
|
{
|
|
m_shared_builder.Val(m_buffer[i]);
|
|
}
|
|
m_shared_builder.EndArr();
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
break;
|
|
}
|
|
default:
|
|
m_shared_builder.PutChar('"');
|
|
m_shared_builder.Obj();
|
|
m_shared_builder.KeyWV("ok").Val(false);
|
|
m_shared_builder.KeyWV("error").ValSWV("Error, invalid mode");
|
|
m_shared_builder.EndObj();
|
|
m_shared_builder.PutChar('"');
|
|
break;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
}
|
|
#endif // FULLMT5MCPBYLEO_SRC_IND_MAIN_MQH
|
|
//+------------------------------------------------------------------+
|