Просмотр исходного кода

Ticket: 5163 TP/SL and CSV updated

Huzaifa-MQLDev 9 месяцев назад
Родитель
Сommit
33cc5d33d3
3 измененных файлов с 169 добавлено и 54 удалено
  1. 3 2
      data/vol_hedge_data.csv
  2. BIN
      vol_hedge_strategy_mt5.ex5
  3. 166 52
      vol_hedge_strategy_mt5.mq5

+ 3 - 2
data/vol_hedge_data.csv

@@ -1,2 +1,3 @@
-EURUSDm,1.08384,1000,1000,2023.03.22 02:05:25,2023.03.24 02:05:25
-EURUSDm,1.08734,400,400,2023.03.30 00:00:00,2023.04.04 02:05:25
+Symbol,Price,Buy StopLoss,Buy TakeProfit,Sell StopLoss,Sell TakeProfit,StartTime,EndTime
+EURUSDm,1.08384,1.07384,1.09384,1.09384,1.07384,2023.03.22 02:05:25,2024.03.24 02:05:25
+EURUSDm,1.08734,1.07734,1.09734,1.09734,1.07734,2023.03.30 00:00:00,2024.04.04 02:05:25

BIN
vol_hedge_strategy_mt5.ex5


+ 166 - 52
vol_hedge_strategy_mt5.mq5

@@ -5,7 +5,7 @@
 //+------------------------------------------------------------------+
 #property copyright "Copyright 2025, MQL Development"
 #property link      "https://www.mqldevelopment.com/"
-#property version   "1.00"
+#property version   "1.10"
 #define MaxOrders 100
 #include <Trade\Trade.mqh>
 CTrade  trade;
@@ -61,8 +61,10 @@ struct new_trade_store
    ulong             sell_ticket;           // Sell Ticket
    string            symbol;                // Symbol
    double            price;                 // Price
-   double            stop_loss;             // StopLoss
-   double            take_profit;           // TakeProfit
+   double            stop_loss_buy;         // StopLoss Buy
+   double            take_profit_buy;       // TakeProfit Buy
+   double            stop_loss_sell;        // StopLoss Sell
+   double            take_profit_sell;      // TakeProfit Sell
    datetime          start_time;            // Start time
    datetime          end_time;              // End Time
    bool              buy_hit_virtual_sl;    // Buy Hit Virtual StopLoss
@@ -89,8 +91,10 @@ enum lotcalculator
 
 sinput       string                  string_0                   = "<><><><><><> General SETTINGS <><><><><><>";   //__
 input        int                     magic_no                   = 333;             // Magic no
+input        bool                    useTpSlPips                = true;            // Use Tp/Sl in Pips
+input        double                  stopLoss                   = 100;             // Fixed Stop Loss in Pips
+input        double                  takeProfit                 = 100;             // Fixed Take Profit in Pips
 input        bool                    bothHitsSl                 = false;           // Open after Both Hits StopLoss
-input        int                     maxTrades                  = 2;               // Max Concurrent Trades
 input        int                     maxSlippage                = 5;               // Max Slippage
 input        bool                    enableSpreadFilter         = false;           // Enable Spread Filter
 input        double                  maximumSpread              = 10;              // Maximum Spread
@@ -140,6 +144,7 @@ double tickPreviousBid = 0;
 static double tickCurrentAsk = 0;
 double tickPreviousAsk = 0;
 datetime startSessionTime, endSessionTime;
+int maxTrades = 2; // Max Concurrent Trades
 int GMT_Broker_Time = +2; // GMT_Broker_Time Time of your Broker
 int                     gmt                        = 0;                   // GMT_Broker_Time Time of your Broker
 string Lname="newsLabel3";
@@ -179,7 +184,7 @@ int OnInit()
             Print(" Order Data: ", orderData[i], " i: ", i);
            }
 
