Pārlūkot izejas kodu

Ticket: 5131 Virtual Sl Hit & Filing for Ea Restart

Huzaifa-MQLDev 9 mēneši atpakaļ
vecāks
revīzija
9e9296189b
2 mainītis faili ar 443 papildinājumiem un 72 dzēšanām
  1. BIN
      vol_hedge_strategy_mt5.ex5
  2. 443 72
      vol_hedge_strategy_mt5.mq5

BIN
vol_hedge_strategy_mt5.ex5


+ 443 - 72
vol_hedge_strategy_mt5.mq5

@@ -57,19 +57,24 @@ void PrintStructure();
 
 struct new_trade_store
   {
-   ulong             buy_ticket;     // Buy Ticket
-   ulong             sell_ticket;    // Sell Ticket
-   string            symbol;         // Symbol
-   double            price;          // Price
-   double            stop_loss;      // StopLoss
-   double            take_profit;    // TakeProfit
-   datetime          start_time;     // Start time
-   datetime          end_time;       // End Time
+   ulong             buy_ticket;            // Buy Ticket
+   ulong             sell_ticket;           // Sell Ticket
+   string            symbol;                // Symbol
+   double            price;                 // Price
+   double            stop_loss;             // StopLoss
+   double            take_profit;           // TakeProfit
+   datetime          start_time;            // Start time
+   datetime          end_time;              // End Time
+   bool              buy_hit_virtual_sl;    // Buy Hit Virtual StopLoss
+   bool              sell_hit_virtual_sl;   // Sell Hit Virtual StopLoss
 
                      new_trade_store()
      {
       buy_ticket = -1;
       sell_ticket = -1;
+      price = 0;
+      buy_hit_virtual_sl = false;
+      sell_hit_virtual_sl = false;
      }
 
   };
@@ -89,6 +94,7 @@ input        int                     maxTrades                  = 2;
 input        int                     maxSlippage                = 5;               // Max Slippage
 input        bool                    enableSpreadFilter         = false;           // Enable Spread Filter
 input        double                  maximumSpread              = 10;              // Maximum Spread
+input        string                  dataFileName               = "vol_hedge_data.csv"; // Data File Name
 
 input        string                  string_1                   = "<><><><><><> Lot Management<><><><><><>";   //__
 input        lotcalculator           lot_calculator             = fix;             // Lot Size Option
@@ -106,6 +112,11 @@ input        bool                    indivial_trailing          = false;
 input        double                  ts_sl                      = 15;              // Trailing Start in Pips
 input        double                  ts                         = 5;               // Trailing Stop in Pips
 
+input        string                  strMA14                    ="<><><><><><> BreakEven Settings <><><><><><>";//_
+input        bool                    UseBreakEven               = false;           // Use Break Even
+input        int                     breakEvenPoints            = 15;              // BreakEven Trigger Pips
+input        int                     breakStopPoint             = 5;               // BreakEven Above OpenPrice Pips
+
 input        string                  news                       = "<><><><><><> News Settings <><><><><><>";         // News
 input        NewsCloseOrder          newsClose                  = CloseAllRunningOrder; // On News Action on Running Orders
 input        bool                    High_Impact_News           = true;                 //High Impact News
@@ -132,6 +143,7 @@ datetime startSessionTime, endSessionTime;
 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";
+double levelsAre[];
 //+------------------------------------------------------------------+
 //|                                                                  |
 //+------------------------------------------------------------------+
@@ -145,7 +157,12 @@ int OnInit()
    trade.LogLevel(LOG_LEVEL_ALL);
    trade.SetAsyncMode(false);
 
