Gold MetaLockDay EA

İş Gereklilikleri

//+------------------------------------------------------------------+
//| Gold MetaLockDay EA (MT5)                                        |
//| Meta líquida diária com MIX de entradas (XAUUSD)                 |
//+------------------------------------------------------------------+
#property strict

#include <Trade/Trade.mqh>
CTrade trade;

//======================== INPUTS ========================//
input string          InpSymbol            = "";        // Vazio = usa símbolo do gráfico
input ENUM_TIMEFRAMES InpTF                = PERIOD_CURRENT;
input double          InpLotPerEntry        = 0.10;
input int             InpMaxEntriesPerDay   = 5;
input int             InpBurstEntries       = 3;        // <<< MIX: entradas rápidas iniciais
input double          InpNetDailyTarget     = 95.75;
input double          InpNetDailyStop       = 120.00;
input int             InpEMA_Fast           = 21;
input int             InpEMA_Slow           = 50;
input int             InpATR_Period         = 14;
input double          InpATR_ContMult       = 0.3;      // <<< Continuação mais curta
input ulong           InpMagic              = 777777;
input bool            InpCloseOnTrendFlip   = true;

//======================== GLOBAL ========================//
int      g_entriesToday   = 0;
bool     g_lockedForToday = true;
int      g_dayKey         = -1;
double   g_lastEntryPrice = 0.0;
int      g_lastDir        = 0;

int hEmaFast = INVALID_HANDLE;
int hEmaSlow = INVALID_HANDLE;
int hATR     = INVALID_HANDLE;

//======================== UTILS ========================//
string TRADE_SYMBOL()
{
   if(StringLen(InpSymbol) == 0) return _Symbol;
   return InpSymbol;
}

int DAY_KEY(datetime t)
{
   MqlDateTime dt; TimeToStruct(t, dt);
   return dt.year*10000 + dt.mon*100 + dt.day;
}

datetime DAY_START(datetime t)
{
   MqlDateTime dt; TimeToStruct(t, dt);
   dt.hour=0; dt.min=0; dt.sec=0;
   return StructToTime(dt);
}

//======================== HISTORY ========================//
double NetProfitToday(string sym)
{
   datetime now  = TimeCurrent();
   datetime from = DAY_START(now);

   if(!HistorySelect(from, now)) return 0.0;

   double sum = 0.0;
   for(int i=0;i<HistoryDealsTotal();i++)
   {
      ulong deal = HistoryDealGetTicket(i);
      if(deal==0) continue;
      if(HistoryDealGetString(deal, DEAL_SYMBOL) != sym) continue;

      sum += HistoryDealGetDouble(deal, DEAL_PROFIT)
           + HistoryDealGetDouble(deal, DEAL_COMMISSION)
           + HistoryDealGetDouble(deal, DEAL_SWAP);
   }
   return sum;
}

//======================== POSITIONS ========================//
bool SelectPosByIndex(int i, ulong &ticket)
{
   ticket = PositionGetTicket(i);
   if(ticket==0) return false;
   return PositionSelectByTicket(ticket);
}

int PositionDirection(string sym)
{
   for(int i=PositionsTotal()-1;i>=0;i--)
   {
      ulong tk;
      if(!SelectPosByIndex(i,tk)) continue;
      if(PositionGetString(POSITION_SYMBOL)!=sym) continue;

      long type = PositionGetInteger(POSITION_TYPE);
      if(type==POSITION_TYPE_BUY)  return 1;
      if(type==POSITION_TYPE_SELL) return -1;
   }
   return 0;
}

void CloseAll(string sym)
{
   trade.SetExpertMagicNumber(InpMagic);
   for(int i=PositionsTotal()-1;i>=0;i--)
   {
      ulong tk;
      if(!SelectPosByIndex(i,tk)) continue;
      if(PositionGetString(POSITION_SYMBOL)!=sym) continue;
      trade.PositionClose(tk);
   }
}

//======================== INDICATORS ========================//
bool GetIndicators(double &emaFast,double &emaSlow,double &atr)
{
   if(hEmaFast==INVALID_HANDLE || hEmaSlow==INVALID_HANDLE || hATR==INVALID_HANDLE)
      return false;

   double b1[1], b2[1], b3[1];
   if(CopyBuffer(hEmaFast,0,0,1,b1)<=0) return false;
   if(CopyBuffer(hEmaSlow,0,0,1,b2)<=0) return false;
   if(CopyBuffer(hATR,    0,0,1,b3)<=0) return false;

   emaFast=b1[0];
   emaSlow=b2[0];
   atr=b3[0];
   return true;
}