-         if(ArraySize(orderData) >= 6)
+         if(ArraySize(orderData) >= 8)
            {
             if(orderData[0] == Symbol())
               {
@@ -188,11 +193,13 @@ int OnInit()
                ulong  sell_ticket_local = (ulong)-1;
                string symbol_local      = orderData[0];
                double price_local       = StringToDouble(orderData[1]);
-               double sl_local          = StringToDouble(orderData[2]);
-               double tp_local          = StringToDouble(orderData[3]);
+               double sl_buy_local      = StringToDouble(orderData[2]);
+               double tp_buy_local      = StringToDouble(orderData[3]);
+               double sl_sell_local     = StringToDouble(orderData[4]);
+               double tp_sell_local     = StringToDouble(orderData[5]);
                // if your CSV has extra fields (tp2,tp3, etc.) parse here as needed
-               datetime start_local     = StringToTime(orderData[4]);
-               datetime end_local       = StringToTime(orderData[5]);
+               datetime start_local     = StringToTime(orderData[6]);
+               datetime end_local       = StringToTime(orderData[7]);
 
                ArrayResize(levelsAre,ArraySize(levelsAre)+1);
                levelsAre[ArraySize(levelsAre) - 1] = price_local;
@@ -212,7 +219,8 @@ int OnInit()
                  {
                   addToNewTradeStore(buy_ticket_local, sell_ticket_local,
                                      symbol_local, price_local,
-                                     sl_local, tp_local,
+                                     sl_buy_local, tp_buy_local,
+                                     sl_sell_local, tp_sell_local,
                                      start_local, end_local,
                                      buy_virtual_tp_hit, sell_virtual_tp_hit);
                  }
@@ -566,14 +574,16 @@ void struct_level_check()
                buy_virtual_tp_hit = false;
                sell_virtual_tp_hit = false;
               }
-            newTradeStore[i].buy_hit_virtual_sl = buy_virtual_tp_hit;
+            newTradeStore[i].buy_hit_virtual_sl  = buy_virtual_tp_hit;
             newTradeStore[i].sell_hit_virtual_sl = sell_virtual_tp_hit;
-            newTradeStore[i].symbol      = "";
-            newTradeStore[i].price       = 0.0;
-            newTradeStore[i].stop_loss   = 0.0;
-            newTradeStore[i].take_profit = 0.0;
-            newTradeStore[i].start_time  = 0;
-            newTradeStore[i].end_time    = 0;
+            newTradeStore[i].symbol           = "";
+            newTradeStore[i].price            = 0.0;
+            newTradeStore[i].stop_loss_buy    = 0.0;
+            newTradeStore[i].take_profit_buy  = 0.0;
+            newTradeStore[i].stop_loss_sell   = 0.0;
+            newTradeStore[i].take_profit_sell = 0.0;
+            newTradeStore[i].start_time       = 0;
+            newTradeStore[i].end_time         = 0;
             return;
            }
         }