-   int filehandle = FileOpen("vol_hedge_data.csv", FILE_READ | FILE_CSV | FILE_COMMON | FILE_ANSI);
+   if(!MQLInfoInteger(MQL_TESTER))
+     {
+      loadNewTradeStoreFile();
+     }
+
+   int filehandle = FileOpen(dataFileName, FILE_READ | FILE_CSV | FILE_COMMON | FILE_ANSI);
    if(filehandle != INVALID_HANDLE)
      {
       Print(" Valid Handler. ");
@@ -177,14 +194,32 @@ int OnInit()
                datetime start_local     = StringToTime(orderData[4]);
                datetime end_local       = StringToTime(orderData[5]);
 
+               ArrayResize(levelsAre,ArraySize(levelsAre)+1);
+               levelsAre[ArraySize(levelsAre) - 1] = price_local;
+
                // OPTIONAL: only add when price == 0:
                // if(MathAbs(price_local) > 1e-9) { Print("Skipped: price != 0"); continue; }
+               bool buy_virtual_tp_hit = true;
+               bool sell_virtual_tp_hit = true;
+               if(bothHitsSl)
+                 {
+                  buy_virtual_tp_hit = false;
+                  sell_virtual_tp_hit = false;
+                 }
 
                // call the single-responsibility function that writes into struct array
-               addToNewTradeStore(buy_ticket_local, sell_ticket_local,
-                                  symbol_local, price_local,
-                                  sl_local, tp_local,
-                                  start_local, end_local);
+               if(!level_present(price_local))
+                 {
+                  addToNewTradeStore(buy_ticket_local, sell_ticket_local,
+                                     symbol_local, price_local,
+                                     sl_local, tp_local,
+                                     start_local, end_local,
+                                     buy_virtual_tp_hit, sell_virtual_tp_hit);
+                 }
+               else
+                 {
+                  Print("Level is already Present. Level: ", price_local);
+                 }
               }
            }
         }
@@ -195,6 +230,8 @@ int OnInit()
       Print(" InValid Handler. Error: ", GetLastError());
      }
 
+   struct_level_check();
+
    timeFilter(true,start_time_session, end_time_session, startSessionTime, endSessionTime);
    Print(" Session Start  = ", startSessionTime,  " Asian  Session End = ", endSessionTime);
 
@@ -232,7 +269,10 @@ int OnInit()
 void OnDeinit(const int reason)
   {
 //---
-
+   if(!MQLInfoInteger(MQL_TESTER))
+     {
+      saveNewTradeStoreFile();
+     }
   }
 //+------------------------------------------------------------------+
 //| Expert tick function                                             |
@@ -358,6 +398,10 @@ void mainActivity()
      {
       Individual_Trailing();
      }
+   if(UseBreakEven)
+     {
+      breakEven();
+     }
    double Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
    double Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
 
@@ -388,11 +432,12 @@ void mainActivity()
 // Comment(" Session Start  = ", startSessionTime,  " Asian  Session End = ", endSessionTime);
    if((!enableTimeSession) || (enableTimeSession && TimeCurrent() >= startSessionTime && TimeCurrent() <= endSessionTime))
      {
-      tradePlacingCheck();
+      removeFromStructure();
       if(bothHitsSl)
         {
-         removeBuySellOnSlHit();
+         virtualSLHitCheck();
         }
+      tradePlacingCheck();
      }
   }
 //+------------------------------------------------------------------+
@@ -475,33 +520,106 @@ int orderCount(int type)
 //+------------------------------------------------------------------+
 //|                                                                  |
 //+------------------------------------------------------------------+
