TP 300, (optimize of TP 2000)

 avatar
unknown
plain_text
3 months ago
15 kB
9
Indexable
//+------------------------------------------------------------------+
//|                                      HedgingGrid_v4.mq5          |
//|          CODE GOC NGUYEN BAN + Magic Number + Daily Reset        |
//|          KHONG thay doi bat ky tham so nao cua code goc          |
//+------------------------------------------------------------------+
#property copyright "Hedging Grid v4"
#property version   "4.00"
#property strict

#include <Trade\Trade.mqh>
#include <Trade\DealInfo.mqh>

CTrade   trade;
CDealInfo m_deal;

//+------------------------------------------------------------------+
//| INPUTS - Chi them Magic va Daily Reset                            |
//+------------------------------------------------------------------+
input int     InpMagic           = 999777;       // Magic Number
input double  InpEntryVol        = 0.01;         // Lot (nhu code goc)
input double  InpReverseDist     = 1.0;          // Dao chieu khi lo $ (code goc = 1)
input double  InpSL_Dist         = 1.0;          // SL cach entry $ (code goc = 1)
input double  InpExpectedTP      = 300.0;        // TP equity/ngay (giam de hit nhanh hon)
input double  InpExpectedSL      = 500.0;        // SL equity/ngay (rong hon TP de cho EA hoi phuc)
input bool    InpDailyReset      = true;         // [MOI] Reset moi ngay
input bool    InpStartBuy        = true;         // Bat dau bang BUY
input int     InpMaxPositions    = 30;           // [MOI] Gioi han so lenh toi da

//+------------------------------------------------------------------+
//| GLOBALS - Giong code goc                                          |
//+------------------------------------------------------------------+
bool     IsBuy;
double   EntryVol;
double   BID = 0;
double   ASK = 0;
bool     flag = true;
bool     trading = true;
double   initBalance = 0;
bool     NEED_TO_CLOSE_ALL = false;
double   lowestBalance = 0;
int      total = 0;

// [MOI] Daily tracking
datetime g_todayDate = 0;
double   g_dayStartBal = 0;
int      g_totalDays = 0;
int      g_daysTP = 0;
int      g_daysSL = 0;

//+------------------------------------------------------------------+
int OnInit()
{
   trade.SetExpertMagicNumber(InpMagic);
   trade.SetDeviationInPoints(50);

   IsBuy = InpStartBuy;
   EntryVol = InpEntryVol;
   initBalance = AccountInfoDouble(ACCOUNT_BALANCE);
   lowestBalance = initBalance;
   trading = true;
   NEED_TO_CLOSE_ALL = false;
   total = 0;

   // Init daily
   g_todayDate = 0;
   g_dayStartBal = initBalance;

   MqlTick tick;
   if(SymbolInfoTick(_Symbol, tick))
   {
      BID = tick.bid;
      ASK = tick.ask;
      Print(BID, " | ", ASK);

      // Mo lenh dau tien (nhu code goc)
      if(IsBuy && PositionsTotal() == 0)
      {
         Print("Buy");
         trade.Buy(EntryVol, _Symbol, ASK, ASK - InpSL_Dist);
      }
   }

   Print("=============================================");
   Print("  HEDGING GRID v4 | CODE GOC + DAILY RESET");
   Print("  Lot: ", EntryVol, " | Reverse: $", InpReverseDist);
   Print("  TP: $", InpExpectedTP, " | SL: $", InpExpectedSL);
   Print("  Daily Reset: ", InpDailyReset);
   Print("=============================================");

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   Print("========= TONG KET =========");
   Print("THE INIT BALANCE IS: ", initBalance);
   Print("THE LOWEST BALANCE IS: ", lowestBalance);
   Print("Max Position: ", total);
   Print("Total Days: ", g_totalDays);
   Print("Days TP: ", g_daysTP);
   Print("Days SL: ", g_daysSL);
   Print("Final Balance: ", AccountInfoDouble(ACCOUNT_BALANCE));
}

//+------------------------------------------------------------------+
//| [MOI] Check ngay moi va reset                                    |
//+------------------------------------------------------------------+
void CheckDailyReset()
{
   if(!InpDailyReset) return;

   MqlDateTime dt;
   TimeCurrent(dt);
   datetime today = (datetime)(TimeCurrent() - dt.hour*3600 - dt.min*60 - dt.sec);

   if(today == g_todayDate) return;

   // === NGAY MOI ===
   if(g_todayDate > 0)
   {
      // Log ngay cu
      double endBal = AccountInfoDouble(ACCOUNT_BALANCE);
      Print("[DAY END] Balance: $", DoubleToString(endBal,2),
            " | Day PnL: $", DoubleToString(endBal - g_dayStartBal, 2));
   }

   g_todayDate = today;
   g_dayStartBal = AccountInfoDouble(ACCOUNT_BALANCE);
   g_totalDays++;

   // Reset trang thai giao dich (nhu khi moi khoi dong EA)
   trading = true;
   NEED_TO_CLOSE_ALL = false;
   IsBuy = InpStartBuy;
   EntryVol = InpEntryVol;

   if(g_dayStartBal < lowestBalance)
      lowestBalance = g_dayStartBal;

   Print("[NEW DAY] #", g_totalDays,
         " | Balance: $", DoubleToString(g_dayStartBal, 2));
}

