562 satır
18 KiB
MQL5
562 satır
18 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| Main.mqh |
|
|
//| Copyright 2025, Niquel Mendoza. |
|
|
//| https://www.mql5.com/es/users/nique_372/news |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2025, Niquel Mendoza."
|
|
#property link "https://www.mql5.com/es/users/nique_372/news"
|
|
#property strict
|
|
|
|
#ifndef EASYSB_CORE_STRATEGY_MQH
|
|
#define EASYSB_CORE_STRATEGY_MQH
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
// Source: https://www.youtube.com/watch?v=o0v4KQxZbpU&t=183s
|
|
#include "Functions.mqh"
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
class CEstrategia : public CStrategyBase
|
|
{
|
|
private:
|
|
//--- Variables
|
|
bool m_operate;
|
|
uint8_t m_strategy_flags;
|
|
double m_max_9;
|
|
double m_min_9;
|
|
bool m_ai_init;
|
|
|
|
//--- Functions pointers
|
|
CEstrategia_FuncBos m_func_bos;
|
|
CEstrategia_FuncBos m_func_pda;
|
|
|
|
//--- Ia
|
|
// Variables miembro
|
|
uint8_t m_ai_flags;
|
|
CStrategyAiGetData* m_ai_get_data;
|
|
IStrategyAddonAiFilter* m_ai_intermadiary;
|
|
IStrategyAddonTPSL* m_ai_sl;
|
|
IStrategyAddonTPSL* m_ai_tp;
|
|
CAiLeoMulyiFeatureGen* m_data_generator;
|
|
|
|
// Funciones
|
|
template <typename TTrainerClass, typename TWriterClass, typename TOutputClass, typename TFinalClass>
|
|
bool InitAiComponentForTraining(const string& prefix, TFinalClass* &intermediay, const int bar_to_revise, const bool common_folder);
|
|
|
|
|
|
//---
|
|
void Clean();
|
|
void OpenOrder(ENUM_POSITION_TYPE type);
|
|
|
|
public:
|
|
|
|
CEstrategia(ulong magic_number_, string symbol_, ENUM_TIMEFRAMES timeframe_ = PERIOD_CURRENT, long chart_id_ = 0,
|
|
int subwindow_ = 0, ulong max_deviation_ = NO_MAX_DEVIATION_DEFINED);
|
|
~CEstrategia(void);
|
|
|
|
//---
|
|
void InitAiTraining(int bar_to_revise, bool common_folder);
|
|
void InitAiLive(int bar_to_revise, double min_proba, ENUM_TPSL_GENERAL type_tp_sl_ai, ENUM_STRATEGY_ENTRY entry_type, CSetFile* &set_file, ConfigDependencyAiStrBase& config_in);
|
|
|
|
//---
|
|
void OnNewBar(const datetime curr_time) override;
|
|
void OnNewWeek(const datetime curr_time) override;
|
|
void OnInterupcion();
|
|
void OnTick(const datetime curr_time) override {}
|
|
|
|
//---
|
|
void OnNewBarM1(const datetime curr_time);
|
|
|
|
//---
|
|
__forceinline bool UseAi() const { return m_ai_flags > 0;}
|
|
void InitAiFlags(ENUM_TPSL_GENERAL type_tp_sl_ai, ENUM_STRATEGY_ENTRY entry_type);
|
|
};
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
CEstrategia::CEstrategia(ulong magic_number_, string symbol_, ENUM_TIMEFRAMES timeframe_ = PERIOD_CURRENT, long chart_id_ = 0, int subwindow_ = 0, ulong max_deviation_ = 0)
|
|
: CStrategyBase(magic_number_, symbol_, timeframe_, chart_id_, subwindow_, max_deviation_, "TTRdes sb"),
|
|
m_ai_tp(NULL), m_ai_sl(NULL), m_ai_intermadiary(NULL), m_data_generator(NULL), m_ai_init(false), m_ai_get_data(NULL), m_ai_flags(0)
|
|
{
|
|
CBasicEvents::RegisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_WEEK);
|
|
Clean();
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
CEstrategia::~CEstrategia(void)
|
|
{
|
|
//---
|
|
if(CBasicEvents::IsActive()) // CONSULTAMOS si aun esta activo
|
|
{
|
|
// Si esta activo entonces nos desuscribirremos
|
|
CBasicEvents::UnregisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_WEEK);
|
|
}
|
|
|
|
//---
|
|
if(m_ai_get_data != NULL)
|
|
delete m_ai_get_data;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CEstrategia::InitAiFlags(ENUM_TPSL_GENERAL type_tp_sl_ai, ENUM_STRATEGY_ENTRY entry_type)
|
|
{
|
|
m_ai_flags |= (entry_type == STRATEGY_TYPE_ENTRY_WITH_AI ? AIDATALEO_ADDON_FLAG_ENTRY : 0);
|
|
m_ai_flags |= (type_tp_sl_ai == TPSL_GENERAL_TYPE_USE_TP_AI || type_tp_sl_ai == TPSL_GENERAL_TYPE_USE_FULL_AI ? AIDATALEO_ADDON_FLAG_TP : 0);
|
|
m_ai_flags |= (type_tp_sl_ai == TPSL_GENERAL_TYPE_USE_SL_AI || type_tp_sl_ai == TPSL_GENERAL_TYPE_USE_FULL_AI ? AIDATALEO_ADDON_FLAG_SL : 0);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TTrainerClass, typename TWriterClass, typename TOutputClass, typename TFinalClass>
|
|
bool CEstrategia::InitAiComponentForTraining(const string& prefix, TFinalClass* &intermediay, const int bar_to_revise, const bool common_folder)
|
|
{
|
|
// Intermediario de ia
|
|
intermediay = new TTrainerClass();
|
|
TTrainerClass* trainer = (TTrainerClass*)intermediay;
|
|
|
|
// Writer
|
|
TWriterClass* writer = new TWriterClass(m_ai_get_data);
|
|
|
|
// Output
|
|
TOutputClass* output = new TOutputClass();
|
|
|
|
// Inicamos
|
|
const string file_name_scaler_p = FILE_NAME_AI_DATA_SCALER_P(prefix);
|
|
const string file_name_data = FILE_NAME_AI_DATA_SCALER_DATA(prefix);
|
|
|
|
// Iniciamos trainer
|
|
return trainer.Init(m_timeframe, m_symbol, file_name_scaler_p, file_name_data, common_folder, m_data_generator.Header(), bar_to_revise, writer, output, SCALERBYLEO_SCALER_TYPE_ROBUST);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CEstrategia::InitAiTraining(int bar_to_revise, bool common_folder)
|
|
{
|
|
//---
|
|
if(m_ai_init)
|
|
return;
|
|
|
|
//--- Trainer
|
|
//---
|
|
m_ai_flags = AIDATALEO_ADDON_FLAG_ENTRY | AIDATALEO_ADDON_FLAG_TP | AIDATALEO_ADDON_FLAG_SL;
|
|
|
|
//--- Generador de data
|
|
m_data_generator = new CAiLeoMulyiFeatureGen();
|
|
g_ai_data_features_parser.AddLogFlags(LogFlags());
|
|
if(!m_data_generator.Init("GeneradorData", g_res_generic_features))
|
|
{
|
|
LogError("Fallo al cargar las features", FUNCION_ACTUAL);
|
|
Remover();
|
|
}
|
|
else
|
|
{
|
|
LogInfo("Generador de data cargado exitosamente", FUNCION_ACTUAL);
|
|
AddLogger(m_data_generator);
|
|
}
|
|
|
|
//--- Data global
|
|
m_ai_get_data = new CStrategyAiGetData(m_data_generator, true);
|
|
|
|
//--- Trainer para prediccion
|
|
if(!InitAiComponentForTraining<CStrategyAddonAiFilterTrainer, CStrategyAiAddWriter, CStrategyAiGetOutput, IStrategyAddonAiFilter>("pred", m_ai_intermadiary, bar_to_revise, common_folder))
|
|
{
|
|
LogCriticalError("Fallo al iniciar el trainer para entry ia", FUNCION_ACTUAL);
|
|
Remover();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
AddLogger(m_ai_intermadiary);
|
|
}
|
|
|
|
//--- Trainer para tp
|
|
if(!InitAiComponentForTraining<CStrategyAddonAiTpTrainer, CStrategyAiAddWriter, CStrategyAiTpGetOutput, IStrategyAddonTPSL>("tp", m_ai_tp, bar_to_revise, common_folder))
|
|
{
|
|
LogCriticalError("Fallo al iniciar el trainer para tp", FUNCION_ACTUAL);
|
|
Remover();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
AddLogger(m_ai_tp);
|
|
}
|
|
|
|
//--- Trainer para sl
|
|
if(!InitAiComponentForTraining<CStrategyAddonAiSlTrainer, CStrategyAiAddWriter, CStrategyAiSlGetOutput, IStrategyAddonTPSL>("sl", m_ai_sl, bar_to_revise, common_folder))
|
|
{
|
|
LogCriticalError("Fallo al iniciar el trainer para sl", FUNCION_ACTUAL);
|
|
Remover();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
AddLogger(m_ai_sl);
|
|
}
|
|
|
|
|
|
//---
|
|
m_ai_init = true;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CEstrategia::InitAiLive(int bar_to_revise, double min_proba, ENUM_TPSL_GENERAL type_tp_sl_ai, ENUM_STRATEGY_ENTRY entry_type, CSetFile* &set_file, ConfigDependencyAiStrBase& config_in)
|
|
{
|
|
//---
|
|
if(m_ai_init)
|
|
return;
|
|
|
|
//---
|
|
if(m_ai_flags == 0) // NO AI
|
|
return;
|
|
|
|
//---
|
|
config_in.main_folder = FOLDER_AI_DATA;
|
|
//config_in.comon_folder = true; lo elige el user
|
|
config_in.file_name_idx = "idx.txt";
|
|
|
|
// Scalado
|
|
config_in.file_name_scalers[CONFIGURATION_DEPENDECY_ARR_IDX_PRED] = FILE_NAME_AI_DATA_SCALER_NAME("pred");
|
|
config_in.file_name_scalers[CONFIGURATION_DEPENDECY_ARR_IDX_SL] = FILE_NAME_AI_DATA_SCALER_NAME("sl");
|
|
config_in.file_name_scalers[CONFIGURATION_DEPENDECY_ARR_IDX_TP] = FILE_NAME_AI_DATA_SCALER_NAME("tp");
|
|
|
|
// Onnx
|
|
config_in.file_name_models[CONFIGURATION_DEPENDECY_ARR_IDX_PRED] = "ModelPred.onnx";
|
|
config_in.file_name_models[CONFIGURATION_DEPENDECY_ARR_IDX_SL] = "ModelSL_f.onnx";
|
|
config_in.file_name_models[CONFIGURATION_DEPENDECY_ARR_IDX_TP] = "ModelTP_f.onnx";
|
|
|
|
//---
|
|
ConfigDependencyOutAiNormal out_data;
|
|
if(!CConfigurationsDependecy::GetDependencyNormal(config_in, out_data))
|
|
{
|
|
LogError("Fallo al cargar dependencias del modelo", FUNCION_ACTUAL);
|
|
Remover();
|
|
return;
|
|
}
|
|
set_file = out_data.set_file;
|
|
|
|
//--- Generador de data
|
|
m_data_generator = new CAiLeoMulyiFeatureGen();
|
|
g_ai_data_features_parser.AddLogFlags(LogFlags());
|
|
if(!m_data_generator.Init("GeneradorData", g_res_generic_features))
|
|
{
|
|
LogError("Fallo al cargar las features", FUNCION_ACTUAL);
|
|
Remover();
|
|
}
|
|
else
|
|
{
|
|
LogInfo("Generador de data cargado exitosamente", FUNCION_ACTUAL);
|
|
AddLogger(m_data_generator);
|
|
}
|
|
|
|
//--- Data global
|
|
m_ai_get_data = new CStrategyAiGetData(m_data_generator, true);
|
|
|
|
//---
|
|
if((m_ai_flags & AIDATALEO_ADDON_FLAG_ENTRY) != 0)
|
|
{
|
|
m_ai_intermadiary = new CAiPredictorFinal();
|
|
CAiPredictorFinal* preditor = (CAiPredictorFinal*)m_ai_intermadiary;
|
|
if(!preditor.Init(SCALERBYLEO_SCALER_TYPE_ROBUST, m_ai_get_data, out_data.file_name_scaler_pred, out_data.file_name_onnx_pred, out_data.idx_pred))
|
|
{
|
|
LogError("Fallo al cargar el predictor", FUNCION_ACTUAL);
|
|
Remover();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
AddLogger(m_ai_intermadiary);
|
|
preditor.MinProba(min_proba);
|
|
}
|
|
}
|
|
|
|
//---
|
|
if((m_ai_flags & AIDATALEO_ADDON_FLAG_TP) != 0)
|
|
{
|
|
m_ai_tp = new CAiPredictorFinalRegTp();
|
|
CAiPredictorFinalRegTp* preditor = (CAiPredictorFinalRegTp*)m_ai_tp;
|
|
if(!preditor.Init(SCALERBYLEO_SCALER_TYPE_ROBUST, m_ai_get_data, out_data.file_name_scaler_tp, out_data.file_name_onnx_tp, out_data.idx_tp))
|
|
{
|
|
LogError("Fallo al cargar el predictor", FUNCION_ACTUAL);
|
|
Remover();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
AddLogger(m_ai_tp);
|
|
}
|
|
}
|
|
|
|
//---
|
|
if((m_ai_flags & AIDATALEO_ADDON_FLAG_SL) != 0)
|
|
{
|
|
m_ai_sl = new CAiPredictorFinalRegSl();
|
|
CAiPredictorFinalRegSl* preditor = (CAiPredictorFinalRegSl*)m_ai_sl;
|
|
if(!preditor.Init(SCALERBYLEO_SCALER_TYPE_ROBUST, m_ai_get_data, out_data.file_name_scaler_sl, out_data.file_name_onnx_sl, out_data.idx_sl))
|
|
{
|
|
LogError("Fallo al cargar el predictor", FUNCION_ACTUAL);
|
|
Remover();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
AddLogger(m_ai_sl);
|
|
}
|
|
}
|
|
|
|
//---
|
|
m_ai_init = true;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CEstrategia::OnNewBarM1(const datetime curr_time)
|
|
{
|
|
if(m_data_generator != NULL)
|
|
{
|
|
CIctLibPool::OnNewBarM1(curr_time); // Ejecutamos el POOL
|
|
m_data_generator.OnNewBarM1(curr_time); // Ejecutamos las features
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CEstrategia::OnNewWeek(const datetime curr_time)
|
|
{
|
|
g_bos_choch.DeleteAll();
|
|
g_bloque1.DeleteAll();
|
|
g_bloque2.DeleteAll();
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CEstrategia::Clean(void)
|
|
{
|
|
m_strategy_flags = 0;
|
|
m_func_bos = NULL;
|
|
m_func_pda = NULL;
|
|
m_max_9 = 0.000;
|
|
m_min_9 = 0.000;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CEstrategia::OnInterupcion()
|
|
{
|
|
g_bloque1.SetParo();
|
|
g_bloque2.SetParo();
|
|
g_bos_choch.SetParo();
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CEstrategia::OnNewBar(const datetime curr_time)
|
|
{
|
|
if(risk.GetPositionsTotal() > 0)
|
|
return;
|
|
|
|
//--- Ejecuciones de addons Ai solo si se utilizan
|
|
if(m_ai_intermadiary != NULL)
|
|
m_ai_intermadiary.OnNewBar(curr_time);
|
|
|
|
// SL
|
|
if(m_ai_sl != NULL)
|
|
m_ai_sl.OnNewBar(curr_time);
|
|
|
|
// TP
|
|
if(m_ai_tp != NULL)
|
|
m_ai_tp.OnNewBar(curr_time);
|
|
|
|
//--- Estrategia
|
|
if(g_sesion.EnSesion())
|
|
{
|
|
if(g_sesion.IsInitSession())
|
|
{
|
|
LogInfo("Inicio de sesion", FUNCION_ACTUAL);
|
|
m_max_9 = ::iHigh(m_symbol, PERIOD_H1, 1);
|
|
m_min_9 = ::iLow(m_symbol, PERIOD_H1, 1);
|
|
m_operate = false;
|
|
}
|
|
|
|
if(m_operate)
|
|
return;
|
|
|
|
|
|
//---
|
|
if(m_strategy_flags == 0)
|
|
{
|
|
const double prev_high = ::iHigh(m_symbol, m_timeframe, 1);
|
|
const double prev_low = ::iLow(m_symbol, m_timeframe, 1);
|
|
|
|
if(prev_high > m_max_9)
|
|
{
|
|
m_strategy_flags |= S_FLAG_DIRECION_SELL;
|
|
m_func_bos = EstrategiaFuncionts::EstRopturaAlaBaja;
|
|
}
|
|
else
|
|
if(m_min_9 > prev_low)
|
|
{
|
|
m_strategy_flags |= S_FLAG_DIRECION_BUY;
|
|
m_func_bos = EstrategiaFuncionts::EstRopturaAlAlza;
|
|
}
|
|
}
|
|
else
|
|
if((m_strategy_flags & S_FLAG_DEZPLAZAMIENTO_HECHO) == 0)
|
|
{
|
|
if(m_func_bos())
|
|
{
|
|
m_strategy_flags |= S_FLAG_DEZPLAZAMIENTO_HECHO;
|
|
|
|
if((m_strategy_flags & S_FLAG_DIRECION_BUY) != 0)
|
|
{
|
|
m_func_pda = EstrategiaFuncionts::PdaMigAlcista;
|
|
}
|
|
else
|
|
{
|
|
m_func_pda = EstrategiaFuncionts::PdaMitBajista;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(m_func_pda())
|
|
{
|
|
OpenOrder(((m_strategy_flags & S_FLAG_DIRECION_BUY) != 0 ? POSITION_TYPE_BUY : POSITION_TYPE_SELL));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if(g_sesion.IsEndSession())
|
|
{
|
|
LogInfo("Fin de sesion", FUNCION_ACTUAL);
|
|
Clean();
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Open Order Default |
|
|
//+------------------------------------------------------------------+
|
|
void CEstrategia::OpenOrder(ENUM_POSITION_TYPE type)
|
|
{
|
|
::SymbolInfoTick(m_symbol, m_tick);
|
|
|
|
//---
|
|
static StrategyTradeConfig config;
|
|
config.type = type;
|
|
config.curr_time = m_tick.time;
|
|
|
|
//---
|
|
if(m_ai_get_data != NULL)
|
|
{
|
|
m_ai_get_data.GenerateData(m_tick.time);
|
|
}
|
|
//---
|
|
if(type == POSITION_TYPE_BUY)
|
|
{
|
|
double entry = m_tick.ask;
|
|
config.entry = entry;
|
|
|
|
//--- SL
|
|
static double sl;
|
|
if(m_ai_sl != NULL)
|
|
{
|
|
m_ai_sl.ModifyTPSL(config, sl, EMPTY_DOUBLE);
|
|
}
|
|
else
|
|
{
|
|
sl = GetSL(entry, type, m_tick.time);
|
|
}
|
|
|
|
//--- TP
|
|
static double tp;
|
|
if(m_ai_tp != NULL)
|
|
{
|
|
m_ai_tp.ModifyTPSL(config, EMPTY_DOUBLE, tp);
|
|
}
|
|
else
|
|
{
|
|
tp = GetTP(entry, type, m_tick.time);
|
|
}
|
|
|
|
//--- Entrada
|
|
if(m_ai_intermadiary != NULL && !m_ai_intermadiary.CheckOpenOrder(config))
|
|
{
|
|
Clean();
|
|
m_operate = true;
|
|
return;
|
|
}
|
|
|
|
//--- Apertura de posiciones
|
|
risk.SetStopLoss(entry - sl);
|
|
double l = m_LOT_SIZE > 0.00 ? m_LOT_SIZE : risk.GetLote(ORDER_TYPE_BUY, entry, m_max_deviation, 0);
|
|
m_trade.Buy(l, m_symbol, entry, sl, tp, "Ea buy");
|
|
}
|
|
else
|
|
if(type == POSITION_TYPE_SELL)
|
|
{
|
|
double entry = m_tick.bid;
|
|
config.entry = entry;
|
|
|
|
//--- SL
|
|
static double sl;
|
|
if(m_ai_sl != NULL)
|
|
{
|
|
m_ai_sl.ModifyTPSL(config, sl, EMPTY_DOUBLE);
|
|
}
|
|
else
|
|
{
|
|
sl = GetSL(entry, type, m_tick.time);
|
|
}
|
|
|
|
//--- TP
|
|
static double tp;
|
|
if(m_ai_tp != NULL)
|
|
{
|
|
m_ai_tp.ModifyTPSL(config, EMPTY_DOUBLE, tp);
|
|
}
|
|
else
|
|
{
|
|
tp = GetTP(entry, type, m_tick.time);
|
|
}
|
|
|
|
//--- Entrada
|
|
if(m_ai_intermadiary != NULL && !m_ai_intermadiary.CheckOpenOrder(config))
|
|
{
|
|
Clean();
|
|
m_operate = true;
|
|
return;
|
|
}
|
|
|
|
//--- Apertura de posiciones
|
|
risk.SetStopLoss(sl - entry);
|
|
double l = m_LOT_SIZE > 0.00 ? m_LOT_SIZE : risk.GetLote(ORDER_TYPE_SELL, entry, m_max_deviation, 0);
|
|
m_trade.Sell(l, m_symbol, entry, sl, tp, "Ea sell");
|
|
}
|
|
|
|
//---
|
|
Clean();
|
|
m_operate = true;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
#endif // EASYSB_CORE_STRATEGY_MQH
|