//+------------------------------------------------------------------+ //| Fimathe_Trend_EA.mq5 | //| Baseado na Técnica Fimathe de Marcelo Ferreira | //| Expert Advisor para MetaTrader 5 | //+------------------------------------------------------------------+ #property copyright "Fimathe Trend EA" #property link "" #property version "1.00" #property description "EA profissional baseado na técnica Fimathe de Marcelo Ferreira" #property strict /* ================================================================================ CABEÇALHO — REGRAS DA TÉCNICA FIMATHE (Marcelo Ferreira) ================================================================================ FUNDAMENTOS: ┌──────────────────────────────────────────────────────────────────┐ │ 1. TENDÊNCIA É SOBERANA │ │ - Opere SEMPRE a favor da tendência principal (TF superior) │ │ - Alta : sequência de topos e fundos ASCENDENTES │ │ - Baixa : sequência de topos e fundos DESCENDENTES │ │ - Jamais entre contra a tendência principal identificada │ ├──────────────────────────────────────────────────────────────────┤ │ 2. ESTRUTURA DE MERCADO (Canais / Zonas) │ │ - Máximas e mínimas recentes formam suportes e resistências │ │ - O preço respeita e reage a estruturas formadas anteriormente │ │ - Breakout confirma novo movimento direcional │ ├──────────────────────────────────────────────────────────────────┤ │ 3. CORREÇÕES FIBONACCI │ │ - Após o impulso, aguardar a correção (pullback) │ │ - Níveis principais de entrada: 0.618 e 0.786 │ │ - A correção deve respeitar a estrutura anterior │ │ - Não entrar antes do preço atingir a zona Fibonacci │ ├──────────────────────────────────────────────────────────────────┤ │ 4. CONFIRMAÇÃO DE ENTRADA (corpo da vela) │ │ - Aguardar FECHAMENTO do corpo da vela na direção da tendência │ │ - Compra : vela de alta com corpo relevante │ │ - Venda : vela de baixa com corpo relevante │ │ - Evitar doji e velas de indecisão │ ├──────────────────────────────────────────────────────────────────┤ │ 5. GESTÃO DE RISCO │ │ - Stop Loss ABAIXO da mínima do pullback (compra) │ │ - Stop Loss ACIMA da máxima do pullback (venda) │ │ - Take Profit em próxima estrutura ou % do capital │ │ - Risco fixo por operação (% do saldo) │ ├──────────────────────────────────────────────────────────────────┤ │ 6. HORÁRIO E LIQUIDEZ │ │ - Priorizar horários de maior volume │ │ - Londres : 08h–12h | Nova York : 13h–17h (hora servidor) │ │ - Evitar entrada em horários de baixo volume │ ├──────────────────────────────────────────────────────────────────┤ │ 7. DISCIPLINA OPERACIONAL │ │ - Máximo 1 posição aberta por vez │ │ - Não reentrar em sequência imediata após stop │ │ - Aguardar novo setup completo antes de reentrar │ └──────────────────────────────────────────────────────────────────┘ FLUXO DE DECISÃO: Tendência TF Superior → Impulso Identificado → Aguardar Pullback → Zona Fibonacci (0.618 / 0.786) → Confirmação de Vela → Entrada → Gestão com SL estrutural + TP percentual + Trailing/Breakeven ================================================================================ */ #include #include #include //============================================================================= // INPUTS //============================================================================= sinput string sep_cap = "════ GESTÃO DE CAPITAL ════"; input bool UseMoneyMgmt = true; // Usar gestão de capital por risco input double RiskPercent = 1.0; // % do saldo a arriscar por operação input double TargetPct = 2.0; // % de lucro alvo por operação input double LotSize = 0.01; // Lote fixo (se gestão desativada) sinput string sep_tf = "════ TIMEFRAMES ════"; input ENUM_TIMEFRAMES TrendTF = PERIOD_H1; // Timeframe de identificação da tendência input ENUM_TIMEFRAMES OperTF = PERIOD_M5; // Timeframe operacional de entrada sinput string sep_fib = "════ FIBONACCI ════"; input double FibLvl1 = 0.618; // Nível Fibonacci 1 (entrada principal) input double FibLvl2 = 0.786; // Nível Fibonacci 2 (entrada secundária) input double FibTolerance = 0.015; // Tolerância da zona Fib (fração do range) sinput string sep_struct = "════ ESTRUTURA / SETUP ════"; input int StructBars = 35; // Barras para detectar estrutura de swing input int MinBodyPts = 60; // Pontos mínimos no corpo da vela de conf. input bool NeedBodyClose = true; // Exigir corpo mínimo na vela de confirmação sinput string sep_sl = "════ STOP LOSS ════"; input bool UseATR = true; // Calcular SL via ATR input int ATRPeriod = 14; // Período do ATR input double ATRMult = 2.0; // Multiplicador do ATR para o SL input double SLBuffer = 150.0; // Buffer além da estrutura em pontos (sem ATR) sinput string sep_be = "════ BREAKEVEN / TRAILING ════"; input bool UseBreakEven = true; // Ativar breakeven automático input double BEPct = 0.5; // % de lucro no saldo para ativar BE input bool UseTrailing = true; // Ativar trailing stop automático input double TSPct = 1.0; // % de lucro no saldo para ativar trailing input double TSPoints = 250.0; // Distância do trailing em pontos sinput string sep_time = "════ HORÁRIO ════"; input bool UseTimeFilter = true; // Filtrar horário de operação input int StartHour = 9; // Hora de início (servidor) input int StartMin = 0; // Minuto de início input int EndHour = 18; // Hora de fim (servidor) input int EndMin = 0; // Minuto de fim input bool CloseAtEnd = false; // Fechar posições ao atingir hora fim sinput string sep_id = "════ IDENTIFICAÇÃO ════"; input int MagicNumber = 202536; // Número mágico input string EAComment = "Fimathe Trend EA"; // Comentário nas ordens //============================================================================= // ENUMERAÇÕES //============================================================================= enum ENUM_FTREND { FT_UP = 1, // Tendência de Alta FT_DOWN = -1, // Tendência de Baixa FT_NEUTRAL = 0 // Sem tendência definida }; //============================================================================= // ESTRUTURA DO SETUP FIMATHE //============================================================================= struct SSetup { bool valid; bool isBuy; double entry; double sl; double tp; double lots; double swHigh; double swLow; double fib618; double fib786; }; //============================================================================= // CLASSE: GERENCIADOR DE TRADES //============================================================================= class CManager { private: CTrade m_trade; CPositionInfo m_pos; CAccountInfo m_acc; int m_magic; string m_sym; string m_comment; public: CManager(int magic, string sym, string comment) { m_magic = magic; m_sym = sym; m_comment = comment; m_trade.SetExpertMagicNumber(magic); m_trade.SetDeviationInPoints(30); m_trade.SetTypeFilling(ORDER_FILLING_FOK); m_trade.LogLevel(LOG_LEVEL_ERRORS); } bool HasPos(ENUM_POSITION_TYPE type) { for(int i = PositionsTotal()-1; i >= 0; i--) { if(!m_pos.SelectByIndex(i)) continue; if(m_pos.Symbol() == m_sym && m_pos.Magic() == m_magic && m_pos.PositionType() == type) return true; } return false; } bool HasAny() { return HasPos(POSITION_TYPE_BUY) || HasPos(POSITION_TYPE_SELL); } bool Buy(double lots, double sl, double tp) { int d = (int)SymbolInfoInteger(m_sym, SYMBOL_DIGITS); double ask = SymbolInfoDouble(m_sym, SYMBOL_ASK); bool ok = m_trade.Buy(lots, m_sym, ask, NormalizeDouble(sl,d), NormalizeDouble(tp,d), m_comment); if(!ok) Print("[Fimathe] BUY falhou: ", m_trade.ResultRetcode(), " - ", m_trade.ResultRetcodeDescription()); else Print("[Fimathe] BUY aberto | Lots=",lots," SL=",NormalizeDouble(sl,d)," TP=",NormalizeDouble(tp,d)); return ok; } bool Sell(double lots, double sl, double tp) { int d = (int)SymbolInfoInteger(m_sym, SYMBOL_DIGITS); double bid = SymbolInfoDouble(m_sym, SYMBOL_BID); bool ok = m_trade.Sell(lots, m_sym, bid, NormalizeDouble(sl,d), NormalizeDouble(tp,d), m_comment); if(!ok) Print("[Fimathe] SELL falhou: ", m_trade.ResultRetcode(), " - ", m_trade.ResultRetcodeDescription()); else Print("[Fimathe] SELL aberto | Lots=",lots," SL=",NormalizeDouble(sl,d)," TP=",NormalizeDouble(tp,d)); return ok; } // Breakeven: move SL para o preço de entrada após X% de lucro no saldo void DoBreakEven(double actPct) { double bal = m_acc.Balance(); if(bal <= 0) return; int d = (int)SymbolInfoInteger(m_sym, SYMBOL_DIGITS); double spread = (double)SymbolInfoInteger(m_sym, SYMBOL_SPREAD) * SymbolInfoDouble(m_sym, SYMBOL_POINT); for(int i = PositionsTotal()-1; i >= 0; i--) { if(!m_pos.SelectByIndex(i)) continue; if(m_pos.Symbol() != m_sym || m_pos.Magic() != m_magic) continue; if((m_pos.Profit() / bal) * 100.0 < actPct) continue; double op = m_pos.PriceOpen(); double csl = m_pos.StopLoss(); if(m_pos.PositionType() == POSITION_TYPE_BUY) { double nsl = NormalizeDouble(op + spread, d); if(nsl > csl) { if(m_trade.PositionModify(m_pos.Ticket(), nsl, m_pos.TakeProfit())) Print("[Fimathe] Breakeven BUY ativado | SL=", nsl); } } else { double nsl = NormalizeDouble(op - spread, d); if(csl == 0.0 || nsl < csl) { if(m_trade.PositionModify(m_pos.Ticket(), nsl, m_pos.TakeProfit())) Print("[Fimathe] Breakeven SELL ativado | SL=", nsl); } } } } // Trailing stop: segue o preço após X% de lucro no saldo void DoTrailing(double actPct, double stepPts) { double bal = m_acc.Balance(); if(bal <= 0) return; double pt = SymbolInfoDouble(m_sym, SYMBOL_POINT); int d = (int)SymbolInfoInteger(m_sym, SYMBOL_DIGITS); double step = stepPts * pt; for(int i = PositionsTotal()-1; i >= 0; i--) { if(!m_pos.SelectByIndex(i)) continue; if(m_pos.Symbol() != m_sym || m_pos.Magic() != m_magic) continue; if((m_pos.Profit() / bal) * 100.0 < actPct) continue; double csl = m_pos.StopLoss(); if(m_pos.PositionType() == POSITION_TYPE_BUY) { double bid = SymbolInfoDouble(m_sym, SYMBOL_BID); double nsl = NormalizeDouble(bid - step, d); if(nsl > csl) m_trade.PositionModify(m_pos.Ticket(), nsl, m_pos.TakeProfit()); } else { double ask = SymbolInfoDouble(m_sym, SYMBOL_ASK); double nsl = NormalizeDouble(ask + step, d); if(csl == 0.0 || nsl < csl) m_trade.PositionModify(m_pos.Ticket(), nsl, m_pos.TakeProfit()); } } } void CloseAll() { for(int i = PositionsTotal()-1; i >= 0; i--) { if(!m_pos.SelectByIndex(i)) continue; if(m_pos.Symbol() == m_sym && m_pos.Magic() == m_magic) m_trade.PositionClose(m_pos.Ticket()); } } }; //============================================================================= // VARIÁVEIS GLOBAIS //============================================================================= CManager* g_mgr = NULL; CAccountInfo g_acc; int g_hATR = INVALID_HANDLE; int g_hEMA20T = INVALID_HANDLE; // EMA 20 no TF de tendência int g_hEMA50T = INVALID_HANDLE; // EMA 50 no TF de tendência int g_hEMA200T = INVALID_HANDLE; // EMA 200 no TF de tendência datetime g_lastBar = 0; int g_digits = 5; double g_point = 0.00001; //============================================================================= // UTILITÁRIOS //============================================================================= bool IsNewBar() { datetime t[]; ArraySetAsSeries(t, true); if(CopyTime(_Symbol, OperTF, 0, 1, t) < 1) return false; if(t[0] == g_lastBar) return false; g_lastBar = t[0]; return true; } bool InTradingHours() { if(!UseTimeFilter) return true; MqlDateTime dt; TimeToStruct(TimeCurrent(), dt); int now = dt.hour * 60 + dt.min; int start = StartHour * 60 + StartMin; int end = EndHour * 60 + EndMin; if(start <= end) return (now >= start && now < end); return (now >= start || now < end); } bool PastEndTime() { if(!CloseAtEnd) return false; MqlDateTime dt; TimeToStruct(TimeCurrent(), dt); int now = dt.hour * 60 + dt.min; int end = EndHour * 60 + EndMin; return (now >= end); } double NormLots(double lots) { double mn = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); double mx = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); double st = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP); if(st <= 0) st = 0.01; lots = MathFloor(lots / st) * st; return NormalizeDouble(MathMax(mn, MathMin(mx, lots)), 2); } // Calcula lote por risco percentual sobre o saldo double CalcLots(double slDist) { if(!UseMoneyMgmt) return NormLots(LotSize); if(slDist <= 0) return NormLots(LotSize); double bal = g_acc.Balance(); double risk = bal * (RiskPercent / 100.0); double ts = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE); double tv = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE); if(ts <= 0 || tv <= 0) return NormLots(LotSize); double lpl = (slDist / ts) * tv; // perda por lote if(lpl <= 0) return NormLots(LotSize); return NormLots(risk / lpl); } // Calcula Take Profit baseado em % do saldo para o lote especificado double CalcTP(double entry, bool buy, double lots) { if(lots <= 0) return 0; double bal = g_acc.Balance(); double target = bal * (TargetPct / 100.0); double ts = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE); double tv = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE); if(ts <= 0 || tv <= 0) return 0; double tpDist = (target / (lots * tv)) * ts; return NormalizeDouble(buy ? entry + tpDist : entry - tpDist, g_digits); } double GetATR() { double buf[]; ArraySetAsSeries(buf, true); if(CopyBuffer(g_hATR, 0, 1, 1, buf) < 1) return 0; return buf[0]; } //============================================================================= // IDENTIFICAÇÃO DE TENDÊNCIA (TF Superior) //============================================================================= /* Critérios combinados: 1. Estrutura de topos/fundos (Higher High + Higher Low = alta; Lower High + Lower Low = baixa) 2. Alinhamento das EMAs 20/50/200 Tendência confirmada quando ambos os critérios concordam. Se apenas estrutura ou apenas EMAs disponíveis, usa o que está disponível. */ ENUM_FTREND IdentifyTrend() { // --- EMAs --- double ema20[], ema50[], ema200[]; ArraySetAsSeries(ema20, true); ArraySetAsSeries(ema50, true); ArraySetAsSeries(ema200, true); bool emasOk = (CopyBuffer(g_hEMA20T, 0, 0, 3, ema20) >= 3 && CopyBuffer(g_hEMA50T, 0, 0, 3, ema50) >= 3 && CopyBuffer(g_hEMA200T, 0, 0, 3, ema200) >= 3); // --- Dados OHLC do TF de tendência --- MqlRates tr[]; ArraySetAsSeries(tr, true); int needed = StructBars + 10; bool ratesOk = (CopyRates(_Symbol, TrendTF, 0, needed, tr) >= needed); // --- Análise de estrutura (topos e fundos locais) --- double h1 = 0, h2 = 0, l1 = DBL_MAX, l2 = DBL_MAX; int hc = 0, lc = 0; if(ratesOk) { for(int i = 2; i < StructBars - 2; i++) { if(hc < 2) { if(tr[i].high > tr[i-1].high && tr[i].high > tr[i+1].high && tr[i].high > tr[i-2].high && tr[i].high > tr[i+2].high) { if(hc == 0) h1 = tr[i].high; else h2 = tr[i].high; hc++; } } if(lc < 2) { if(tr[i].low < tr[i-1].low && tr[i].low < tr[i+1].low && tr[i].low < tr[i-2].low && tr[i].low < tr[i+2].low) { if(lc == 0) l1 = tr[i].low; else l2 = tr[i].low; lc++; } } if(hc >= 2 && lc >= 2) break; } } bool structUp = (hc >= 2 && lc >= 2 && h1 > h2 && l1 > l2); bool structDown = (hc >= 2 && lc >= 2 && h1 < h2 && l1 < l2); bool emaUp = emasOk && (ema20[0] > ema50[0] && ema50[0] > ema200[0]); bool emaDown = emasOk && (ema20[0] < ema50[0] && ema50[0] < ema200[0]); // Confirmação forte (estrutura + EMA) if(structUp && emaUp) return FT_UP; if(structDown && emaDown) return FT_DOWN; // Confirmação parcial if(structUp && !structDown) return FT_UP; if(structDown && !structUp) return FT_DOWN; if(emaUp && !emaDown) return FT_UP; if(emaDown && !emaUp) return FT_DOWN; return FT_NEUTRAL; } //============================================================================= // DETECÇÃO DO SETUP FIMATHE (Pullback → Fibonacci → Confirmação) //============================================================================= /* COMPRA (uptrend): - Localizar swing high e swing low recentes no TF operacional - O swing high deve ser MAIS RECENTE que o swing low (impulso de alta concluído) - Preço recuou do topo e está na zona Fibonacci (0.618–0.786 do range) - Vela confirmação: bullish, corpo >= MinBodyPts, fechando acima da mínima da zona - SL: abaixo do swing low + buffer | TP: % do saldo VENDA (downtrend): - O swing low deve ser MAIS RECENTE que o swing high (impulso de baixa concluído) - Preço recuperou do fundo e está na zona Fibonacci (0.618–0.786 do range) - Vela confirmação: bearish, corpo >= MinBodyPts, fechando abaixo do máximo da zona - SL: acima do swing high + buffer | TP: % do saldo */ SSetup DetectSetup(ENUM_FTREND trend) { SSetup s; ZeroMemory(s); s.valid = false; if(trend == FT_NEUTRAL) return s; // Barras do TF operacional (índice 0 = barra em formação, excluída) MqlRates r[]; ArraySetAsSeries(r, true); if(CopyRates(_Symbol, OperTF, 0, StructBars + 5, r) < StructBars + 5) return s; // Localizar swing high e swing low no lookback (barras 1..StructBars) double swH = 0, swL = DBL_MAX; int iH = 0, iL = 0; for(int i = 1; i <= StructBars; i++) { if(r[i].high > swH) { swH = r[i].high; iH = i; } if(r[i].low < swL) { swL = r[i].low; iL = i; } } if(swH <= 0 || swL >= DBL_MAX || swH <= swL) return s; double range = swH - swL; // Exigir range mínimo de 50 pontos para evitar noise if(range < 50.0 * g_point) return s; // Níveis Fibonacci double fib618_buy = swH - range * FibLvl1; // zona suporte Fib para compra double fib786_buy = swH - range * FibLvl2; double fib618_sel = swL + range * FibLvl1; // zona resistência Fib para venda double fib786_sel = swL + range * FibLvl2; double tol = range * FibTolerance; // Vela de confirmação = barra 1 (último candle fechado) double cClose = r[1].close; double cOpen = r[1].open; double body = MathAbs(cClose - cOpen); bool okBody = (!NeedBodyClose || body >= (double)MinBodyPts * g_point); double atr = GetATR(); //--- SETUP DE COMPRA --- // iH < iL: swing high mais recente → impulso de alta concluído, agora em correção if(trend == FT_UP && iH < iL && iH >= 2) { bool inZone = (cClose >= fib786_buy - tol && cClose <= fib618_buy + tol); bool bullish = (cClose > cOpen); // vela bullish bool turning = (cClose > r[2].close); // preço retomando a subida if(inZone && bullish && okBody && turning) { s.valid = true; s.isBuy = true; s.swHigh = swH; s.swLow = swL; s.fib618 = fib618_buy; s.fib786 = fib786_buy; s.entry = SymbolInfoDouble(_Symbol, SYMBOL_ASK); s.sl = UseATR && atr > 0 ? s.entry - atr * ATRMult : swL - SLBuffer * g_point; s.sl = NormalizeDouble(s.sl, g_digits); s.lots = CalcLots(s.entry - s.sl); s.tp = CalcTP(s.entry, true, s.lots); } } //--- SETUP DE VENDA --- // iL < iH: swing low mais recente → impulso de baixa concluído, agora em correção if(trend == FT_DOWN && iL < iH && iL >= 2) { bool inZone = (cClose <= fib786_sel + tol && cClose >= fib618_sel - tol); bool bearish = (cClose < cOpen); bool turning = (cClose < r[2].close); if(inZone && bearish && okBody && turning) { s.valid = true; s.isBuy = false; s.swHigh = swH; s.swLow = swL; s.fib618 = fib618_sel; s.fib786 = fib786_sel; s.entry = SymbolInfoDouble(_Symbol, SYMBOL_BID); s.sl = UseATR && atr > 0 ? s.entry + atr * ATRMult : swH + SLBuffer * g_point; s.sl = NormalizeDouble(s.sl, g_digits); s.lots = CalcLots(s.sl - s.entry); s.tp = CalcTP(s.entry, false, s.lots); } } return s; } //============================================================================= // EXECUÇÃO DO SETUP //============================================================================= void ExecuteSetup(SSetup &s) { if(!s.valid || s.lots <= 0) return; // Verificar distância mínima de stop exigida pelo broker double minStop = (double)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * SymbolInfoDouble(_Symbol, SYMBOL_POINT); if(s.isBuy) { if(g_mgr.HasPos(POSITION_TYPE_BUY)) { Print("[Fimathe] Já existe BUY aberto. Ignorando."); return; } double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); if(ask - s.sl < minStop) { Print("[Fimathe] SL BUY muito próximo. Ignorando."); return; } s.entry = ask; s.tp = CalcTP(ask, true, s.lots); g_mgr.Buy(s.lots, s.sl, s.tp); } else { if(g_mgr.HasPos(POSITION_TYPE_SELL)) { Print("[Fimathe] Já existe SELL aberto. Ignorando."); return; } double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); if(s.sl - bid < minStop) { Print("[Fimathe] SL SELL muito próximo. Ignorando."); return; } s.entry = bid; s.tp = CalcTP(bid, false, s.lots); g_mgr.Sell(s.lots, s.sl, s.tp); } } //============================================================================= // OnInit //============================================================================= int OnInit() { if(StructBars < 10) { Alert("[Fimathe] StructBars deve ser >= 10!"); return INIT_PARAMETERS_INCORRECT; } if(RiskPercent <= 0 || RiskPercent > 20) { Alert("[Fimathe] RiskPercent deve estar entre 0.1 e 20!"); return INIT_PARAMETERS_INCORRECT; } if(TargetPct <= 0) { Alert("[Fimathe] TargetPct deve ser > 0!"); return INIT_PARAMETERS_INCORRECT; } g_digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); g_point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); g_mgr = new CManager(MagicNumber, _Symbol, EAComment); if(g_mgr == NULL) { Print("[Fimathe] Falha ao criar CManager!"); return INIT_FAILED; } g_hEMA20T = iMA(_Symbol, TrendTF, 20, 0, MODE_EMA, PRICE_CLOSE); g_hEMA50T = iMA(_Symbol, TrendTF, 50, 0, MODE_EMA, PRICE_CLOSE); g_hEMA200T = iMA(_Symbol, TrendTF, 200, 0, MODE_EMA, PRICE_CLOSE); g_hATR = iATR(_Symbol, OperTF, ATRPeriod); if(g_hEMA20T == INVALID_HANDLE || g_hEMA50T == INVALID_HANDLE || g_hEMA200T == INVALID_HANDLE || g_hATR == INVALID_HANDLE) { Print("[Fimathe] Falha ao criar indicadores!"); return INIT_FAILED; } Print("════════════════════════════════════════════════"); Print(" Fimathe Trend EA — Iniciado com sucesso!"); Print(" Símbolo : ", _Symbol); Print(" TF Tendência : ", EnumToString(TrendTF)); Print(" TF Operac. : ", EnumToString(OperTF)); Print(" Gestão Cap. : ", UseMoneyMgmt ? "Sim — Risco=" + DoubleToString(RiskPercent,1) + "% / Alvo=" + DoubleToString(TargetPct,1) + "%" : "Não — Lote fixo=" + DoubleToString(LotSize,2)); Print(" Fib Levels : ", FibLvl1, " / ", FibLvl2); Print(" Magic : ", MagicNumber); Print("════════════════════════════════════════════════"); return INIT_SUCCEEDED; } //============================================================================= // OnDeinit //============================================================================= void OnDeinit(const int reason) { if(CloseAtEnd && g_mgr != NULL) g_mgr.CloseAll(); if(g_hEMA20T != INVALID_HANDLE) IndicatorRelease(g_hEMA20T); if(g_hEMA50T != INVALID_HANDLE) IndicatorRelease(g_hEMA50T); if(g_hEMA200T != INVALID_HANDLE) IndicatorRelease(g_hEMA200T); if(g_hATR != INVALID_HANDLE) IndicatorRelease(g_hATR); if(g_mgr != NULL) { delete g_mgr; g_mgr = NULL; } Comment(""); Print("[Fimathe] EA desativado. Razão: ", reason); } //============================================================================= // OnTick — Lógica principal //============================================================================= void OnTick() { if(g_mgr == NULL) return; // Gestão contínua a cada tick (trailing e breakeven) if(UseBreakEven) g_mgr.DoBreakEven(BEPct); if(UseTrailing) g_mgr.DoTrailing(TSPct, TSPoints); // Fechar ao atingir hora fim if(PastEndTime()) { g_mgr.CloseAll(); Comment("Fimathe Trend EA | Horário encerrado — posições fechadas"); return; } // Processar apenas no fechamento de cada nova barra if(!IsNewBar()) return; // Verificar janela de horário if(!InTradingHours()) { Comment("Fimathe Trend EA | Fora do horário | ", StartHour, ":", StringFormat("%02d", StartMin), " — ", EndHour, ":", StringFormat("%02d", EndMin)); return; } // 1) Identificar tendência principal no TF superior ENUM_FTREND trend = IdentifyTrend(); string tStr = (trend == FT_UP) ? "ALTA ▲" : (trend == FT_DOWN) ? "BAIXA ▼" : "NEUTRA ●"; if(trend == FT_NEUTRAL) { Comment("Fimathe Trend EA | Tendência: NEUTRA — aguardando definição"); return; } // 2) Se há posição aberta, apenas gerir (trailing/BE já aplicados acima) if(g_mgr.HasAny()) { Comment("Fimathe Trend EA | Tendência: ", tStr, " | Posição aberta — gerenciando"); return; } // 3) Detectar setup Fimathe (pullback para zona Fibonacci + confirmação) SSetup setup = DetectSetup(trend); if(setup.valid) { string dir = setup.isBuy ? "COMPRA ▲" : "VENDA ▼"; Print("[Fimathe] Setup ", dir, " | SwH=", setup.swHigh, " SwL=", setup.swLow, " | Fib618=", setup.fib618, " Fib786=", setup.fib786, " | Lots=", setup.lots, " SL=", setup.sl, " TP=", setup.tp); Comment("Fimathe Trend EA | Tendência: ", tStr, " | Setup ", dir, " | Lots=", DoubleToString(setup.lots,2), " SL=", DoubleToString(setup.sl, g_digits), " TP=", DoubleToString(setup.tp, g_digits)); ExecuteSetup(setup); } else { Comment("Fimathe Trend EA | Tendência: ", tStr, " | Aguardando pullback para zona Fibonacci (", DoubleToString(FibLvl1,3), " / ", DoubleToString(FibLvl2,3), ")..."); } } //+------------------------------------------------------------------+ //| FIM — Fimathe Trend EA v1.00 | //+------------------------------------------------------------------+