commit bc6f403b2832fef0a71bf5686a0462436479a554 Author: adalbertodasilva2580asf-collab Date: Sat May 30 08:14:36 2026 -0300 feat: Fimathe Trend EA v1.00 — Expert Advisor MQL5 EA profissional baseado na Técnica Fimathe de Marcelo Ferreira. Inclui identificação de tendência (EMA + estrutura), detecção de pullback em zona Fibonacci (0.618/0.786), gestão de capital por risco percentual, breakeven e trailing stop automáticos. Co-Authored-By: Claude Sonnet 4.6 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8475a62 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +# MetaTrader 5 compilado +*.ex5 + +# Arquivos de log e temporários +*.log +*.tmp +Thumbs.db +.DS_Store diff --git a/Fimathe_Trend_EA.mq5 b/Fimathe_Trend_EA.mq5 new file mode 100644 index 0000000..9ade5c8 --- /dev/null +++ b/Fimathe_Trend_EA.mq5 @@ -0,0 +1,761 @@ +//+------------------------------------------------------------------+ +//| 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 | +//+------------------------------------------------------------------+ diff --git a/README.md b/README.md new file mode 100644 index 0000000..56ac0bc --- /dev/null +++ b/README.md @@ -0,0 +1,187 @@ +# Fimathe Trend EA + +Expert Advisor profissional para MetaTrader 5 baseado na **Técnica Fimathe** de Marcelo Ferreira. + +O EA automatiza integralmente o método: identifica a tendência no timeframe superior, aguarda o pullback para a zona de Fibonacci e entra após confirmação de candle — tudo com gestão de capital integrada. + +--- + +## Sumário + +- [Como Funciona](#como-funciona) +- [Fluxo de Decisão](#fluxo-de-decisão) +- [Parâmetros de Configuração](#parâmetros-de-configuração) +- [Instalação](#instalação) +- [Requisitos](#requisitos) +- [Aviso Legal](#aviso-legal) + +--- + +## Como Funciona + +### Os 7 Pilares da Técnica Fimathe + +| # | Pilar | Descrição | +|---|-------|-----------| +| 1 | **Tendência é Soberana** | Opera sempre a favor da tendência principal identificada no TF superior | +| 2 | **Estrutura de Mercado** | Máximas e mínimas recentes formam suportes e resistências que o preço respeita | +| 3 | **Correções Fibonacci** | Após o impulso, aguarda o pullback nas zonas de 61,8% e 78,6% | +| 4 | **Confirmação de Entrada** | Aguarda o fechamento de uma vela na direção da tendência com corpo relevante | +| 5 | **Gestão de Risco** | SL estrutural abaixo/acima do pullback; TP percentual sobre o saldo | +| 6 | **Horário e Liquidez** | Prioriza sessões de Londres (08h–12h) e Nova York (13h–17h) | +| 7 | **Disciplina Operacional** | Máximo 1 posição aberta; sem reentrada imediata após stop | + +### Identificação de Tendência + +A tendência é confirmada por dois critérios combinados: + +- **Estrutura de mercado**: sequência de topos e fundos ascendentes (alta) ou descendentes (baixa) +- **Alinhamento de EMAs**: EMA 20 > EMA 50 > EMA 200 (alta) ou inverso (baixa) + +A confirmação é forte quando ambos concordam; parcial quando apenas um está presente. + +### Detecção do Setup + +**Compra (uptrend):** +1. Localiza o swing high e swing low recentes no TF operacional +2. O swing high deve ser mais recente que o swing low (impulso de alta concluído) +3. Preço recuou para a zona Fibonacci (entre 61,8% e 78,6% do range) +4. Vela de confirmação: bullish, corpo >= mínimo configurado, fechando acima do mínimo da zona + +**Venda (downtrend):** +1. O swing low deve ser mais recente que o swing high (impulso de baixa concluído) +2. Preço recuperou para a zona Fibonacci (61,8%–78,6% do range) +3. Vela de confirmação: bearish, corpo >= mínimo configurado, fechando abaixo do máximo da zona + +--- + +## Fluxo de Decisão + +``` +Tendência TF Superior + ↓ +Impulso Identificado (Swing High / Swing Low) + ↓ +Aguardar Pullback para Zona Fibonacci (0.618 / 0.786) + ↓ +Confirmação de Vela (corpo relevante na direção da tendência) + ↓ +Abertura da Posição + ↓ +Gestão: SL estrutural + TP percentual + Trailing + Breakeven +``` + +--- + +## Parâmetros de Configuração + +### Gestão de Capital + +| Parâmetro | Padrão | Descrição | +|-----------|--------|-----------| +| `UseMoneyMgmt` | `true` | Ativa gestão de capital por risco percentual | +| `RiskPercent` | `1.0` | % do saldo a arriscar por operação | +| `TargetPct` | `2.0` | % de lucro alvo por operação | +| `LotSize` | `0.01` | Lote fixo (usado quando `UseMoneyMgmt = false`) | + +### Timeframes + +| Parâmetro | Padrão | Descrição | +|-----------|--------|-----------| +| `TrendTF` | `H1` | Timeframe para identificação da tendência | +| `OperTF` | `M5` | Timeframe operacional de entrada | + +### Fibonacci + +| Parâmetro | Padrão | Descrição | +|-----------|--------|-----------| +| `FibLvl1` | `0.618` | Nível Fibonacci principal (61,8%) | +| `FibLvl2` | `0.786` | Nível Fibonacci secundário (78,6%) | +| `FibTolerance` | `0.015` | Tolerância da zona como fração do range | + +### Estrutura e Setup + +| Parâmetro | Padrão | Descrição | +|-----------|--------|-----------| +| `StructBars` | `35` | Barras para detectar swing high/low | +| `MinBodyPts` | `60` | Pontos mínimos no corpo da vela de confirmação | +| `NeedBodyClose` | `true` | Exige corpo mínimo na vela de confirmação | + +### Stop Loss + +| Parâmetro | Padrão | Descrição | +|-----------|--------|-----------| +| `UseATR` | `true` | Calcula SL via ATR | +| `ATRPeriod` | `14` | Período do ATR | +| `ATRMult` | `2.0` | Multiplicador do ATR para o SL | +| `SLBuffer` | `150` | Buffer além da estrutura em pontos (sem ATR) | + +### Breakeven e Trailing Stop + +| Parâmetro | Padrão | Descrição | +|-----------|--------|-----------| +| `UseBreakEven` | `true` | Ativa breakeven automático | +| `BEPct` | `0.5` | % de lucro no saldo para ativar o breakeven | +| `UseTrailing` | `true` | Ativa trailing stop automático | +| `TSPct` | `1.0` | % de lucro no saldo para ativar o trailing | +| `TSPoints` | `250` | Distância do trailing stop em pontos | + +### Horário de Operação + +| Parâmetro | Padrão | Descrição | +|-----------|--------|-----------| +| `UseTimeFilter` | `true` | Filtra o horário de operação | +| `StartHour` | `9` | Hora de início (horário do servidor) | +| `StartMin` | `0` | Minuto de início | +| `EndHour` | `18` | Hora de fim (horário do servidor) | +| `EndMin` | `0` | Minuto de fim | +| `CloseAtEnd` | `false` | Fecha posições ao atingir a hora de fim | + +### Identificação + +| Parâmetro | Padrão | Descrição | +|-----------|--------|-----------| +| `MagicNumber` | `202536` | Número mágico para identificar as ordens do EA | +| `EAComment` | `Fimathe Trend EA` | Comentário nas ordens abertas | + +--- + +## Instalação + +1. Abra o **MetaEditor** (atalho `F4` no MetaTrader 5) +2. Copie o arquivo `Fimathe_Trend_EA.mq5` para a pasta: + ``` + [Dados MT5]\MQL5\Experts\ + ``` + Por padrão em Windows: + ``` + C:\Users\[SeuUsuário]\AppData\Roaming\MetaQuotes\Terminal\[ID]\MQL5\Experts\ + ``` +3. No MetaEditor, abra o arquivo e clique em **Compilar** (`F7`) — o arquivo `.ex5` será gerado automaticamente +4. No MetaTrader 5, vá em **Exibir → Navegador → Expert Advisors** +5. Arraste o `Fimathe_Trend_EA` para o gráfico do ativo desejado +6. Na janela de configuração, ajuste os parâmetros conforme sua estratégia +7. Certifique-se de que o **AutoTrading** está habilitado (botão verde na barra de ferramentas) + +--- + +## Requisitos + +- **Plataforma**: MetaTrader 5 (build 3000+) +- **Linguagem**: MQL5 +- **Conta**: Real ou Demo com execução automática de ordens habilitada +- **Ativos sugeridos**: Forex, Índices, Commodities com liquidez nas sessões de Londres e Nova York + +--- + +## Aviso Legal + +> **Este software é fornecido para fins educacionais e de estudo da Técnica Fimathe.** +> +> Trading automatizado envolve riscos significativos de perda de capital. Resultados passados não garantem resultados futuros. Teste sempre em conta demo antes de operar com capital real. O autor não se responsabiliza por perdas financeiras decorrentes do uso deste software. +> +> A Técnica Fimathe é de autoria de **Marcelo Ferreira**. Este EA é uma implementação técnica independente e não tem vínculo oficial com o autor da técnica. + +--- + +*Fimathe Trend EA v1.00 — MQL5 / MetaTrader 5*