2025-11-26 07:19:36 -05:00
//+------------------------------------------------------------------+
//| 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
/ / + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
//| |
//+------------------------------------------------------------------+
# include "Confirmacion.mqh"
// Source: https://www.youtube.com/watch?v=1gDEl5FxsGA
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-10-23 21:51:38 -05:00
class CEstrategia : public TSN : : CStrategyBase
2025-11-26 07:19:36 -05:00
{
private :
//--- General
datetime m_next_max_espera ;
2026-11-06 15:35:47 -05:00
ENUM_ESTRATEGIA_SENSEI_STATE m_state ;
2025-11-26 07:19:36 -05:00
bool m_operate ;
//--- Htf
ENUM_TIMEFRAMES m_timeframe_htf ;
2026-01-06 06:46:34 -05:00
int8_t m_index_contoler_htf ;
2025-11-26 07:19:36 -05:00
IConfirmacion * m_confirmacion_htf ;
//--- MidTimeframe
ENUM_TIMEFRAMES m_timeframe_mid_tf ;
// Fibbo
2026-11-06 15:35:47 -05:00
TSN : : CFibbo m_fibbo ;
2025-11-26 07:19:36 -05:00
double m_price_fibbo ;
2026-11-06 15:35:47 -05:00
int m_level_fibbo ;
2025-11-26 07:19:36 -05:00
// Espera
int m_max_espera_to_descuento_in_bars ; // Velas en timeframe curr
//--- Timefgrame de entrada
IConfirmacion * m_confirmation_entrada ;
//---
void Clean ( ) ;
void OpenOrder ( ENUM_POSITION_TYPE type ) ;
//---
void ChangeTimeframeConcepts ( ENUM_TIMEFRAMES tf ) ;
public :
2026-11-06 15:35:47 -05:00
CEstrategia ( ulong magic_number_ , string symbol_ , bool draw_fibbo , ENUM_TIMEFRAMES timeframe_ = PERIOD_CURRENT , long chart_id_ = 0 ,
2025-11-26 07:19:36 -05:00
int subwindow_ = 0 , ulong max_deviation_ = NO_MAX_DEVIATION_DEFINED ) ;
~ CEstrategia ( void ) ;
//---
2026-11-06 15:35:47 -05:00
bool SetFibbo ( color clr_fibbo , string fibbo_levels , string fibbo_colors , double fibbo_level_principal = 0.50 ) ;
2025-11-26 07:19:36 -05:00
void SetConfirmations ( IConfirmacion * confirmation_htf , IConfirmacion * confirmaction_entrada ) ;
void Init ( ENUM_TIMEFRAMES tf_mif , ENUM_TIMEFRAMES tf_high , int max_epsera_para_descuento , ENUM_ESTRATEGIA_SENSEI_DIRECCION_IND tpye_dir ) ;
//---
2026-11-06 15:35:47 -05:00
void OnNewBar ( const datetime curr_time ) override final ;
void OnNewWeek ( const datetime curr_time ) override final ;
void OnTick ( const datetime curr_time ) override final { }
//--- Error
static void FormatTrace ( const TSN : : TSNErrorFrame & trace [ ] , int & trace_idx , string & out ) ;
2025-11-26 07:19:36 -05:00
} ;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-11-06 15:35:47 -05:00
CEstrategia : : CEstrategia ( ulong magic_number_ , string symbol_ , bool draw_fibbo , ENUM_TIMEFRAMES timeframe_ = PERIOD_CURRENT , long chart_id_ = 0 ,
2025-11-26 07:19:36 -05:00
int subwindow_ = 0 , ulong max_deviation_ = NO_MAX_DEVIATION_DEFINED )
2026-11-06 15:35:47 -05:00
: CStrategyBase ( magic_number_ , symbol_ , timeframe_ , chart_id_ , subwindow_ , max_deviation_ , " Estrategia sensei " ) , m_fibbo ( draw_fibbo ) ,
m_confirmacion_htf ( NULL ) , m_confirmation_entrada ( NULL ) , m_index_contoler_htf ( NULL ) , m_operate ( true ) ,
m_state ( ESTRATEGIA_SENSEI_STATE_BUSCAR_DIR ) , m_price_fibbo ( 0.00 ) , m_level_fibbo ( -1 ) , m_next_max_espera ( 0 ) // no se llama Clean() aqui: los conceptos globales aun no estan creados
2025-11-26 07:19:36 -05:00
{
2026-02-01 13:11:51 -05:00
CBasicEvents : : RegisterEvent ( & this , BASICEVENT_REG_FLAG_ON_NEW_WEEK ) ;
2025-11-26 07:19:36 -05:00
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CEstrategia : : ~ CEstrategia ( void )
{
2026-02-01 13:11:51 -05:00
if ( CBasicEvents : : IsActive ( ) )
CBasicEvents : : UnregisterEvent ( & this , BASICEVENT_REG_FLAG_ON_NEW_WEEK ) ;
2025-11-26 07:19:36 -05:00
if ( : : CheckPointer ( m_confirmation_entrada ) = = POINTER_DYNAMIC )
delete m_confirmation_entrada ;
if ( : : CheckPointer ( m_confirmacion_htf ) = = POINTER_DYNAMIC )
delete m_confirmacion_htf ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-11-06 15:35:47 -05:00
bool CEstrategia : : SetFibbo ( color clr_fibbo , string fibbo_levels , string fibbo_colors , double fibbo_level_principal = 0.500000 )
{
// estos ya ponen su error en el trace
if ( ! m_fibbo . Create ( m_chart_id , " FibboSensei " , m_subwindow , clr_fibbo , STYLE_SOLID , 1 , " Fibbo " , true ) )
return false ;
if ( ! m_fibbo . InitFibbo ( fibbo_levels , fibbo_colors , STYLE_SOLID , 1 , ' , ' ) )
return false ;
// este no pone error (usa un hashmap de bajo nivel), hace falta que lo hagamos nosotros
if ( ! m_fibbo . GetLevelIndex ( fibbo_level_principal , m_level_fibbo ) )
return TSN : : CErrorTrace : : FailInit < CEstrategia > ( ESTRATEGIA_ERR_FAILED_CALC_LEVEL_IDX , TSN : : CBitsReinterprete : : ToBasic < ulong , double > ( fibbo_level_principal ) ) ;
return true ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static void CEstrategia : : FormatTrace ( const TSN : : TSNErrorFrame & trace [ ] , int & trace_idx , string & out )
2025-11-26 07:19:36 -05:00
{
2026-11-06 15:35:47 -05:00
TSNSTD_ERRMAN_PUSHINI ( out , trace_idx )
switch ( trace [ trace_idx ] . code )
{
case ESTRATEGIA_ERR_NOT :
TSNSTD_ERRMAN_PUSHOUT ( out , " Not error " , trace_idx )
break ;
case ESTRATEGIA_ERR_FAILED_CALC_LEVEL_IDX :
TSNSTD_ERRMAN_PUSHOUT ( out , StringFormat ( " The chosen fibbo level [%.4f] is not one of the fibbo levels (InpStrategyFibboLevels) " ,
TSN : : CBitsReinterprete : : ToBasic < double , ulong > ( trace [ trace_idx ] . info ) ) , trace_idx )
break ;
default :
TSNSTD_ERRMAN_PUSHOUT ( out , " Unknow error " , trace_idx )
break ;
}
2025-11-26 07:19:36 -05:00
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-02-14 17:50:28 -05:00
void CEstrategia : : OnNewWeek ( const datetime curr_time )
2025-11-26 07:19:36 -05:00
{
// Limpieza semanal
g_fvg . DeleteAll ( ) ;
g_ob . DeleteAll ( ) ;
g_zz . DeleteAll ( ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CEstrategia : : SetConfirmations ( IConfirmacion * confirmation_htf , IConfirmacion * confirmaction_entrada )
{
m_confirmacion_htf = confirmation_htf ;
m_confirmation_entrada = confirmaction_entrada ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CEstrategia ::Init ( ENUM_TIMEFRAMES tf_mif , ENUM_TIMEFRAMES tf_high , int max_epsera_para_descuento , ENUM_ESTRATEGIA_SENSEI_DIRECCION_IND tpye_dir )
{
2026-01-06 06:46:34 -05:00
//---
2025-11-26 07:19:36 -05:00
m_timeframe_htf = tf_high ;
m_timeframe_mid_tf = tf_mif ;
m_max_espera_to_descuento_in_bars = max_epsera_para_descuento ;
//---
2026-01-06 06:46:34 -05:00
// Aqui algo.. el HTF siempre debera de ser mayor al timeframe de la estrateiga el current
2025-11-26 07:19:36 -05:00
if ( tpye_dir = = SENSEI_DIR_MANIPULACION_SESIONES )
2026-01-06 06:46:34 -05:00
g_new_bar_manager . GetPosExecute ( m_timeframe , m_index_contoler_htf ) ; // Usamos directament ela funcion para registar el TF
2025-11-26 07:19:36 -05:00
else
2026-01-06 06:46:34 -05:00
g_new_bar_manager . GetPosExecute ( tf_high , m_index_contoler_htf ) ;
2025-11-26 07:19:36 -05:00
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CEstrategia : : Clean ( void )
{
2026-11-06 15:35:47 -05:00
m_state = ESTRATEGIA_SENSEI_STATE_BUSCAR_DIR ;
2025-11-26 07:19:36 -05:00
m_price_fibbo = 0.00 ;
m_next_max_espera = 0 ;
g_ob . SetParo ( ) ;
g_fvg . SetParo ( ) ;
// g_zz.SetParo(); // zz se ejecuta en todo momento
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CEstrategia : : ChangeTimeframeConcepts ( ENUM_TIMEFRAMES tf )
{
g_fvg . ChangeTimeframe ( tf ) ;
g_ob . ChangeTimeframe ( tf ) ;
g_fvg . SetCalculatePrevInNextBar ( ) ;
g_ob . SetCalculatePrevInNextBar ( ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-02-14 17:50:28 -05:00
void CEstrategia : : OnNewBar ( const datetime curr_time )
2025-11-26 07:19:36 -05:00
{
if ( risk . GetPositionsTotal ( ) > 0 )
return ;
//---
if ( g_session_operativa . EnSesion ( ) )
{
//---
if ( g_session_operativa . IsInitSession ( ) )
{
2026-01-06 06:46:34 -05:00
LogInfo ( " Inicio de sesion " , FUNCION_ACTUAL ) ;
2025-11-26 07:19:36 -05:00
ChangeTimeframeConcepts ( m_timeframe_htf ) ;
m_operate = true ;
}
//---
if ( ! m_operate )
return ; // No ejeuctamos nada
//---
g_fvg . OnNewBar ( ) ;
g_ob . OnNewBar ( ) ;
//---
2026-11-06 15:35:47 -05:00
do
2025-11-26 07:19:36 -05:00
{
2026-11-06 15:35:47 -05:00
switch ( m_state )
2025-11-26 07:19:36 -05:00
{
2026-11-06 15:35:47 -05:00
case ESTRATEGIA_SENSEI_STATE_BUSCAR_DIR :
2025-11-26 07:19:36 -05:00
{
2026-11-06 15:35:47 -05:00
// Importnate descomentamos debido a que;
// Dado queestamos segurmos que no habra "colgamiento" para empeozae
// OnNewBar se jecuta cada M3 current mismo perido que m_confirmation_entrada asi que por mas que este listo para entener
// Esperara una vela para limpiar data previa por lo que no quedara "data colgada" ademas otra razon es que solo llaamsmo a una vez
// SizeAlcista y SizeBajistas y par ala siutiente llamada si o si es un diferte "timestap" no el mismo..
// Ahora cuando SI LLAMAR este caos: digmaos que OnNEWbAR DE AQUI SE ejeucta m1 entonces luego de esto busco doble mtiigaicon de fvg o cosas que esten
// En la misma insurccion o conseuticaaos en este caso si el timeframel dle ob e smaytor entonce quedaria "colgado" pro lqo ei la siugietne codnicon
// Se elualria como TRUE cuando no lo es ahi si vale la pena controlar la arptuira de las velas
// if(true /*CNewBarManager_IsNewBar(g_new_bar_manager, m_index_contoler_htf)*/) // OB-LOWHIGH-FVG (NO SABEMOS NO ESTAMOS SEGUROs)
// {
// }
//---
if ( m_confirmacion_htf . ConfirmacionCompra ( ) )
{
LogInfo ( " Direccion detectada: compra " , FUNCION_ACTUAL ) ;
m_next_max_espera = curr_time + ( m_period_in_seconds * m_max_espera_to_descuento_in_bars ) ;
//---
// Fibbo de compra
: : SymbolInfoTick ( m_symbol , m_tick ) ;
const Swings swing = g_zz . GetSwingHighMasCeracanoPorPrecioYTime ( m_tick . bid , SWING_MAYOR_A_TARGET_PRICE ) ;
const double minimo = : : iLow ( m_symbol , m_timeframe_mid_tf , : : iLowest ( m_symbol , m_timeframe_mid_tf , MODE_LOW , : : iBarShift ( m_symbol , m_timeframe_mid_tf , swing . time ) , 0 ) ) ;
//Print(minimo);
m_fibbo . Move ( swing . time , m_tick . time , swing . price , minimo ) ;
m_price_fibbo = m_fibbo . GetLevelPrice ( m_level_fibbo ) ;
//---
ChangeTimeframeConcepts ( m_timeframe ) ; // Timefrmae de entrada
m_state = ESTRATEGIA_SENSEI_STATE_BUSCAR_DESCUENTO_COMPRA ;
continue ; // "al toque" sale a laa siuginte (Esto para uqe sea "fiel" a como estaba antes)
}
else
if ( m_confirmacion_htf . ConfirmacionVenta ( ) )
{
m_next_max_espera = curr_time + ( m_period_in_seconds * m_max_espera_to_descuento_in_bars ) ;
//---
// Fibob de venta
: : SymbolInfoTick ( m_symbol , m_tick ) ;
const Swings swing = g_zz . GetSwingLowMasCeracanoPorPrecioYTime ( m_tick . bid , SWING_MENOR_A_TARGET_PRICE ) ;
const double maximo = : : iHigh ( m_symbol , m_timeframe_mid_tf , : : iHighest ( m_symbol , m_timeframe_mid_tf , MODE_HIGH , : : iBarShift ( m_symbol , m_timeframe_mid_tf , swing . time ) , 0 ) ) ;
m_fibbo . Move ( swing . time , m_tick . time , maximo , swing . price ) ;
m_price_fibbo = m_fibbo . GetLevelPrice ( m_level_fibbo ) ;
//---
ChangeTimeframeConcepts ( m_timeframe ) ; // Timefrmae de entrada
LogInfo ( " Direccion detectada: venta " , FUNCION_ACTUAL ) ;
m_state = ESTRATEGIA_SENSEI_STATE_BUSCAR_DESCUENTO_VENTA ;
continue ; // "al toque" sale a laa siuginte (Esto para uqe sea "fiel" a como estaba antes)
}
break ;
2025-11-26 07:19:36 -05:00
}
2026-11-06 15:35:47 -05:00
//--- Ya hay direccion de compra: esperamos que el precio este en descuento (concepto MID-TF)
case ESTRATEGIA_SENSEI_STATE_BUSCAR_DESCUENTO_COMPRA :
2025-11-26 07:19:36 -05:00
{
2026-11-06 15:35:47 -05:00
if ( g_zz . IsNewBarConcept ( ) ) // El desucuento siempre sera el concepto MID-TF
{
// Actulizacion del fibbo y vemos si estamos en descuento
m_fibbo . UpdateTime2 ( curr_time ) ;
: : SymbolInfoTick ( m_symbol , m_tick ) ;
if ( m_price_fibbo > m_tick . bid ) // Bid en desucneto
{
m_state = ESTRATEGIA_SENSEI_STATE_BUSCAR_ENTRADA_COMPRA ; // la entrada se busca en la siguiente llamada
LogInfo ( " Precio en descuento " , FUNCION_ACTUAL ) ;
}
}
// Maxima espera (se evalua aunque en esta misma llamada ya se haya llegado al descuento, igual que antes)
if ( curr_time > m_next_max_espera )
2025-11-26 07:19:36 -05:00
{
2026-11-06 15:35:47 -05:00
m_state = ESTRATEGIA_SENSEI_STATE_BUSCAR_DIR ; // Reinicio
LogInfo ( " Max espera para fibbo superada " , FUNCION_ACTUAL ) ;
// Aqui podemos hacer dos cosas o cambiar de timeframe
m_operate = false ;
// O calendar el trade m_operate = false
2025-11-26 07:19:36 -05:00
}
2026-11-06 15:35:47 -05:00
break ;
2025-11-26 07:19:36 -05:00
}
2026-11-06 15:35:47 -05:00
//--- Ya hay direccion de venta: esperamos que el precio este en premium
case ESTRATEGIA_SENSEI_STATE_BUSCAR_DESCUENTO_VENTA :
2025-11-26 07:19:36 -05:00
{
2026-11-06 15:35:47 -05:00
if ( g_zz . IsNewBarConcept ( ) )
{
m_fibbo . UpdateTime2 ( curr_time ) ;
: : SymbolInfoTick ( m_symbol , m_tick ) ;
if ( m_tick . bid > m_price_fibbo ) // Bid en premiun
{
m_state = ESTRATEGIA_SENSEI_STATE_BUSCAR_ENTRADA_VENTA ;
LogInfo ( " Precio en premiun " , FUNCION_ACTUAL ) ;
}
}
if ( curr_time > m_next_max_espera )
2025-11-26 07:19:36 -05:00
{
2026-11-06 15:35:47 -05:00
m_state = ESTRATEGIA_SENSEI_STATE_BUSCAR_DIR ; // Reinicio
LogInfo ( " Max espera para fibbo superada " , FUNCION_ACTUAL ) ;
m_operate = false ;
2025-11-26 07:19:36 -05:00
}
2026-11-06 15:35:47 -05:00
break ;
2025-11-26 07:19:36 -05:00
}
2026-11-06 15:35:47 -05:00
//--- Entrada
case ESTRATEGIA_SENSEI_STATE_BUSCAR_ENTRADA_COMPRA :
{
if ( m_confirmation_entrada . ConfirmacionCompra ( ) )
OpenOrder ( POSITION_TYPE_BUY ) ;
break ;
}
case ESTRATEGIA_SENSEI_STATE_BUSCAR_ENTRADA_VENTA :
2025-11-26 07:19:36 -05:00
{
2026-11-06 15:35:47 -05:00
if ( m_confirmation_entrada . ConfirmacionVenta ( ) )
OpenOrder ( POSITION_TYPE_SELL ) ;
break ;
2025-11-26 07:19:36 -05:00
}
2026-11-06 15:35:47 -05:00
default :
break ;
}
//--- sale siempre
break ;
2025-11-26 07:19:36 -05:00
}
2026-11-06 15:35:47 -05:00
while ( true ) ;
2025-11-26 07:19:36 -05:00
}
else
if ( g_session_operativa . IsEndSession ( ) ) // Session finalizada
{
Clean ( ) ;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CEstrategia : : OpenOrder ( ENUM_POSITION_TYPE type )
{
: : SymbolInfoTick ( m_symbol , m_tick ) ;
if ( type = = POSITION_TYPE_BUY )
{
double entry = m_tick . ask ;
double sl = GetSL ( entry , type , m_tick . time ) ;
double tp = GetTP ( entry , type , m_tick . time ) ;
2026-11-01 22:12:14 -05:00
risk . SetStopLoss ( m_symbol , entry - sl ) ;
2025-11-26 07:19:36 -05:00
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 ;
double sl = GetSL ( entry , type , m_tick . time ) ;
double tp = GetTP ( entry , type , m_tick . time ) ;
2026-11-01 22:12:14 -05:00
risk . SetStopLoss ( m_symbol , sl - entry ) ;
2025-11-26 07:19:36 -05:00
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 " ) ;
}
2026-01-06 06:46:34 -05:00
m_operate = false ;
2025-11-26 07:19:36 -05:00
Clean ( ) ;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+