2026-06-29 17:48:51 -05:00
//+------------------------------------------------------------------+
//| 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
{
2026-06-29 20:43:05 -05:00
# define MCPFUNCIND_MASK_HANDLE ( 0xFFFFFFFF )
2026-06-29 17:48:51 -05:00
//+------------------------------------------------------------------+
//| indicator_manage |
//+------------------------------------------------------------------+
class CMcpFuncInd : public CMcpFunction
{
private :
CDictSValue < long > m_indicators ;
CJsonBuilder m_builder ;
2026-07-01 10:15:51 -05:00
double m_buffer [ ] ;
2026-06-29 17:48:51 -05:00
public :
2026-07-01 10:15:51 -05:00
CMcpFuncInd ( void ) : CMcpFunction ( 0 , false , " indicator_manage " ) { ArraySetAsSeries ( m_buffer , true ) ; }
2026-06-29 20:43:05 -05:00
~ CMcpFuncInd ( void )
{
long meta [ ] ;
string keys [ ] ;
const int t = m_indicators . GetValues ( meta , keys ) ;
for ( int i = 0 ; i < t ; i + + )
{
IndicatorRelease ( int ( meta [ i ] & MCPFUNCIND_MASK_HANDLE ) ) ;
}
}
2026-06-29 17:48:51 -05:00
//---
void Run ( CJsonNode & param , string & res ) override final ;
} ;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CMcpFuncInd : : Run ( CJsonNode & param , string & res )
{
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 ) )
{
res = StringFormat ( " { \" ok \" :false, \" result \" : \" Indicator with alias '%s' is register in dict \" } " , name ) ;
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 ) ;
//---
2026-07-01 11:41:37 -05:00
if ( t > 0 )
2026-06-29 17:48:51 -05:00
{
2026-07-01 11:41:37 -05:00
CJsonIteratorArray it = parametros . BeginArr ( ) ;
int k = 0 ;
2026-06-29 17:48:51 -05:00
//---
2026-07-01 11:41:37 -05:00
while ( it . IsValid ( ) )
2026-06-29 17:48:51 -05:00
{
2026-07-01 11:41:37 -05:00
CJsonNode parametro = it . Val ( ) ;
params [ k ] . type = CEnumRegBasis : : GetValNoRef < ENUM_DATATYPE > ( parametro [ " data_type " ] . ToString ( ) , TYPE_STRING ) ;
//---
switch ( params [ k ] . type )
{
case TYPE_BOOL :
params [ k ] . integer_value = parametro [ " value " ] . ToInt ( 0 ) ;
break ;
case TYPE_CHAR :
params [ k ] . integer_value = parametro [ " value " ] . ToInt ( 0 ) ;
break ;
case TYPE_UCHAR :
params [ k ] . integer_value = parametro [ " value " ] . ToInt ( 0 ) ;
break ;
case TYPE_SHORT :
params [ k ] . integer_value = parametro [ " value " ] . ToInt ( 0 ) ;
break ;
case TYPE_USHORT :
params [ k ] . integer_value = parametro [ " value " ] . ToInt ( 0 ) ;
break ;
case TYPE_COLOR :
params [ k ] . integer_value = long ( color ( parametro [ " value " ] . ToString ( " " ) ) ) ;
break ;
case TYPE_INT :
params [ k ] . integer_value = parametro [ " value " ] . ToInt ( 0 ) ;
break ;
case TYPE_UINT :
params [ k ] . integer_value = parametro [ " value " ] . ToInt ( 0 ) ;
break ;
case TYPE_DATETIME :
params [ k ] . integer_value = long ( datetime ( parametro [ " value " ] . ToString ( " 0 " ) ) ) ;
break ;
case TYPE_LONG :
case TYPE_ULONG :
params [ k ] . integer_value = parametro [ " value " ] . ToInt ( 0 ) ;
break ;
case TYPE_FLOAT :
params [ k ] . double_value = parametro [ " value " ] . ToDouble ( 0.00 ) ;
break ;
case TYPE_DOUBLE :
params [ k ] . double_value = parametro [ " value " ] . ToDouble ( 0.00 ) ;
break ;
case TYPE_STRING :
params [ k ] . string_value = parametro [ " value " ] . ToString ( " " ) ;
break ;
default :
params [ k ] . string_value = parametro [ " value " ] . ToString ( " " ) ;
break ;
}
k + + ;
it . Next ( ) ;
2026-06-29 17:48:51 -05:00
}
}
: : ResetLastError ( ) ;
const int handle = IndicatorCreate ( symbol , tf , type , t , params ) ;
if ( handle = = INVALID_HANDLE )
{
if ( type = = IND_CUSTOM )
{
res = StringFormat ( " { \" ok \" :false, \" result \" : \" 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
{
2026-06-29 20:43:05 -05:00
res = StringFormat ( " { \" ok \" :false, \" result \" : \" Indicator with alias '%s' cannot created, last mql5 error = %d \" } " ,
name , : : GetLastError ( ) ) ;
2026-06-29 17:48:51 -05:00
}
}
else
{
2026-06-29 20:43:05 -05:00
res = StringFormat ( " { \" ok \" :true, \" result \" : \" Indicator %s successfully created, with handle = %d \" } " , name , handle ) ;
2026-06-29 17:48:51 -05:00
long meta = long ( handle ) | long ( type ) < < 32 ;
m_indicators . Add ( name , meta ) ;
}
break ;
}
case MCPFUNC_IND_ACTION_TOTAL :
{
res = " { \" ok \" :true, \" result \" : " + string ( m_indicators . Count ( ) ) + " } " ;
break ;
}
case MCPFUNC_IND_ACTION_GET_HANDLES_NAMES :
{
long metas [ ] ;
string names [ ] ;
const int c = m_indicators . GetValues ( metas , names ) ;
if ( c < 1 )
{
res = " { \" ok \" :true, \" result \" :[]} " ;
return ;
}
//---
res = " { \" ok \" :true, \" result \" :[ " ;
for ( int i = 0 ; i < c ; i + + )
{
res + = " { " ;
res + = " \" " + names [ i ] + " \" : " ;
2026-06-29 20:43:05 -05:00
res + = string ( int ( metas [ i ] & MCPFUNCIND_MASK_HANDLE ) ) ;
2026-06-29 17:48:51 -05:00
res + = " } " ;
}
//---
res + = " ]} " ;
break ;
}
case MCPFUNC_IND_ACTION_REMOVE :
{
const string name = param [ " indicator_alias_name " ] . ToString ( " " ) ;
long meta ;
if ( ! m_indicators . TryGet ( name , meta ) )
{
res = StringFormat ( " { \" ok \" :false, \" result \" : \" Indicator with alias = %s, It does not exist in the dict \" } " ,
name ) ;
return ;
}
2026-06-29 20:43:05 -05:00
const int handle = int ( meta & MCPFUNCIND_MASK_HANDLE ) ;
2026-06-29 17:48:51 -05:00
2026-07-01 11:41:37 -05:00
if ( ! m_indicators . Remove ( name ) )
2026-06-29 17:48:51 -05:00
{
res = StringFormat ( " { \" ok \" :false, \" result \" : \" Indicator with alias = %s and handle = %d, failed to removed from dict \" } " ,
name , handle ) ;
return ;
}
: : ResetLastError ( ) ;
if ( IndicatorRelease ( handle ) )
{
res = StringFormat ( " { \" ok \" :true, \" result \" : \" Indicator with alias = %s and handle = %d, removed from dict and released \" } " ,
name , handle ) ;
}
else
{
res = StringFormat ( " { \" ok \" :true, \" result \" : \" Indicator with alias = %s and handle = %d, removed from dict but IndicatorRelease failed, last mistake in MT5 = %d \" } "
, name , handle , : : GetLastError ( ) ) ;
}
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 ) )
{
res = StringFormat ( " { \" ok \" :false, \" result \" : \" Indicator with alias = %s, It does not exist in the dict \" } " ,
name ) ;
return ;
}
2026-06-29 20:43:05 -05:00
const int handle = int ( meta & MCPFUNCIND_MASK_HANDLE ) ;
2026-06-29 17:48:51 -05:00
res = " { \" ok \" :true, \" result \" : " + string ( handle ) + " } " ;
break ;
}
case MCPFUNC_IND_ACTION_GET_PARAMETERS :
{
const string name = param [ " indicator_alias_name " ] . ToString ( " " ) ;
long meta ;
if ( ! m_indicators . TryGet ( name , meta ) )
{
res = StringFormat ( " { \" ok \" :false, \" result \" : \" Indicator with alias = %s, It does not exist in the dict \" } " ,
name ) ;
return ;
}
//---
2026-06-29 20:43:05 -05:00
const int handle = int ( meta & MCPFUNCIND_MASK_HANDLE ) ;
2026-06-29 17:48:51 -05:00
//---
MqlParam params [ ] ;
ENUM_INDICATOR type ;
: : ResetLastError ( ) ;
const int t = IndicatorParameters ( handle , type , params ) ;
if ( t = = -1 )
{
res = StringFormat ( " { \" ok \" :false, \" result \" : \" Error get parameters of = %s, last mql5 error = %d \" } " , name , : : GetLastError ( ) ) ;
return ;
}
//---
2026-06-30 13:04:20 -05:00
m_builder . Clear ( ) ;
2026-06-29 17:48:51 -05:00
m_builder . Obj ( ) ;
m_builder . Key ( " ok " ) ;
m_builder . Val ( true ) ;
m_builder . Key ( " result " ) ;
m_builder . Arr ( ) ;
//---
for ( int k = 0 ; k < t ; k + + )
{
m_builder . Obj ( ) ;
m_builder . Key ( " data_type " ) ;
m_builder . ValSNoRef ( EnumToString ( params [ k ] . type ) ) ;
m_builder . Key ( " value " ) ;
//---
switch ( params [ k ] . type )
{
case TYPE_BOOL :
m_builder . Val ( params [ k ] . integer_value ) ;
break ;
case TYPE_CHAR :
m_builder . Val ( params [ k ] . integer_value ) ;
break ;
case TYPE_UCHAR :
m_builder . Val ( params [ k ] . integer_value ) ;
break ;
case TYPE_SHORT :
m_builder . Val ( params [ k ] . integer_value ) ;
break ;
case TYPE_USHORT :
m_builder . Val ( params [ k ] . integer_value ) ;
break ;
case TYPE_COLOR :
m_builder . ValSNoRef ( string ( color ( params [ k ] . integer_value ) ) ) ;
break ;
case TYPE_INT :
m_builder . Val ( params [ k ] . integer_value ) ;
break ;
case TYPE_UINT :
m_builder . Val ( params [ k ] . integer_value ) ;
break ;
case TYPE_DATETIME :
m_builder . ValSNoRef ( string ( datetime ( params [ k ] . integer_value ) ) ) ;
break ;
case TYPE_LONG :
case TYPE_ULONG :
m_builder . Val ( params [ k ] . integer_value ) ;
break ;
case TYPE_FLOAT :
m_builder . Val ( params [ k ] . double_value ) ;
break ;
case TYPE_DOUBLE :
m_builder . Val ( params [ k ] . double_value ) ;
break ;
case TYPE_STRING :
m_builder . ValS ( params [ k ] . string_value ) ;
break ;
default :
m_builder . ValS ( params [ k ] . string_value ) ;
break ;
}
m_builder . EndObj ( ) ;
}
//---
m_builder . EndArr ( ) . EndObj ( ) ;
res = m_builder . Build ( ) ;
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 )
{
res = StringFormat ( " { \" ok \" :false, \" result \" : \" Indicator with alias '%s' is register in dict, use forze_add=true, If you want to replace it \" } " ,
name ) ;
}
else
{
m_indicators . Remove ( name ) ;
}
}
//---
long meta = long ( handle ) | long ( type ) < < 32 ;
m_indicators . Add ( name , meta ) ;
//---
res = StringFormat ( " { \" ok \" :true, \" result \" : \" Indicator with alias = %s and handle = %d, added to dict \" } " ,
name , handle ) ;
break ;
}
2026-07-01 10:15:51 -05:00
case MCPFUNC_IND_ACTION_COPYBUFFER :
{
const string name = param [ " indicator_alias_name " ] . ToString ( " " ) ;
long meta ;
if ( ! m_indicators . TryGet ( name , meta ) )
{
res = StringFormat ( " { \" ok \" :false, \" result \" : \" Indicator with alias = %s, It does not exist in the dict \" } " ,
name ) ;
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 )
{
res = StringFormat ( " { \" ok \" :false, \" result \" : \" Indicator with alias = %s, Failed in copy buffer, last mt5 err = %d \" } " ,
name , : : GetLastError ( ) ) ;
return ;
}
//---
res = " { \" ok \" :true, \" result \" :[ " ;
const int last = t - 1 ;
for ( int i = 0 ; i < last ; i + + )
{
res + = string ( m_buffer [ i ] ) + " , " ;
}
res + = string ( m_buffer [ last ] ) + " ]} " ;
break ;
}
2026-06-29 17:48:51 -05:00
default :
res = " { \" ok \" :false, \" error \" : \" Error, invalid mode \" } " ;
break ;
}
}
//+------------------------------------------------------------------+
}
# endif // FULLMT5MCPBYLEO_SRC_IND_MAIN_MQH
//+------------------------------------------------------------------+