@@ -587,7 +597,8 @@ void struct_level_check()
 //+------------------------------------------------------------------+
 void addToNewTradeStore(ulong r_buy_ticket, ulong r_sell_ticket,
                         string r_symbol, double r_price,
-                        double r_stop_loss, double r_take_profit,
+                        double r_stop_loss_buy, double r_take_profit_buy,
+                        double r_stop_loss_sell, double r_take_profit_sell,
                         datetime r_start_time, datetime r_end_time, bool r_buy_hit_sl, bool r_sell_hit_sl)
   {
    Print(" Tier 1. ");
@@ -602,8 +613,10 @@ void addToNewTradeStore(ulong r_buy_ticket, ulong r_sell_ticket,
             newTradeStore[i].sell_ticket = r_sell_ticket;
             newTradeStore[i].symbol      = r_symbol;
             newTradeStore[i].price       = r_price;
-            newTradeStore[i].stop_loss   = r_stop_loss;
-            newTradeStore[i].take_profit = r_take_profit;
+            newTradeStore[i].stop_loss_buy   = r_stop_loss_buy;
+            newTradeStore[i].take_profit_buy = r_take_profit_buy;
+            newTradeStore[i].stop_loss_sell   = r_stop_loss_sell;
+            newTradeStore[i].take_profit_sell = r_take_profit_sell;
             newTradeStore[i].start_time  = r_start_time;
             newTradeStore[i].end_time    = r_end_time;
             newTradeStore[i].buy_hit_virtual_sl = r_buy_hit_sl;
@@ -612,8 +625,10 @@ void addToNewTradeStore(ulong r_buy_ticket, ulong r_sell_ticket,
             Print("Stored -> idx: ", i,
                   " | Symbol: ", newTradeStore[i].symbol,
                   " | price: ", DoubleToString(newTradeStore[i].price, Digits()),
-                  " | sl: ", DoubleToString(newTradeStore[i].stop_loss, Digits()),
-                  " | tp: ", DoubleToString(newTradeStore[i].take_profit, Digits()),
+                  " | Sl Buy: ", DoubleToString(newTradeStore[i].stop_loss_buy, Digits()),
+                  " | Tp Buy: ", DoubleToString(newTradeStore[i].take_profit_buy, Digits()),
+                  "\n | Sl Sell: ", DoubleToString(newTradeStore[i].stop_loss_sell, Digits()),
+                  " | Tp Sell: ", DoubleToString(newTradeStore[i].take_profit_sell, Digits()),
                   " | start: ", TimeToString(newTradeStore[i].start_time, TIME_DATE|TIME_SECONDS),
                   " | end: ", TimeToString(newTradeStore[i].end_time, TIME_DATE|TIME_SECONDS),
                   " | Buy Virtal Sl Hit: ", newTradeStore[i].buy_hit_virtual_sl,
@@ -642,12 +657,12 @@ void tradePlacingCheck()
                   if((tickPreviousBid > levelPriceIs && tickCurrentBid < levelPriceIs) ||
                      (tickPreviousBid < levelPriceIs && tickCurrentBid > levelPriceIs))
                     {
-                     if(countLiveTrades() < maxTrades)
+                     if(countLiveTrades() == 0)
                        {
                         if((enableSpreadFilter && spreadFilter()) || !enableSpreadFilter)
                           {
-                           ulong buyTicket = placeBuyTrade(newTradeStore[i].stop_loss, newTradeStore[i].take_profit);
-                           ulong sellTicket = placeSellTrade(newTradeStore[i].stop_loss, newTradeStore[i].take_profit);
+                           ulong buyTicket = placeBuyTrade(newTradeStore[i].stop_loss_buy, newTradeStore[i].take_profit_buy);
+                           ulong sellTicket = placeSellTrade(newTradeStore[i].stop_loss_sell, newTradeStore[i].take_profit_sell);
 
                            newTradeStore[i].buy_ticket = buyTicket;
                            newTradeStore[i].sell_ticket = sellTicket;
@@ -671,13 +686,27 @@ ulong placeBuyTrade(double stoploss, double takeprofit)
    double Ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK);
    double Bid = SymbolInfoDouble(Symbol(),SYMBOL_BID);
 
-   if(stoploss != 0)
+   if(useTpSlPips)
      {
-      buySL = Ask - (stoploss * Point());
+      if(stoploss != 0)
+        {
+         buySL = Ask - (stopLoss * 10 * Point());
+        }
+      if(takeprofit != 0)
+        {
+         buyTp = Ask + (takeProfit * 10 * Point());
+        }
      }
-   if(takeprofit != 0)
+   else
      {
-      buyTp = Ask + (takeprofit * Point());
+      if(stoploss > 0)
+        {
+         buySL = stoploss;
+        }
+      if(takeprofit > 0)
+        {
+         buyTp = takeprofit;
+        }
      }
 
    double distance = MathAbs((Ask - buySL) / Point());
@@ -703,13 +732,27 @@ ulong placeSellTrade(double stoploss, double takeprofit)
    double Ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK);
    double Bid = SymbolInfoDouble(Symbol(),SYMBOL_BID);
 
-   if(stoploss != 0)
+   if(useTpSlPips)
      {
-      sellSL = Bid + (stoploss * Point());
+      if(stoploss != 0)
+        {
+         sellSL = Bid + (stopLoss * 10 * Point());
+        }
+      if(takeprofit != 0)
+        {
+         sellTp = Bid - (takeProfit * 10 * Point());
+        }
      }
-   if(takeprofit != 0)
+   else
      {
-      sellTp = Bid - (takeprofit * Point());
+      if(stoploss > 0)
+        {
+         sellSL = stoploss;
+        }
+      if(takeprofit > 0)
+        {
+         sellTp = takeprofit;
+        }
      }
    double distance = MathAbs((Bid - sellSL) / Point());
    if(trade.PositionOpen(Symbol(),ORDER_TYPE_SELL,getLot(distance),Bid,sellSL,sellTp,"Sell Trade Placed"))
@@ -941,8 +984,17 @@ void virtualSLHitCheck()
         {
          if(TimeCurrent() > newTradeStore[i].start_time && TimeCurrent() < newTradeStore[i].end_time)
            {
-            double buy_sl = newTradeStore[i].price - (newTradeStore[i].stop_loss * Point());
-            double sell_sl = newTradeStore[i].price + (newTradeStore[i].stop_loss * Point());
+            double buy_sl = 0, sell_sl = 0;
+            if(!useTpSlPips)
+              {
+               buy_sl = newTradeStore[i].stop_loss_buy;
+               sell_sl = newTradeStore[i].stop_loss_sell;
+              }
+            else
+              {
+               buy_sl = newTradeStore[i].price - (stopLoss * 10 * Point());
+               sell_sl = newTradeStore[i].price + (stopLoss * 10 * Point());
+              }
             if(newTradeStore[i].buy_hit_virtual_sl == false)
               {
                if((tickPreviousBid < buy_sl && tickCurrentBid > buy_sl))
@@ -1017,6 +1069,11 @@ void breakEven()
         {
          if(PositionGetString(POSITION_SYMBOL)==Symbol()  && PositionGetInteger(POSITION_MAGIC) == magic_no)
            {
+            if(isCounterpartOpen(ticket))
+              {
+               // counterpart still open -> skip trailing for this position
+               continue;
+              }
             //========================================================Buy Condition=========================================================================
             if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
               {
@@ -1061,6 +1118,48 @@ void breakEven()
 //+------------------------------------------------------------------+
 //|                                                                  |
 //+------------------------------------------------------------------+
+bool isCounterpartOpen(ulong ticket)
+  {
+// scan stored pairs
+   for(int k=0; k<MaxOrders; k++)
+     {
+      // check if this ticket is the buy side in the pair
+      if(newTradeStore[k].buy_ticket == ticket)
+        {
+         ulong other = newTradeStore[k].sell_ticket;
+         if(other <= 0)
+            return false; // no counterpart recorded -> treat as closed
+         // check if counterpart ticket exists in current positions
+         for(int p = PositionsTotal()-1; p >= 0; p--)
+           {
+            ulong t = PositionGetTicket(p);
+            if(t == other)
+               return true; // counterpart still open
+           }
+         return false; // counterpart not found -> closed
+        }
+
+      // check if this ticket is the sell side in the pair
+      if(newTradeStore[k].sell_ticket == ticket)
+        {
+         ulong other = newTradeStore[k].buy_ticket;
+         if(other <= 0)
+            return false; // no counterpart recorded -> treat as closed
+         for(int p = PositionsTotal()-1; p >= 0; p--)
+           {
+            ulong t = PositionGetTicket(p);
+            if(t == other)
+               return true; // counterpart still open
+           }
+         return false; // counterpart not found -> closed
+        }
+     }
+// ticket not found in the stored pairs -> treat as no counterpart open
+   return false;
+  }
+//+------------------------------------------------------------------+
+//|                                                                  |
+//+------------------------------------------------------------------+
 void Individual_Trailing()
   {
    int openedpositions;
@@ -1075,13 +1174,19 @@ void Individual_Trailing()
          ulong ticket = PositionGetTicket(i);
          if(PositionSelectByTicket(ticket))
            {
-            if(PositionGetString(POSITION_SYMBOL)==Symbol()  && PositionGetInteger(POSITION_MAGIC) ==magic_no) // only look if mygrid and symbol. ..
+            if(PositionGetString(POSITION_SYMBOL)==Symbol()  && PositionGetInteger(POSITION_MAGIC) == magic_no) // only look if mygrid and symbol. ..
               {
+               if(isCounterpartOpen(ticket))
+                 {
+                  // counterpart still open -> skip trailing for this position
+                  continue;
+                 }
 
                double SymbolAsk           = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_ASK);
                double SymbolBid           = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_BID);
                int SymbolDigits           = (int)SymbolInfoInteger(PositionGetString(POSITION_SYMBOL), SYMBOL_DIGITS);
                double SymbolTickSize      = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_TRADE_TICK_SIZE);
+
                int type= (int)PositionGetInteger(POSITION_TYPE);
 
                if(type==POSITION_TYPE_BUY) // its a long position
@@ -1154,9 +1259,11 @@ void saveNewTradeStoreFile()
       // convert values to strings
       string buyTicketStr  = IntegerToString((long)newTradeStore[i].buy_ticket);
       string sellTicketStr = IntegerToString((long)newTradeStore[i].sell_ticket);
-      string priceStr      = DoubleToString(newTradeStore[i].price, _Digits);
-      string slStr         = DoubleToString(newTradeStore[i].stop_loss, _Digits);
-      string tpStr         = DoubleToString(newTradeStore[i].take_profit, _Digits);
+      string priceStr      = DoubleToString(newTradeStore[i].price, Digits());
+      string slBuyStr      = DoubleToString(newTradeStore[i].stop_loss_buy, Digits());
+      string tpBuyStr      = DoubleToString(newTradeStore[i].take_profit_buy, Digits());
+      string slSellStr      = DoubleToString(newTradeStore[i].stop_loss_sell, Digits());
+      string tpSellStr      = DoubleToString(newTradeStore[i].take_profit_sell, Digits());
 
       string startTimeStr  = (newTradeStore[i].start_time != 0) ? TimeToString(newTradeStore[i].start_time, TIME_DATE|TIME_SECONDS) : "";
       string endTimeStr    = (newTradeStore[i].end_time   != 0) ? TimeToString(newTradeStore[i].end_time, TIME_DATE|TIME_SECONDS)   : "";
@@ -1185,7 +1292,8 @@ void saveNewTradeStoreFile()
       // build CSV line and write
       string line = buyTicketStr + "," + sellTicketStr + "," +
                     newTradeStore[i].symbol + "," +
-                    priceStr + "," + slStr + "," + tpStr + "," +
+                    priceStr + "," + slBuyStr + "," + tpBuyStr + "," +
+                    slSellStr + "," + tpSellStr + "," +
                     startTimeStr + "," + endTimeStr + "," +
                     buyHitStr + "," + sellHitStr + "\r\n";
 
@@ -1220,8 +1328,10 @@ void loadNewTradeStoreFile()
       newTradeStore[j].sell_ticket          = (ulong)-1;
       newTradeStore[j].symbol               = "";
       newTradeStore[j].price                = 0.0;
-      newTradeStore[j].stop_loss            = 0.0;
-      newTradeStore[j].take_profit          = 0.0;
+      newTradeStore[j].stop_loss_buy        = 0.0;
+      newTradeStore[j].take_profit_buy      = 0.0;
+      newTradeStore[j].stop_loss_sell       = 0.0;
+      newTradeStore[j].take_profit_sell     = 0.0;
       newTradeStore[j].start_time           = 0;
       newTradeStore[j].end_time             = 0;
       newTradeStore[j].buy_hit_virtual_sl   = false;
@@ -1238,24 +1348,26 @@ void loadNewTradeStoreFile()
       string tokens[];
       int total = StringSplit(line, ',', tokens);
 
-      if(total >= 10)
+      if(total >= 12)
         {
          newTradeStore[idx].buy_ticket  = (ulong)tokens[0];
          newTradeStore[idx].sell_ticket = (ulong)tokens[1];
          newTradeStore[idx].symbol      = tokens[2];
          newTradeStore[idx].price       = StringToDouble(tokens[3]);
-         newTradeStore[idx].stop_loss   = StringToDouble(tokens[4]);
-         newTradeStore[idx].take_profit = StringToDouble(tokens[5]);
+         newTradeStore[idx].stop_loss_buy   = StringToDouble(tokens[4]);
+         newTradeStore[idx].take_profit_buy = StringToDouble(tokens[5]);
+         newTradeStore[idx].stop_loss_sell  = StringToDouble(tokens[6]);
+         newTradeStore[idx].take_profit_sell = StringToDouble(tokens[7]);
 
-         string sStart = tokens[6];
-         string sEnd   = tokens[7];
+         string sStart = tokens[8];
+         string sEnd   = tokens[9];
          newTradeStore[idx].start_time = (StringLen(sStart) > 0) ? StringToTime(sStart) : 0;
          newTradeStore[idx].end_time   = (StringLen(sEnd)   > 0) ? StringToTime(sEnd)   : 0;
 
          bool bHit = false;
          bool sHit = false;
 
-         if(tokens[8] == "true")
+         if(tokens[10] == "true")
            {
             bHit = true;
            }
@@ -1264,7 +1376,7 @@ void loadNewTradeStoreFile()
             bHit = false;
            }
 
-         if(tokens[9] == "true")
+         if(tokens[11] == "true")
            {
             sHit = true;
            }
@@ -1282,9 +1394,11 @@ void loadNewTradeStoreFile()
             " buy_ticket=", newTradeStore[idx].buy_ticket,
             " sell_ticket=", newTradeStore[idx].sell_ticket,
             " symbol=", newTradeStore[idx].symbol,
-            " price=", DoubleToString(newTradeStore[idx].price, _Digits),
-            " \n sl=", DoubleToString(newTradeStore[idx].stop_loss, _Digits),
-            " tp=", DoubleToString(newTradeStore[idx].take_profit, _Digits),
+            " price=", DoubleToString(newTradeStore[idx].price, Digits()),
+            " \n sl buy=", DoubleToString(newTradeStore[idx].stop_loss_buy, Digits()),
+            " tp buy=", DoubleToString(newTradeStore[idx].take_profit_buy, Digits()),
+            " sl sell=", DoubleToString(newTradeStore[idx].stop_loss_sell, Digits()),
+            " tp sell=", DoubleToString(newTradeStore[idx].take_profit_sell, Digits()),
             " start=", (newTradeStore[idx].start_time != 0 ? TimeToString(newTradeStore[idx].start_time, TIME_DATE|TIME_SECONDS) : ""),
             " end=", (newTradeStore[idx].end_time   != 0 ? TimeToString(newTradeStore[idx].end_time,   TIME_DATE|TIME_SECONDS) : ""),
             " buyHit=", newTradeStore[idx].buy_hit_virtual_sl,