+bool level_present(double priceIs)
+  {
+   for(int i = 0 ; i < MaxOrders ; i++)
+     {
+      if(newTradeStore[i].price > 0)
+        {
+         if(priceIs == newTradeStore[i].price)
+           {
+            return true;
+           }
+        }
+     }
+   return false;
+  }
+//+------------------------------------------------------------------+
+//|                                                                  |
+//+------------------------------------------------------------------+
+void struct_level_check()
+  {
+   for(int i = 0; i < MaxOrders; i++)
+     {
+      if(newTradeStore[i].price > 0)
+        {
+         bool found = false;
+
+         for(int j = 0; j < ArraySize(levelsAre); j++)
+           {
+            if(newTradeStore[i].price == levelsAre[j])
+              {
+               found = true;
+               break;
+              }
+           }
+
+         if(!found)
+           {
+            Print("Price not found in levelsAre[] -> index:", i, " | price:", newTradeStore[i].price);
+            newTradeStore[i].buy_ticket  = (ulong)-1;
+            newTradeStore[i].sell_ticket = (ulong)-1;
+            bool buy_virtual_tp_hit = true;
+            bool sell_virtual_tp_hit = true;
+            if(bothHitsSl)
+              {
+               buy_virtual_tp_hit = false;
+               sell_virtual_tp_hit = false;
+              }
+            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;
+            return;
+           }
+        }
+     }
+
+   return;
+  }
+
+//+------------------------------------------------------------------+
+//|                                                                  |
+//+------------------------------------------------------------------+
 void addToNewTradeStore(ulong r_buy_ticket, ulong r_sell_ticket,
                         string r_symbol, double r_price,
                         double r_stop_loss, double r_take_profit,
-                        datetime r_start_time, datetime r_end_time)
+                        datetime r_start_time, datetime r_end_time, bool r_buy_hit_sl, bool r_sell_hit_sl)
   {
+   Print(" Tier 1. ");
    for(int i = 0; i < MaxOrders; i++)
      {
       // treat slot as empty when both tickets are -1 (same convention as constructor)
       if(newTradeStore[i].buy_ticket == -1 && newTradeStore[i].sell_ticket == -1)
         {
-         newTradeStore[i].buy_ticket  = r_buy_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].start_time  = r_start_time;
-         newTradeStore[i].end_time    = r_end_time;
-
-         Print("Stored -> idx: ", i,
-               " | sym: ", newTradeStore[i].symbol,
-               " | price: ", DoubleToString(newTradeStore[i].price, Digits()),
-               " | sl: ", DoubleToString(newTradeStore[i].stop_loss, Digits()),
-               " | tp: ", DoubleToString(newTradeStore[i].take_profit, Digits()),
-               " | start: ", TimeToString(newTradeStore[i].start_time, TIME_DATE|TIME_SECONDS),
-               " | end: ", TimeToString(newTradeStore[i].end_time, TIME_DATE|TIME_SECONDS));
-         break;
+         if(newTradeStore[i].price == 0)
+           {
+            newTradeStore[i].buy_ticket  = r_buy_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].start_time  = r_start_time;
+            newTradeStore[i].end_time    = r_end_time;
+            newTradeStore[i].buy_hit_virtual_sl = r_buy_hit_sl;
+            newTradeStore[i].sell_hit_virtual_sl = r_sell_hit_sl;
+
+            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()),
+                  " | 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,
+                  " | Sell Virtual Sl Hit: ", newTradeStore[i].sell_hit_virtual_sl);
+            break;
+           }
         }
      }
   }
@@ -518,19 +636,22 @@ void tradePlacingCheck()
            {
             if(TimeCurrent() > newTradeStore[i].start_time && TimeCurrent() < newTradeStore[i].end_time)
               {
-               double levelPriceIs = newTradeStore[i].price;
-               if((tickPreviousBid > levelPriceIs && tickCurrentBid < levelPriceIs) ||
-                  (tickPreviousBid < levelPriceIs && tickCurrentBid > levelPriceIs))
+               if(newTradeStore[i].buy_hit_virtual_sl == true && newTradeStore[i].sell_hit_virtual_sl == true)
                  {
-                  if(countLiveTrades() < maxTrades)
+                  double levelPriceIs = newTradeStore[i].price;
+                  if((tickPreviousBid > levelPriceIs && tickCurrentBid < levelPriceIs) ||
+                     (tickPreviousBid < levelPriceIs && tickCurrentBid > levelPriceIs))
                     {
-                     if((enableSpreadFilter && spreadFilter()) || !enableSpreadFilter)
+                     if(countLiveTrades() < maxTrades)
                        {
-                        ulong buyTicket = placeBuyTrade(newTradeStore[i].stop_loss, newTradeStore[i].take_profit);
-                        ulong sellTicket = placeSellTrade(newTradeStore[i].stop_loss, newTradeStore[i].take_profit);
+                        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);
 
-                        newTradeStore[i].buy_ticket = buyTicket;
-                        newTradeStore[i].sell_ticket = sellTicket;
+                           newTradeStore[i].buy_ticket = buyTicket;
+                           newTradeStore[i].sell_ticket = sellTicket;
+                          }
                        }
                     }
                  }