//======================== INIT ========================//
int OnInit()
{
   string sym = TRADE_SYMBOL();
   SymbolSelect(sym,true);

   hEmaFast = iMA(sym,InpTF,InpEMA_Fast,0,MODE_EMA,PRICE_CLOSE);
   hEmaSlow = iMA(sym,InpTF,InpEMA_Slow,0,MODE_EMA,PRICE_CLOSE);
   hATR     = iATR(sym,InpTF,InpATR_Period);

   g_dayKey = DAY_KEY(TimeCurrent());
   return INIT_SUCCEEDED;   // nunca falha
}

//======================== DEINIT ========================//
void OnDeinit(const int reason)
{
   if(hEmaFast!=INVALID_HANDLE) IndicatorRelease(hEmaFast);
   if(hEmaSlow!=INVALID_HANDLE) IndicatorRelease(hEmaSlow);
   if(hATR    !=INVALID_HANDLE) IndicatorRelease(hATR);
}

//======================== TICK ========================//
void OnTick()
{
   string sym = TRADE_SYMBOL();
   SymbolSelect(sym,true);

   MqlTick tick;
   if(!SymbolInfoTick(sym, tick)) return;

   // Reset diário
   int dk = DAY_KEY(TimeCurrent());
   if(dk!=g_dayKey)
   {
      g_dayKey=dk;
      g_entriesToday=0;
      g_lockedForToday=true;
      g_lastDir=0;
      g_lastEntryPrice=0;
   }

   double net = NetProfitToday(sym);

   // Meta / Stop líquidos
   if(!g_lockedForToday)
   {
      if(net>=InpNetDailyTarget || net<=-MathAbs(InpNetDailyStop))
      {
         CloseAll(sym);
         g_lockedForToday=true;
      }
   }
   if(g_lockedForToday) return;

   // Indicadores
   double emaFast,emaSlow,atr;
   if(!GetIndicators(emaFast,emaSlow,atr)) return;

   int trend = (emaFast>emaSlow ? 1 : (emaFast<emaSlow ? -1 : 0));
   if(trend==0) return;

   int posDir = PositionDirection(sym);

   // Fecha no flip (opcional)
   if(InpCloseOnTrendFlip && posDir!=0 && posDir!=trend)
   {
      CloseAll(sym);
      g_lastEntryPrice=0;
      g_lastDir=0;
      return;
   }

   if(g_entriesToday >= InpMaxEntriesPerDay) return;

   double bid = tick.bid;
   double ask = tick.ask;
   double price = (trend>0 ? ask : bid);

   // ================= MIX DE ENTRADAS ================= //

   // 1) Primeira entrada
   if(posDir==0)
   {
      trade.SetExpertMagicNumber(InpMagic);
      bool ok = (trend>0 ? trade.Buy(InpLotPerEntry,sym)
                         : trade.Sell(InpLotPerEntry,sym));
      if(ok)
      {
         g_entriesToday++;
         g_lastDir=trend;
         g_lastEntryPrice=price;
      }
      return;
   }

   // 2) BURST inicial (entradas quase juntas)
   if(posDir==trend && g_entriesToday < InpBurstEntries)
   {
      trade.SetExpertMagicNumber(InpMagic);
      bool okb = (trend>0 ? trade.Buy(InpLotPerEntry,sym)
                          : trade.Sell(InpLotPerEntry,sym));
      if(okb)
      {
         g_entriesToday++;
         g_lastEntryPrice=price;
      }
      return;
   }

   // 3) Continuação com ATR menor
   double contDist = atr * InpATR_ContMult;
   if(posDir==trend && g_entriesToday < InpMaxEntriesPerDay)
   {
      bool canAdd = (trend>0 ? (bid >= g_lastEntryPrice + contDist)
                             : (ask <= g_lastEntryPrice - contDist));
      if(!canAdd) return;

      trade.SetExpertMagicNumber(InpMagic);
      bool okc = (trend>0 ? trade.Buy(InpLotPerEntry,sym)
                          : trade.Sell(InpLotPerEntry,sym));
      if(okc)
      {
         g_entriesToday++;
         g_lastEntryPrice=price;
      }
   }
}

Proje bilgisi

Bütçe
30+ USD

Müşteri

Verilmiş siparişler1
Arabuluculuk sayısı0