//+------------------------------------------------------------------+
//| OnTick - LOGIC CODE GOC NGUYEN BAN                               |
//+------------------------------------------------------------------+
void OnTick()
{
   // [MOI] Check ngay moi
   CheckDailyReset();

   if(PositionsTotal() > total)
      total = PositionsTotal();

   double balance = AccountInfoDouble(ACCOUNT_BALANCE);
   double profit = AccountInfoDouble(ACCOUNT_PROFIT);

   // [MOI] Dung dayStartBal thay vi initBalance
   double refBal = InpDailyReset ? g_dayStartBal : initBalance;

   // TP check (nhu code goc)
   if(balance + profit >= refBal + InpExpectedTP || NEED_TO_CLOSE_ALL)
   {
      trading = false;
      CloseAllCurrentPosition();
      if(InpDailyReset && !NEED_TO_CLOSE_ALL)
      {
         g_daysTP++;
         Print("[DAILY TP] +$", DoubleToString(balance + profit - refBal, 2));
      }
      NEED_TO_CLOSE_ALL = true;
   }

   // SL check (nhu code goc)
   if(balance + profit <= refBal - InpExpectedSL || NEED_TO_CLOSE_ALL)
   {
      if(!NEED_TO_CLOSE_ALL) // Chi dem 1 lan
      {
         trading = false;
         CloseAllCurrentPosition();
         if(InpDailyReset)
         {
            g_daysSL++;
            Print("[DAILY SL] -$", DoubleToString(refBal - (balance + profit), 2));
         }
         NEED_TO_CLOSE_ALL = true;
      }
   }

   if(lowestBalance > balance)
      lowestBalance = balance;

   if(!trading) return;

   // === LOGIC CODE GOC NGUYEN BAN ===
   CheckCurrentPositionPL();
}

//+------------------------------------------------------------------+
//| OnTradeTransaction - CODE GOC NGUYEN BAN + Magic filter          |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
{
   ENUM_TRADE_TRANSACTION_TYPE type = trans.type;

   if(type == TRADE_TRANSACTION_DEAL_ADD)
   {
      if(HistoryDealSelect(trans.deal))
         m_deal.Ticket(trans.deal);
      else
         return;

      // [MOI] Filter magic
      long dealMagic = HistoryDealGetInteger(trans.deal, DEAL_MAGIC);
      if(dealMagic != InpMagic) return;

      long reason = -1;
      if(!m_deal.InfoInteger(DEAL_REASON, reason)) return;

      if((ENUM_DEAL_REASON)reason == DEAL_REASON_SL)
      {
         Print("Stop loss activated for position ==> ", trans.position);

         if(!trading) return; // [MOI] Khong mo lenh khi da dung

         // [MOI] Check gioi han lenh
         int slPos = 0;
         for(int j = 0; j < PositionsTotal(); j++)
         {
            ulong t = PositionGetTicket(j);
            if(t > 0 && PositionGetInteger(POSITION_MAGIC) == InpMagic)
               slPos++;
         }
         if(slPos >= InpMaxPositions)
         {
            Print("[LIMIT] Max pos after SL, skip");
            return;
         }

         // LOGIC CODE GOC: mo lenh nguoc chieu khi bi SL
         MqlTick tick;
         if(SymbolInfoTick(_Symbol, tick))
         {
            if(!IsBuy)
            {
               if(trade.Buy(EntryVol, _Symbol, tick.ask, tick.ask - InpSL_Dist))
                  Print("Reverse Buy after SL. Price: ", tick.ask);
               else
                  RetryTrade(true);
            }
            else
            {
               if(trade.Sell(EntryVol, _Symbol, tick.bid, tick.bid + InpSL_Dist))
                  Print("Reverse Sell after SL. Price: ", tick.bid);
               else
                  RetryTrade(false);
            }
         }
      }
   }
}

//+------------------------------------------------------------------+
//| CloseAll - CODE GOC + Magic filter                               |
//+------------------------------------------------------------------+
void CloseAllCurrentPosition()
{
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      if(PositionGetTicket(i) > 0)
      {
         ulong ticket = PositionGetTicket(i);
         if(PositionSelectByTicket(ticket))
         {
            // [MOI] Chi dong lenh cua EA nay
            if(PositionGetInteger(POSITION_MAGIC) != InpMagic) continue;
            if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;

            string symbol = PositionGetString(POSITION_SYMBOL);
            double volume = PositionGetDouble(POSITION_VOLUME);
            long posType = PositionGetInteger(POSITION_TYPE);
            double posProfit = PositionGetDouble(POSITION_PROFIT);

            if(posType == POSITION_TYPE_BUY)
            {
               if(!trade.PositionClose(ticket, -1))
                  Print("Failed to close BUY: ", GetLastError());
               else
                  Print("CLOSING BUY: ", symbol, " vol: ", volume,
                        ", profit: ", posProfit);
            }
            else if(posType == POSITION_TYPE_SELL)
            {
               if(!trade.PositionClose(ticket, -1))
                  Print("Failed to close SELL: ", GetLastError());
               else
                  Print("CLOSING SELL: ", symbol, " vol: ", volume,
                        ", profit: ", posProfit);
            }
         }
      }
   }
}

