//+------------------------------------------------------------------+ //| Ea.mq5 | //| 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 version "1.00" #property strict //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include "..\\Global.mqh" #include "Main.mqh" //+------------------------------------------------------------------+ //| Inputs | //+------------------------------------------------------------------+ sinput group "----------| General |----------" input ulong InpMagic = 35465; // Número mágico input bool InpModifiedChart = true; // ¿Modificar el gráfico? sinput group "" sinput group "-------| Estrategia |-------" input ENUM_VERBOSE_LOG_LEVEL InpStrategyLogLevel = VERBOSE_LOG_LEVEL_CAUTION; // Nivel de log de la estrategia sinput group "-----| TP/SL |-----" input ENUM_TYPE_TP_SL InpStrategyTypeTpSl = TP_SL_BY_STRATEGY_RR; // Tipo de TP/SL sinput group "-- TP SL por puntos" input long InpStrategySlPoint = 200; // Stop Loss en puntos input long InpStrategyTpPoint = 400; // Take Profit en puntos sinput group "-- TP SL por ATR" input double InpStrategyAtrMultiplierTp = 2.0; // Multiplicador del ATR para el TP input double InpStrategyAtrMultiplierSl = 2.0; // Multiplicador del ATR para el SL sinput group "-- TP/SL by Strategie " input double RR_TP = 3.1; //RR TakeProfit sinput group "-----| Órdenes |-----" input long InpStrategyMaxDeviationOrders = 100; // Máxima desviación/deslizamiento de las órdenes en puntos sinput group "" sinput group "-------| Estado de la cuenta |-------" input ENUM_VERBOSE_LOG_LEVEL InpAccountStatusLogLevel = VERBOSE_LOG_LEVEL_ERROR_ONLY; // Nivel de log de Estado de cuenta/Gestión de tickets sinput group "" sinput group "-------| Gestión de riesgo |-------" input ENUM_LOTE_TYPE InpRmLoteType = Dinamico; // Tipo de lote input double InpRmLote = 0.1; // Tamaño del lote (solo para lote fijo) input ENUM_MODE_RISK_MANAGEMENT InpRmRiskMode = risk_mode_personal_account; // Tipo de modo de gestión de riesgo input ENUM_GET_LOT InpRmGetMode = GET_LOT_BY_STOPLOSS_AND_RISK_PER_OPERATION; // Cómo calcular el tamaño del lote input double InpRmPropFirmBalance = 0; // Balance de cuenta Prop Firm FTMO (si aplica) input ENUM_VERBOSE_LOG_LEVEL InpRmLogLevel = VERBOSE_LOG_LEVEL_ERROR_ONLY; // Nivel de log de Gestión de riesgo sinput group "- ML/Pérdida máxima -" input double InpRmPercentageOrMoneyMl = 0; // Porcentaje o dinero (0 => ML no usado) input ENUM_RISK_CALCULATION_MODE InpRmModeCalculationMl = percentage; // Modo de cálculo de Pérdida Máxima input ENUM_APPLIED_PERCENTAGES InpRmAppliedPercentagesMl = Balance; // Porcentaje ML se aplica a sinput group "- MWL/Pérdida máxima semanal -" input double InpRmPercentageOrMoneyMwl = 0; // Porcentaje o dinero (0 => MWL no usado) input ENUM_RISK_CALCULATION_MODE InpRmModeCalculationMwl = percentage; // Modo de cálculo de Pérdida Máxima Semanal input ENUM_APPLIED_PERCENTAGES InpRmAppliedPercentagesMwl = Balance; // Porcentaje MWL se aplica a sinput group "- MDL/Pérdida máxima diaria -" input double InpRmPercentageOrMoneyMdl = 3.0; // Porcentaje o dinero (0 => MDL no usado) input ENUM_RISK_CALCULATION_MODE InpRmModeCalculationMdl = percentage; // Modo de cálculo de Pérdida Máxima Diaria input ENUM_APPLIED_PERCENTAGES InpRmAppliedPercentagesMdl = Balance; // Porcentaje MDL se aplica a sinput group "- GMLPO/Pérdida máxima bruta por operación -" input ENUM_OF_DYNAMIC_MODES_OF_GMLPO InpRmModeGmlpo = NO_DYNAMIC_GMLPO; // Modo GMLPO input double InpRmPercentageOrMoneyGmlpo = 2.0; // Porcentaje o dinero (0 => GMLPO no usado) input ENUM_RISK_CALCULATION_MODE InpRmModeCalculationGmlpo = percentage; // Modo de cálculo de Pérdida Máxima por Operación input ENUM_APPLIED_PERCENTAGES InpRmAppliedPercentagesGmlpo = Balance; // Porcentaje GMLPO se aplica a sinput group "-- Configuración opcional de GMLPO, GMLPO dinámico" sinput group "--- GMLPO dinámico totalmente personalizable" input string InpRmNote1 = "Este parámetro determina un porcentaje específico que se restará de su balance total para establecer un umbral."; // Nota 1 input string InpRmStrPercentagesToBeReviewed = "15,30,50"; // Porcentajes a revisar (separados por comas) input string InpRmNote2 = "Cuando el balance actual (equity) cae por debajo de este umbral, se activará un nuevo nivel de riesgo en sus operaciones futuras: "; // Nota 2 input string InpRmStrPercentagesToApply = "10,20,25"; // Porcentajes a aplicar (separados por comas) input string InpRmNote3 = "Nota: 0 en ambos parámetros => no usar riesgo dinámico en GMLPO"; // Nota 3 sinput group "--- GMLPO dinámico fijo con parámetros" sinput group "- Nivel 1 -" input string InpRmNote11 = "Este parámetro determina un porcentaje específico que se restará de su balance total para establecer un umbral."; // Nota 1.1 input double InpRmBalancePercentageToActivateTheRisk1 = 2.0; // Umbral de porcentaje de balance 1 para modificar el riesgo input string InpRmNote21 = "Cuando el balance actual (equity) cae por debajo de este umbral, se activará un nuevo nivel de riesgo en sus operaciones futuras: "; // Nota 2.1 input double InpRmPercentageToBeModified1 = 1.0; // Nuevo porcentaje GMLPO 1 sinput group "- Nivel 2 -" input double InpRmBalancePercentageToActivateTheRisk2 = 5.0; // Umbral de porcentaje de balance 2 para modificar el riesgo input double InpRmPercentageToBeModified2 = 0.7; // Nuevo porcentaje GMLPO 2 sinput group "- Nivel 3 -" input double InpRmBalancePercentageToActivateTheRisk3 = 7.0; // Umbral de porcentaje de balance 3 para modificar el riesgo input double InpRmPercentageToBeModified3 = 0.5; // Nuevo porcentaje GMLPO 3 sinput group "- Nivel 4 -" input double InpRmBalancePercentageToActivateTheRisk4 = 9.0; // Umbral de porcentaje de balance 4 para modificar el riesgo input double InpRmPercentageToBeModified4 = 0.33; // Nuevo porcentaje GMLPO 4 sinput group "-- MDP/Ganancia máxima diaria --" input bool InpRmMdpIsStrict = true; // ¿MDP es estricto? input double InpRmPercentageOrMoneyMdp = 11.0; // Porcentaje o dinero (0 => MDP no usado) input ENUM_RISK_CALCULATION_MODE InpRmModeCalculationMdp = percentage; // Modo de cálculo de Ganancia Máxima Diaria input ENUM_APPLIED_PERCENTAGES InpRmAppliedPercentagesMdp = Balance; // Porcentaje MDP se aplica a //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ sinput group "-------| Modificador de riesgo (Oscar) |-------" input bool enable_mod_oscar = true; //Habilitar modificador? input double initial_risk_percenrt_to_mod = 1.0; //% positivo inicial input double max_risk_to_mod_oscar = 30.0; //Maximo riesgo en % input double multo_mod_oscar = 2.0; //Multiplicador sinput group "" sinput group "-------| Session |-------" input string InpSessionBaseName = "Sesion Nocturna"; //Nombre de la sesion sinput group "--| Rectangulo " input color clr_rect_session = clrMintCream; //Color del rectangulo de sesion input int width_sessoin = 1; //Rectangle Lines width input ENUM_LINE_STYLE style_line_rect = STYLE_SOLID; //Rectangle Line Style input bool fill_session = true; //Fill Rectangle session? sinput group "--| Lineas " input color inp_clr_lines = clrMintCream; //Color de las lineas input int width_sessoin_lines = 1; //Ancho de las lineas input ENUM_LINE_STYLE style_line_extra = STYLE_SOLID; //Estilo de las lineas input ENUM_TYPE_DRAW_RANGE_SESSION type_draw_session = draw_session_range_only_rect; //Tipo de dibujado de la sesion sinput group "--| De la sesion en si" input char inp_hora_inicio = 8;//Hora de inicio para poner ordenes (0-23) input char inp_min_inicio = 30;//Minuto de inicio para poner ordenes(0-59) input char inp_hora_fin = 9;//Hora de finalización para poner ordenes (1-23) input char inp_min_fin = 15; //Minuto de finalización poner ordenes (0-59) sinput group "" sinput group "-------| Session Asia |-------" input bool fill_rect_asia = true; // Rellenar el rectángulo de la sesión Asia input ENUM_LINE_STYLE style_rect_actia = STYLE_SOLID; // Estilo de línea para el rectángulo de Asia input int width_rect_asia = 1; // Ancho de la línea del rectángulo de Asia input color color_text_line_rect_asia = clrBisque; // Color del texto y línea del rectángulo de Asia input char hora_inicio_asia = 0; // Hora de inicio de la sesión asiática input char min_inicio_asia = 0; // Minuto de inicio de la sesión asiática input char hora_fin_asia = 8; // Hora de finalización de la sesión asiática input char min_fin_asia = 30; // Minuto de finalización de la sesión asiática sinput group "" sinput group "----------| Session Ny |----------" input char hora_inicio_ny = 16; input char min_inicio_ny = 0; sinput group "" sinput group "-------| Operation Days Configuration |-------" input bool enable_Monday = true; // Operar en lunes input bool enable_Tuesday = true; // Operar en martes input bool enable_Wednesday = true; // Operar en miércoles input bool enable_Thursday = true; // Operar en jueves input bool enable_Friday = true; // Operar en viernes input bool enable_Saturday = false; // Operar en sábado input bool enable_Sunday = false; // Operar en domingo input bool IsCryptoMarket = false; // ¿Es un mercado de criptomonedas? sinput group "" sinput group "-------| Operation Months Configuration |-------" input bool enable_Enero = true; // Operar en enero input bool enable_Febrero = true; // Operar en febrero input bool enable_Marzo = true; // Operar en marzo input bool enable_Abril = true; // Operar en abril input bool enable_Mayo = true; // Operar en mayo input bool enable_Junio = true; // Operar en junio input bool enable_Julio = true; // Operar en julio input bool enable_Agosto = true; // Operar en agosto input bool enable_Septiembre = true; // Operar en septiembre input bool enable_Octubre = true; // Operar en octubre input bool enable_Noviembre = true; // Operar en noviembre input bool enable_Diciembre = true; // Operar en diciembre sinput group "" sinput group "-------| Breakeven |-------" input bool use_be = true; // Enable Breakeven logic input ENUM_BREAKEVEN_TYPE type_break_even = BREAKEVEN_TYPE_RR; // Calculation method (RR, ATR, or fixed points) input ENUM_VERBOSE_LOG_LEVEL log_level_be = VERBOSE_LOG_LEVEL_ALL; // Break Even log level //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ sinput group "--- Breakeven based on Risk/Reward (RR) ---" input string be_rr_adv = "Requires a configured Stop Loss."; // Warning: Stop Loss is required to calculate RR input double be_rr_dbl = 1.0; // Risk/Reward ratio to activate Breakeven (e.g. 1.0) input ENUM_TYPE_EXTRA_BE_BY_RRR be_type_extra_rr = EXTRA_BE_RRR_BY_ATR; // Method to adjust Breakeven price (ATR or points) input double be_extra_points_rr_or_atr_multiplier = 1.0; // Adjustment value: ATR multiplier (atr 14 period) if method = ATR, or fixed points if method = Points sinput group "--- Breakeven based solely on ATR ---" input double be_atr_multiplier = 2.0; // ATR multiplier to trigger Breakeven (atr 14 period) input double be_atr_multiplier_extra = 1.0; // Additional multiplier for precise Breakeven adjustment (atr 14 period) sinput group "--- Breakeven based on fixed points ---" input int be_fixed_points_to_put_be = 200; // Minimum distance (in points) to trigger Breakeven input int be_fixed_points_extra = 100; // Extra points added when Breakeven is triggered //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ //--- CEstrategia strategy(InpMagic, _Symbol, _Period, 0, 0, InpStrategyMaxDeviationOrders); //--- int8_t idx_controler_w1 = INVALID_INDEX; int8_t idx_controler_curr = INVALID_INDEX; int8_t idx_bar_controlerd1 = INVALID_INDEX; int8_t idx_bar_mn1 = INVALID_INDEX; //--- CModificatorOscar mod_oscar(max_risk_to_mod_oscar, initial_risk_percenrt_to_mod, multo_mod_oscar, hora_inicio_ny, min_inicio_ny); //--- CYearFilter year_fil; CWeeklyFilter wekk_fil; //--- const CLossProfitManager* g_loss_profit_manager; CAtrUltraOptimized* atr_pointer_p; CBreakEven break_even(InpMagic, _Symbol); //--- bool NewDay = false; bool CanTrade = true; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Registramos timeframes g_new_bar_manager.GetPosExecute(PERIOD_D1, idx_bar_controlerd1); g_new_bar_manager.GetPosExecute(_Period, idx_controler_curr); g_new_bar_manager.GetPosExecute(PERIOD_W1, idx_controler_w1); g_new_bar_manager.GetPosExecute(PERIOD_MN1, idx_bar_mn1); //--- if(InpModifiedChart) { long chart_id = ChartID(); // Obtén el ID del gráfico actual // Ocultar la cuadrícula ChartSetInteger(chart_id, CHART_SHOW_GRID, false); ChartSetInteger(chart_id, CHART_COLOR_BACKGROUND, C'255,255,255'); // Fondo blanco ChartSetInteger(chart_id, CHART_COLOR_FOREGROUND, clrBlack); // Texto y escalas negras ChartSetInteger(chart_id, CHART_COLOR_CHART_UP, C'38,166,154'); // Velas alcistas color verde azulado ChartSetInteger(chart_id, CHART_COLOR_CHART_DOWN, C'239,83,80'); // Velas bajistas color rojo ChartSetInteger(chart_id, CHART_COLOR_CANDLE_BULL, C'38,166,154'); // Cuerpo de las velas alcistas ChartSetInteger(chart_id, CHART_COLOR_CANDLE_BEAR, C'239,83,80'); // Cuerpo de las velas bajistas ChartSetInteger(chart_id, CHART_COLOR_CHART_LINE, clrDarkSeaGreen); // Línea de tendencia ChartSetInteger(chart_id, CHART_COLOR_VOLUME, C'38,166,154'); // Color de los volúmenes ChartSetInteger(chart_id, CHART_COLOR_BID, C'38,166,154'); // Línea de oferta ChartSetInteger(chart_id, CHART_COLOR_ASK, C'239,83,80'); // Línea de demanda ChartSetInteger(chart_id, CHART_COLOR_LAST, C'156,186,240'); // Último precio ChartSetInteger(chart_id, CHART_COLOR_STOP_LEVEL, C'239,83,80'); // Líneas de stop ChartSetInteger(chart_id, CHART_SHOW_VOLUMES, true); // Actualizar el gráfico ChartRedraw(chart_id); } //--- AtrPtr atr_pointer_p = new CAtrUltraOptimized(); atr_pointer_p.SetVariables(_Period, _Symbol, 0, 14); atr_pointer_p.SetInternalPointer(); //--- if(use_be) { break_even.SetBeByAtr(be_atr_multiplier, be_atr_multiplier_extra, atr_pointer_p); break_even.SetBeByFixedPoints(be_fixed_points_to_put_be, be_fixed_points_extra); break_even.SetBeByRR(be_rr_dbl, be_type_extra_rr, be_extra_points_rr_or_atr_multiplier, atr_pointer_p); break_even.SetInternalPointer(type_break_even); break_even.obj.AddLogFlags(log_level_be); } //--- Sesiones sesion_asia.Create(_Symbol, _Period, 0, 0, true, true, hora_inicio_asia, min_inicio_asia, hora_fin_asia, min_fin_asia, "Session asia"); sesion_asia.SetGrapichStyles(style_rect_actia, color_text_line_rect_asia, width_rect_asia, fill_rect_asia); sesion_asia.Set(width_rect_asia, STYLE_SOLID, color_text_line_rect_asia, color_text_line_rect_asia, color_text_line_rect_asia, draw_session_text_arriba, draw_session_range_only_rect); trading_session.Create(_Symbol, _Period, 0, 0, true, true, inp_hora_inicio, inp_min_inicio, inp_hora_fin, inp_min_fin, InpSessionBaseName); trading_session.SetGrapichStyles(style_line_rect, clr_rect_session, width_sessoin, fill_session); trading_session.SetExtra(inp_clr_lines, inp_clr_lines, style_line_extra, width_sessoin_lines, type_draw_session); //--- Filtro year_fil.Set(enable_Enero, enable_Febrero, enable_Marzo, enable_Abril, enable_Mayo, enable_Junio, enable_Julio, enable_Agosto, enable_Septiembre, enable_Octubre, enable_Noviembre, enable_Diciembre); wekk_fil.Set(enable_Monday, enable_Tuesday, enable_Wednesday, enable_Thursday, enable_Friday, enable_Saturday, enable_Sunday); wekk_fil.OperarCrypto(IsCryptoMarket); //--- Estrategia CAtrUltraOptimized* atr_ultra = new CAtrUltraOptimized(); atr_ultra.SetVariables(PERIOD_CURRENT, _Symbol, 0, 14); atr_ultra.SetInternalPointer(); strategy.AddLogFlags(InpStrategyLogLevel); strategy.SetAtrTP_SL(atr_ultra, InpStrategyAtrMultiplierTp, InpStrategyAtrMultiplierSl); strategy.SetOperateMode(TR_BUY_SELL, (ENUM_TYPE_TP_SL_FIXED)InpStrategyTypeTpSl); strategy.SetTP_SL((InpStrategySlPoint), (InpStrategyTpPoint)); strategy.SetGen(RR_TP, InpStrategyTypeTpSl); strategy.SetNy(hora_inicio_ny, min_inicio_ny); if(InpRmLoteType == Fijo) strategy.FixedLotSize(InpRmLote); //--- Risk management CRiskPointer* manager = new CRiskPointer(InpMagic, InpRmGetMode); manager.SetPropirm(InpRmPropFirmBalance); risk = manager.GetRiskPointer(InpRmRiskMode); risk.AddLogFlags(InpRmLogLevel); risk.SetLote(CreateLotePtr(_Symbol)); // We set the parameters string to_apply = InpRmStrPercentagesToApply, to_modfied = InpRmStrPercentagesToBeReviewed; if(InpRmModeGmlpo == DYNAMIC_GMLPO_FIXED_PARAMETERS) SetDynamicUsingFixedParameters(InpRmBalancePercentageToActivateTheRisk1, InpRmBalancePercentageToActivateTheRisk2, InpRmBalancePercentageToActivateTheRisk3 , InpRmBalancePercentageToActivateTheRisk4, InpRmPercentageToBeModified1, InpRmPercentageToBeModified2, InpRmPercentageToBeModified3, InpRmPercentageToBeModified4 , to_modfied, to_apply); risk.AddLoss(InpRmPercentageOrMoneyMdl, InpRmAppliedPercentagesMdl, InpRmModeCalculationMdl, LP_MDL, true); risk.AddLoss(InpRmPercentageOrMoneyGmlpo, InpRmAppliedPercentagesGmlpo, InpRmModeCalculationGmlpo, LP_GMLPO, true, (InpRmModeGmlpo != NO_DYNAMIC_GMLPO), to_modfied, to_apply); risk.AddLoss(InpRmPercentageOrMoneyMl, InpRmAppliedPercentagesMl, InpRmModeCalculationMl, LP_ML, true); risk.AddLoss(InpRmPercentageOrMoneyMwl, InpRmAppliedPercentagesMwl, InpRmModeCalculationMwl, LP_MWL, true); risk.AddProfit(InpRmPercentageOrMoneyMdp, InpRmAppliedPercentagesMdp, InpRmModeCalculationMdp, LP_MDP, InpRmMdpIsStrict); risk.EndAddProfitLoss(); // Execute this every time we finish setting the maximum losses and profits g_loss_profit_manager = risk.GetLossProfitManager(); //--- if(enable_mod_oscar) risk.AddModificator(mod_oscar); // We finish by adding it account_status.AddItemFast(risk); // We delete the temporary pointer delete manager; //--- We initialize the account account_status.AddLogFlagTicket(InpAccountStatusLogLevel); account_status.AddLogFlags(InpAccountStatusLogLevel); account_status.OnInitEvent(); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- ICTGen_OnDeinitEvent(); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- const datetime time_curr = TimeCurrent(); NewDay = false; g_new_bar_manager.Execute(time_curr); //--- Bloque 1 | Control diario if(CNewBarManager_IsNewBarM1(g_new_bar_manager)) { //--- Nuevo dia if(CNewBarManager_IsNewBar(g_new_bar_manager, idx_bar_controlerd1)) { account_status.OnNewDay(time_curr); NewDay = true; //--- CanTrade = year_fil.IsMonthTrade(); if(!CanTrade) return; //--- CanTrade = wekk_fil.IsDayTrade(); //--- Nueva semana if(CNewBarManager_IsNewBar(g_new_bar_manager, idx_controler_w1)) account_status.OnNewWeek(time_curr); //--- Nuevo mes if(CNewBarManager_IsNewBar(g_new_bar_manager, idx_bar_mn1)) account_status.OnNewMonth(time_curr); } } //--- if(account_status_positions_open) { CAccountStatus_OnTickEvent if(CanTrade) { if(g_loss_profit_manager.MaxLossIsSuperated()) { const ENUM_TYPE_LOSS_PROFIT type = g_loss_profit_manager.GetLastLossSuperatedType(); if(type == LP_ML) { if(InpRmRiskMode == risk_mode_propfirm_dynamic_daiy_loss) { Print("The expert advisor lost the funding test"); } else { Print("Maximum loss exceeded now"); } //--- Remover(); } else if(type == LP_MDL) { Print("Maximum daily loss exceeded now"); } //--- risk.CloseAllPositions(); CanTrade = false; } else if(g_loss_profit_manager.MaxProfitIsSuperated()) { if(g_loss_profit_manager.GetLastProfitSuperatedType() != LP_MDP) return; risk.CloseAllPositions(); Print("Excellent Maximum daily profit achieved"); CanTrade = false; } } } //--- if(use_be) break_even.obj.BreakEven(); //--- if(!CanTrade) // Si se superaron los limites de MDL, o MDP enotnces no CanTrader return; //--- if(CNewBarManager_IsNewBarM1(g_new_bar_manager)) { ICTGen_FuncionOnBarM1(NewDay, time_curr); sesion_asia.OnNewBarM1(); trading_session.OnNewBarM1(); //--- if(CNewBarManager_IsNewBar(g_new_bar_manager, idx_controler_curr)) { strategy.OnNewBar(time_curr); } } } //+------------------------------------------------------------------+ //| TradeTransaction function | //+------------------------------------------------------------------+ void OnTradeTransaction(const MqlTradeTransaction& trans, const MqlTradeRequest& request, const MqlTradeResult& result) { //--- account_status.OnTradeTransactionEvent(trans); } //+------------------------------------------------------------------+