@@ -754,7 +875,7 @@ void timeFilter(bool onInit,string startTime,string endTime,datetime & sessionSt
 //+------------------------------------------------------------------+
 //|                                                                  |
 //+------------------------------------------------------------------+
-void removeBuySellOnSlHit()
+void removeFromStructure()
   {
    for(int i = 0 ; i < MaxOrders ; i++)
      {
@@ -787,18 +908,24 @@ void removeBuySellOnSlHit()
 
          if(!isBuyPresent && !isSellPresent)
            {
-            if(tradeHitSL(newTradeStore[i].buy_ticket) && tradeHitSL(newTradeStore[i].sell_ticket))
+            Print("Buy/Sell Ticket is closed so removed from struct. Buy Ticket: ", newTradeStore[i].buy_ticket, " Sell Ticket: ", newTradeStore[i].sell_ticket);
+            newTradeStore[i].buy_ticket  = (ulong)-1;
+            newTradeStore[i].sell_ticket = (ulong)-1;
+            bool buy_virtual_tp_hit = true;
+            bool sell_virtual_tp_hit = true;
+            if(bothHitsSl)
               {
-               Print("Buy/Sell Ticket is closed on StopLoss so removed from struct. Buy Ticket: ", newTradeStore[i].buy_ticket, " Sell Ticket: ", newTradeStore[i].sell_ticket);
-               newTradeStore[i].buy_ticket  = (ulong)-1;
-               newTradeStore[i].sell_ticket = (ulong)-1;
-               //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;
+               buy_virtual_tp_hit = false;
+               sell_virtual_tp_hit = false;
               }
+            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;
            }
         }
      }
@@ -806,33 +933,35 @@ void removeBuySellOnSlHit()
 //+------------------------------------------------------------------+
 //|                                                                  |
 //+------------------------------------------------------------------+
-bool tradeHitSL(ulong positionID)
+void virtualSLHitCheck()
   {
-
-   if(HistorySelectByPosition(positionID))
+   for(int i = 0 ; i < MaxOrders ; i++)
      {
-      for(int i = 0; i < HistoryDealsTotal(); i++)
+      if(newTradeStore[i].buy_ticket == -1 && newTradeStore[i].sell_ticket == -1)
         {
-         ulong dealTicket = HistoryDealGetTicket(i);
-         ulong dealPositionID = HistoryDealGetInteger(dealTicket, DEAL_POSITION_ID);
-
-         if(HistoryDealGetInteger(dealTicket, DEAL_ENTRY) == DEAL_ENTRY_OUT && dealPositionID == positionID)
+         if(TimeCurrent() > newTradeStore[i].start_time && TimeCurrent() < newTradeStore[i].end_time)
            {
-            int dealType = (int)HistoryDealGetInteger(dealTicket, DEAL_TYPE);
-            string comment = HistoryDealGetString(dealTicket, DEAL_COMMENT);
-
-            if(StringFind(comment, "sl", 0) >= 0)
+            double buy_sl = newTradeStore[i].price - (newTradeStore[i].stop_loss * Point());
+            double sell_sl = newTradeStore[i].price + (newTradeStore[i].stop_loss * Point());
+            if(newTradeStore[i].buy_hit_virtual_sl == false)
               {
-               //               if(dealType == DEAL_TYPE_BUY)
-               //                 {
-               //
-               //                 }
-               return true;
+               if((tickPreviousBid < buy_sl && tickCurrentBid > buy_sl))
+                 {
+                  newTradeStore[i].buy_hit_virtual_sl = true;
+                  Print(" Buy Virtual Sl Hit. newTradeStore[i].buy_hit_virtual_sl: ", newTradeStore[i].buy_hit_virtual_sl, " Order Price is: ", newTradeStore[i].price, " Stop Loss Price is: ", buy_sl, " Time Virtual Sl Hit is: ", TimeCurrent());
+                 }
+              }
+            if(newTradeStore[i].sell_hit_virtual_sl == false)
+              {
+               if((tickPreviousAsk > sell_sl && tickCurrentAsk < sell_sl))
+                 {
+                  newTradeStore[i].sell_hit_virtual_sl = true;
+                  Print(" Sell Virtual Sl Hit. newTradeStore[i].sell_hit_virtual_sl: ", newTradeStore[i].sell_hit_virtual_sl, " Order Price is: ", newTradeStore[i].price, " Stop Loss Price is: ", sell_sl, " Time Virtual Sl Hit is: ", TimeCurrent());
+                 }
               }
            }
         }
      }
-   return false;
   }
 //+------------------------------------------------------------------+
 //|                                                                  |
@@ -875,6 +1004,63 @@ bool spreadFilter()
 //+------------------------------------------------------------------+
 //|                                                                  |
 //+------------------------------------------------------------------+
+void breakEven()
+  {
+   for(int i = PositionsTotal()-1; i>=0; i--)
+     {
+      ulong ticket = PositionGetTicket(i);
+      string symbol=PositionGetSymbol(i);
+      double mySL = 0,newSL = 0;
+      double SymbolTickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
+      ////Print("ticket ",ticket," Symbol : ",symbol);
+      if(PositionSelectByTicket(ticket))
+        {
+         if(PositionGetString(POSITION_SYMBOL)==Symbol()  && PositionGetInteger(POSITION_MAGIC) == magic_no)
+           {
+            //========================================================Buy Condition=========================================================================
+            if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
+              {
+               mySL = PositionGetDouble(POSITION_PRICE_OPEN) + (breakEvenPoints* 10 * SymbolTickSize);
+               if(SymbolInfoDouble(Symbol(),SYMBOL_BID) >= mySL && PositionGetDouble(POSITION_PRICE_OPEN) > PositionGetDouble(POSITION_SL))
+                 {
+                  newSL= PositionGetDouble(POSITION_PRICE_OPEN) + (breakStopPoint* 10 * SymbolTickSize);
+                  if(trade.PositionModify(ticket,newSL,PositionGetDouble(POSITION_TP)))
+                    {
+
+                     Print("Buy Order BreakEven Successfully ");
+                    }
+                  else
+                    {
+                     Print("Error in BreakEven Buy Position ",GetLastError());
+                    }
+                 }
+              }
+            //=======================================================Sell condition  ===============================================================
+            if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
+              {
+               mySL = PositionGetDouble(POSITION_PRICE_OPEN) - (breakEvenPoints* 10 * SymbolTickSize);
+               if(SymbolInfoDouble(Symbol(),SYMBOL_ASK) <= mySL && PositionGetDouble(POSITION_SL) > PositionGetDouble(POSITION_PRICE_OPEN))
+                 {
+                  newSL = PositionGetDouble(POSITION_PRICE_OPEN) - (breakStopPoint* 10 * SymbolTickSize);
+
+                  if(trade.PositionModify(ticket,newSL,PositionGetDouble(POSITION_TP)))
+                    {
+                     Print("Order Sell BreakEven Successfully ");
+                    }
+                  else
+                    {
+                     Print("Error in BreakEven Sell Position ",GetLastError());
+                    }
+                 }
+              }
+           }
+        }
+
+     }
+  }
+//+------------------------------------------------------------------+
+//|                                                                  |
+//+------------------------------------------------------------------+
 void Individual_Trailing()
   {
    int openedpositions;
@@ -934,5 +1120,190 @@ void Individual_Trailing()
 //+------------------------------------------------------------------+
 //|                                                                  |
 //+------------------------------------------------------------------+
+void saveNewTradeStoreFile()
+  {
+// don't run in strategy tester
+   if(MQLInfoInteger(MQL_TESTER))
+      return;
+
+   string file_name = "new_trade_store.csv";
+   int fileHandle = FileOpen(file_name,
+                             FILE_WRITE | FILE_CSV | FILE_COMMON |
+                             FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_READ);
+   if(fileHandle == INVALID_HANDLE)
+     {
+      PrintFormat("saveNewTradeStoreFile() -> Cannot open file '%s'. Error: %d", file_name, GetLastError());
+      return;
+     }
+
+// header (optional) - comment out if you don't want header
+//string header = "buy_ticket,sell_ticket,symbol,price,stop_loss,take_profit,start_time,end_time,buy_hit_virtual_sl,sell_hit_virtual_sl\r\n";
+//FileWriteString(fileHandle, header);
+
+   for(int i = 0; i < MaxOrders; i++)
+     {
+      // decide whether this slot has useful data:
+      // you can tweak this condition as you prefer (symbol != "" is simple)
+      bool slotPopulated = (StringLen(newTradeStore[i].symbol) > 0)
+                           || (newTradeStore[i].price != 0.0)
+                           || (newTradeStore[i].start_time != 0);
+
+      if(!slotPopulated)
+         continue;
+
+      // 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 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)   : "";
+
+      string buyHitStr  = ""; // IntegerToString(newTradeStore[i].buy_hit_virtual_sl  ? 1 : 0);
+      string sellHitStr = ""; // IntegerToString(newTradeStore[i].sell_hit_virtual_sl ? 1 : 0);
+
+      if(newTradeStore[i].buy_hit_virtual_sl == true)
+        {
+         buyHitStr = "true";
+        }
+      else
+        {
+         buyHitStr = "false";
+        }
+
+      if(newTradeStore[i].sell_hit_virtual_sl == true)
+        {
+         sellHitStr = "true";
+        }
+      else
+        {
+         sellHitStr = "false";
+        }
+
+      // build CSV line and write
+      string line = buyTicketStr + "," + sellTicketStr + "," +
+                    newTradeStore[i].symbol + "," +
+                    priceStr + "," + slStr + "," + tpStr + "," +
+                    startTimeStr + "," + endTimeStr + "," +
+                    buyHitStr + "," + sellHitStr + "\r\n";
+
+      FileWriteString(fileHandle, line);
+     }
+
+   FileClose(fileHandle);
+   PrintFormat("saveNewTradeStoreFile() -> saved to '%s'.", file_name);
+  }
+//+------------------------------------------------------------------+
+//|                                                                  |
+//+------------------------------------------------------------------+
+void loadNewTradeStoreFile()
+  {
+   if(MQLInfoInteger(MQL_TESTER))
+      return;
+
+   string file_name = "new_trade_store.csv";
+   int fileHandle = FileOpen(file_name,
+                             FILE_READ | FILE_CSV | FILE_COMMON |
+                             FILE_SHARE_READ | FILE_SHARE_WRITE);
+   if(fileHandle == INVALID_HANDLE)
+     {
+      Print("loadNewTradeStoreFile() -> Cannot open file '", file_name, "'. Error: ", GetLastError());
+      return;
+     }
+
+// reset defaults
+   for(int j = 0; j < MaxOrders; j++)
+     {
+      newTradeStore[j].buy_ticket           = (ulong)-1;
+      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].start_time           = 0;
+      newTradeStore[j].end_time             = 0;
+      newTradeStore[j].buy_hit_virtual_sl   = false;
+      newTradeStore[j].sell_hit_virtual_sl  = false;
+     }
+
+   int idx = 0;
+   while(!FileIsEnding(fileHandle) && idx < MaxOrders)
+     {
+      string line = FileReadString(fileHandle);
+      if(StringLen(line) == 0)
+         continue;
+
+      string tokens[];
+      int total = StringSplit(line, ',', tokens);
+
+      if(total >= 10)
+        {
+         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]);
+
+         string sStart = tokens[6];
+         string sEnd   = tokens[7];
+         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")
+           {
+            bHit = true;
+           }
+         else
+           {
+            bHit = false;
+           }
+
+         if(tokens[9] == "true")
+           {
+            sHit = true;
+           }
+         else
+           {
+            sHit = false;
+           }
+
+         newTradeStore[idx].buy_hit_virtual_sl  = bHit;
+         newTradeStore[idx].sell_hit_virtual_sl = sHit;
+
+         // --- simple Print instead of PrintFormat ---
+         Print(
+            "Loaded newTradeStore[", idx, "]:",
+            " 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),
+            " 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,
+            " sellHit=", newTradeStore[idx].sell_hit_virtual_sl
+         );
+
+         idx++;
+        }
+      else
+        {
+         Print("loadNewTradeStoreFile(): skipping malformed line (tokens=", total, "): ", line);
+        }
+     }
+
+   FileClose(fileHandle);
+   Print("loadNewTradeStoreFile() -> loaded ", idx, " entries from '", file_name, "'.");
+  }
+//+------------------------------------------------------------------+
+//|                                                                  |
+//+------------------------------------------------------------------+
 
 //+------------------------------------------------------------------+