//+------------------------------------------------------------------+
//| CheckCurrentPositionPL - CODE GOC NGUYEN BAN + Magic filter      |
//+------------------------------------------------------------------+
void CheckCurrentPositionPL()
{
   ulong latestTicket = 0;
   datetime latestTime = 0;
   double latestEntryPrice = 0;
   long latestType = -1;
   double latestVolume = 0;
   double latestProfit = 0;
   double currentPrice = 0;

   for(int i = 0; i < PositionsTotal(); i++)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0)
      {
         if(PositionSelectByTicket(ticket))
         {
            // [MOI] Filter Magic + Symbol
            if(PositionGetInteger(POSITION_MAGIC) != InpMagic) continue;
            if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;

            datetime openTime = (datetime)PositionGetInteger(POSITION_TIME);
            if(openTime > latestTime)
            {
               latestTicket = ticket;
               latestTime = openTime;
               latestEntryPrice = PositionGetDouble(POSITION_PRICE_OPEN);
               latestType = PositionGetInteger(POSITION_TYPE);
               latestVolume = PositionGetDouble(POSITION_VOLUME);
               latestProfit = PositionGetDouble(POSITION_PROFIT);
               currentPrice = (latestType == POSITION_TYPE_BUY)
                              ? SymbolInfoDouble(_Symbol, SYMBOL_BID)
                              : SymbolInfoDouble(_Symbol, SYMBOL_ASK);
            }
         }
      }
   }

   if(latestTicket != 0)
   {
      MqlTick tick;
      if(SymbolInfoTick(_Symbol, tick))
      {
         BID = tick.bid;
         ASK = tick.ask;

         // LOGIC CODE GOC NGUYEN BAN: check reverse
         bool mustReverse = (!IsBuy
            ? latestEntryPrice - currentPrice
            : currentPrice - latestEntryPrice) <= -InpReverseDist;

         if(mustReverse && flag)
         {
            flag = false;

            // [MOI] Check gioi han lenh
            int myPos = 0;
            for(int j = 0; j < PositionsTotal(); j++)
            {
               ulong t = PositionGetTicket(j);
               if(t > 0 && PositionGetInteger(POSITION_MAGIC) == InpMagic
                  && PositionGetString(POSITION_SYMBOL) == _Symbol)
                  myPos++;
            }

            if(myPos >= InpMaxPositions)
            {
               Print("[LIMIT] ", myPos, " positions, khong mo them");
               flag = true;
               return;
            }

            if(latestType == POSITION_TYPE_BUY)
            {
               IsBuy = false;
               if(trade.Sell(EntryVol, _Symbol, BID, BID + InpSL_Dist))
                  Print("SELL: Reverse vol: ", EntryVol, ", SL: ", BID + InpSL_Dist);
               else
                  Print("Failed REVERSE SELL. Error: ", GetLastError());
            }
            else
            {
               IsBuy = true;
               if(trade.Buy(EntryVol, _Symbol, ASK, ASK - InpSL_Dist))
                  Print("BUY: Reverse vol: ", EntryVol, ", SL: ", ASK - InpSL_Dist);
               else
                  Print("Failed REVERSE BUY. Error: ", GetLastError());
            }
            flag = true;
         }
      }
   }
   else
   {
      // Khong co lenh -> mo moi (nhu code goc)
      Print("No open position. Creating new order");
      MqlTick tick;
      if(SymbolInfoTick(_Symbol, tick))
      {
         BID = tick.bid;
         ASK = tick.ask;

         if(IsBuy && PositionsTotal() == 0)
         {
            if(trade.Buy(EntryVol, _Symbol, ASK, ASK - InpSL_Dist))
               Print("New BUY: ", ASK, " SL: ", ASK - InpSL_Dist);
         }
         else if(!IsBuy && PositionsTotal() == 0)
         {
            if(trade.Sell(EntryVol, _Symbol, BID, BID + InpSL_Dist))
               Print("New SELL: ", BID, " SL: ", BID + InpSL_Dist);
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Retry - Don gian hon code goc (chi retry 3 lan)                  |
//+------------------------------------------------------------------+
bool RetryTrade(bool isBuy, int maxAttempts = 3)
{
   bool success = false;
   int attempt = 0;

   while(!success && attempt < maxAttempts)
   {
      attempt++;
      MqlTick tick;
      if(SymbolInfoTick(_Symbol, tick))
      {
         if(isBuy)
            success = trade.Buy(EntryVol, _Symbol, tick.ask, tick.ask - InpSL_Dist);
         else
            success = trade.Sell(EntryVol, _Symbol, tick.bid, tick.bid + InpSL_Dist);
      }

      if(!success)
      {
         Print("Retry #", attempt, " failed. Error: ", GetLastError());
         Sleep(200);
      }
   }
   return success;
}
//+------------------------------------------------------------------+
Editor is loading...
Leave a Comment