浏览代码

Ticket: 5131 Trade Placing and File Fetching Data Store

Huzaifa-MQLDev 9 月之前
父节点
当前提交
4ba076e1ff
共有 2 个文件被更改,包括 452 次插入0 次删除
  1. 二进制
      vol_hedge_strategy_mt5.ex5
  2. 452 0
      vol_hedge_strategy_mt5.mq5

二进制
vol_hedge_strategy_mt5.ex5


+ 452 - 0
vol_hedge_strategy_mt5.mq5

@@ -0,0 +1,452 @@
+//+------------------------------------------------------------------+
+//|                                       vol_hedge_strategy_mt5.mq5 |
+//|                                  Copyright 2025, MQL Development |
+//|                                  https://www.mqldevelopment.com/ |
+//+------------------------------------------------------------------+
+#property copyright "Copyright 2025, MQL Development"
+#property link      "https://www.mqldevelopment.com/"
+#property version   "1.00"
+#define MaxOrders 100
+#include <Trade\Trade.mqh>
+CTrade  trade;
+//+------------------------------------------------------------------+
+//| Expert initialization function                                   |
+//+------------------------------------------------------------------+
+
+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
+
+                     new_trade_store()
+     {
+      buy_ticket = -1;
+      sell_ticket = -1;
+     }
+
+  };
+new_trade_store newTradeStore[MaxOrders];
+
+enum lotcalculator
+  {
+   fix, //Fixed Lot Size
+   rsk, //Risk Percentage
+   dollar, // Risk in Dollars
+  };
+
+sinput       string                  string_0                   = "<><><><><><> General SETTINGS <><><><><><>";   //__
+input        int                     magic_no                   = 333;             // Magic no
+
+input        string                  string_1                   = "<><><><><><> Lot Management<><><><><><>";   //__
+input        lotcalculator           lot_calculator             = fix;             // Lot Size Option
+input        double                  lot_amount                 = 0.1;             // Lot Size
+input        double                  risk                       = 0.5;             // Risk in Percentage %
+input        double                  dollars                    = 10;              // Risk in GBP
+
+input        string                  string_2                   = "<><><><><><> Time Filter Setting <><><><><><> ";//_
+input        bool                    enableTimeSession          = false;           // Enable Time Session
+input        string                  start_time                 = "01:00";         // Start Session
+input        string                  end_time                   = "23:59";         // End Session
+
+// Global Variables
+static double tickCurrentBid = 0;
+double tickPreviousBid = 0;
+static double tickCurrentAsk = 0;
+double tickPreviousAsk = 0;
+datetime startSessionTime, endSessionTime;
+//+------------------------------------------------------------------+
+//|                                                                  |
+//+------------------------------------------------------------------+
+int OnInit()
+  {
+//---
+   Print(" OnInIt. ");
+
+   trade.SetExpertMagicNumber(magic_no);
+   trade.SetDeviationInPoints(10);
+   trade.SetTypeFilling(ORDER_FILLING_IOC);
+   trade.LogLevel(LOG_LEVEL_ALL);
+   trade.SetAsyncMode(false);
+
+   int filehandle = FileOpen("vol_hedge_data.csv", FILE_READ | FILE_CSV | FILE_COMMON | FILE_ANSI);
+   if(filehandle != INVALID_HANDLE)
+     {
+      Print(" Valid Handler. ");
+      while(!FileIsEnding(filehandle))
+        {
+         string orderToRead = FileReadString(filehandle);
+         string orderData[];
+         //Print("Data: ", OrderToRead);
+         StringSplit(orderToRead, StringGetCharacter(",",0), orderData);
+         Print("Array Size: ", ArraySize(orderData));
+         Print(" Order is: ", orderToRead);
+         for(int i = 0 ; i < ArraySize(orderData) ; i++)
+           {
+            Print(" Order Data: ", orderData[i], " i: ", i);
+           }
+
+         if(ArraySize(orderData) >= 6)
+           {
+            if(orderData[0] == Symbol())
+              {
+               // store into local variables first (trim if needed)
+               ulong  buy_ticket_local  = (ulong)-1; // keep -1 as per your convention
+               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]);
+               // 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]);
+
+               // OPTIONAL: only add when price == 0:
+               // if(MathAbs(price_local) > 1e-9) { Print("Skipped: price != 0"); continue; }
+
+               // 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);
+              }
+           }
+        }
+      FileClose(filehandle);
+     }
+   else
+     {
+      Print(" InValid Handler. Error: ", GetLastError());
+     }
+
+   timeFilter(true,start_time, end_time, startSessionTime, endSessionTime);
+   Print(" Session Start  = ", startSessionTime,  " Asian  Session End = ", endSessionTime);
+//---
+   return(INIT_SUCCEEDED);
+  }
+//+------------------------------------------------------------------+
+//| Expert deinitialization function                                 |
+//+------------------------------------------------------------------+
+void OnDeinit(const int reason)
+  {
+//---
+
+  }
+//+------------------------------------------------------------------+
+//| Expert tick function                                             |
+//+------------------------------------------------------------------+
+void OnTick()
+  {
+//---
+   double Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
+   double Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
+
+   if(tickPreviousBid == 0 && tickCurrentBid == 0)
+     {
+      tickPreviousBid = Bid;
+      tickCurrentBid  = Bid;
+     }
+   else
+     {
+      tickPreviousBid = tickCurrentBid;
+      tickCurrentBid  = Bid;
+     }
+
+   if(tickPreviousAsk == 0 && tickCurrentAsk == 0)
+     {
+      tickPreviousAsk = Ask;
+      tickCurrentAsk  = Ask;
+     }
+   else
+     {
+      tickPreviousAsk = tickCurrentAsk;
+      tickCurrentAsk  = Ask;
+     }
+
+// Print(" Time is: ", TimeCurrent());
+   timeFilter(false,start_time, end_time, startSessionTime, endSessionTime);
+   Comment(" Session Start  = ", startSessionTime,  " Asian  Session End = ", endSessionTime);
+   if((!enableTimeSession) || (enableTimeSession && TimeCurrent() >= startSessionTime && TimeCurrent() <= endSessionTime))
+     {
+      tradePlacingCheck();
+     }
+  }
+//+------------------------------------------------------------------+
+//+------------------------------------------------------------------+
+//|                                                                  |
+//+------------------------------------------------------------------+
+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)
+  {
+   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;
+        }
+     }
+  }
+//+------------------------------------------------------------------+
+//|                                                                  |
+//+------------------------------------------------------------------+
+void tradePlacingCheck()
+  {
+   for(int i = 0; i < MaxOrders; i++)
+     {
+      if(newTradeStore[i].buy_ticket == -1 && newTradeStore[i].sell_ticket == -1)
+        {
+         if(newTradeStore[i].price > 0)
+           {
+            double levelPriceIs = newTradeStore[i].price;
+            if((tickPreviousBid > levelPriceIs && tickCurrentBid < levelPriceIs) ||
+               (tickPreviousBid < levelPriceIs && tickCurrentBid > levelPriceIs))
+              {
+               ulong buyTicket = placeBuyTrade(newTradeStore[i].stop_loss, newTradeStore[i].take_profit);
+               ulong sellTicket = 0; // placeSellTrade(newTradeStore[i].stop_loss, newTradeStore[i].take_profit);
+
+               newTradeStore[i].buy_ticket = buyTicket;
+               newTradeStore[i].sell_ticket = sellTicket;
+              }
+           }
+        }
+     }
+  }
+//+------------------------------------------------------------------+
+//|                                                                  |
+//+------------------------------------------------------------------+
+ulong placeBuyTrade(double stoploss, double takeprofit)
+  {
+
+   double buySL = 0, buyTp=0;
+//openPrice = SymbolInfoDouble(Symbol(),SYMBOL_ASK);
+   double Ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK);
+   double Bid = SymbolInfoDouble(Symbol(),SYMBOL_BID);
+
+   if(stoploss != 0)
+     {
+      buySL = Ask - (stoploss * Point());
+     }
+   if(takeprofit != 0)
+     {
+      buyTp = Ask + (takeprofit * Point());
+     }
+
+   double distance = MathAbs((Ask - buySL) / Point());
+   if(trade.PositionOpen(Symbol(),ORDER_TYPE_BUY,getLot(distance),Ask,buySL,buyTp,"Buy Trade Placed"))
+     {
+      Print("Buy Trade Placed: ",trade.ResultOrder());
+      return trade.ResultOrder();
+     }
+   else
+     {
+      Print("Error in placing Buy: "+Symbol()+"  ",GetLastError());
+      return -1;
+     }
+   return -1;
+  }
+//+------------------------------------------------------------------+
+//|                                                                  |
+//+------------------------------------------------------------------+
+ulong placeSellTrade(double stoploss, double takeprofit)
+  {
+
+   double sellSL = 0, sellTp = 0;
+   double Ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK);
+   double Bid = SymbolInfoDouble(Symbol(),SYMBOL_BID);
+
+   if(stoploss != 0)
+     {
+      sellSL = Bid + (stoploss * Point());
+     }
+   if(takeprofit != 0)
+     {
+      sellTp = Bid - (takeprofit * Point());
+     }
+   double distance = MathAbs((Bid - sellSL) / Point());
+   if(trade.PositionOpen(Symbol(),ORDER_TYPE_SELL,getLot(distance),Bid,sellSL,sellTp,"Sell Trade Placed"))
+     {
+      Print("Sell Trade PLaced: ",trade.ResultOrder());
+      return trade.ResultOrder();
+     }
+   else
+     {
+      Print("Error in placing Sell: "+Symbol()+"  ",GetLastError());
+      return -1;
+     }
+   return -1;
+  }
+//+------------------------------------------------------------------+
+//|                                                                  |
+//+------------------------------------------------------------------+
+double getLot(double stop_loss)
+  {
+   Print("Tick Value: ",SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE));
+   Print("Tick Size: ",SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE));
+   double modeTickV=SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE)
+                    ,modeTickS=SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE);
+// Print("Pip value: ", NormalizeDouble(((SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE)/(SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE)/Point))*10),2));
+   double pipvalue = NormalizeDouble(((SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE)/(SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE)/Point()))*10),2);
+// pipvalue=NormalizeDouble((modeTickV/modeTickS/Point()),)
+// pipvalue=
+   pipvalue = pipvalue / 10;
+   double lotSize = lot_amount;
+   if(lot_calculator == rsk || lot_calculator == dollar) //calculating risk
+     {
+      double riskamount = 0;
+      if(lot_calculator == rsk)
+        {
+         riskamount = (risk/100)*AccountInfoDouble(ACCOUNT_BALANCE);
+        }
+      if(lot_calculator == dollar)
+        {
+         riskamount = dollars;
+        }
+      double pipvalue_required=riskamount/stop_loss;
+      lotSize = pipvalue_required/pipvalue;
+      //sl=riskamount/pipValuelot
+      int roundDigit=0;
+      double step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);
+
+      while(step<1)
+        {
+         roundDigit++;
+         step=step*10;
+        }
+      Print("Round Digits:",roundDigit);
+      lotSize = NormalizeDouble(lotSize,roundDigit);
+      //
+     }
+   Print("Lot Size: ",lotSize);
+
+   if(lotSize > SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX))
+     {
+      lotSize=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
+     }
+   else
+      if(lotSize<SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN))
+        {
+         lotSize=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
+        }
+
+//---
+   return lotSize;
+  }
+//+------------------------------------------------------------------+
+//|                                                                  |
+//+------------------------------------------------------------------+
+void timeFilter(bool onInit,string startTime,string endTime,datetime & sessionStart,datetime & sessionEnd)
+  {
+   int newYorkStartHour = 0, newYorkStartMin = 0, newYorkEndHour = 0, newYorkEndMin = 0;
+
+   datetime newYorkStartTrading,newYorkEndTrading;
+
+   string time[];
+   StringSplit(startTime,':',time);
+   newYorkStartHour = (int)StringToInteger(time[0]);
+   newYorkStartMin  = (int)StringToInteger(time[1]);
+
+   EventSetMillisecondTimer(500);
+   time[0] = "";
+   time[1] = "";
+   StringSplit(endTime,':',time);
+   newYorkEndHour = (int)StringToInteger(time[0]);
+   newYorkEndMin  = (int)StringToInteger(time[1]);
+
+// Print(" Start Time Hour: ",newYorkStartHour,"  Start Time Min: ",newYorkStartMin);
+// Print(" End Time Hour: ",newYorkEndHour,"  End Time Min: ",newYorkEndMin);
+
+
+   datetime startDateTime;
+   MqlDateTime st;
+   TimeCurrent(st); // get current date
+   st.hour   = newYorkStartHour;
+   st.min    = newYorkStartMin;
+   st.sec    = 0;
+   startDateTime = StructToTime(st);
+
+
+   datetime endDateTime;
+   MqlDateTime et;
+   TimeCurrent(et); // get current date
+   et.hour   = newYorkEndHour;
+   et.min    = newYorkEndMin;
+   et.sec    = 0;
+   endDateTime = StructToTime(et);
+
+
+   MqlDateTime sdate,edate;
+   datetime start_Time = 0, end_Time = 0;
+   if(startDateTime > endDateTime)
+     {
+      if(onInit)
+        {
+         start_Time = iTime(Symbol(),PERIOD_D1,1);
+         end_Time = iTime(Symbol(),PERIOD_D1,0);
+        }
+      else
+        {
+         start_Time = sessionStart;
+         end_Time = sessionEnd;
+         if(TimeCurrent() >= sessionEnd && sessionEnd != 0)
+           {
+            start_Time = iTime(Symbol(),PERIOD_D1,0);
+            end_Time = start_Time + 86400;
+           }
+        }
+     }
+   else
+     {
+      start_Time = iTime(Symbol(),PERIOD_D1,0);
+      end_Time = iTime(Symbol(),PERIOD_D1,0);
+     }
+
+   if(TimeToStruct(end_Time,edate))
+     {
+      edate.hour = newYorkEndHour;
+      edate.min  = newYorkEndMin;
+      edate.sec  = 0;
+     }
+   else
+      Print("Error in Converting Time: ",GetLastError());
+   newYorkEndTrading = StructToTime(edate);
+
+   if(TimeToStruct(start_Time,sdate))
+     {
+      sdate.hour = newYorkStartHour;
+      sdate.min  = newYorkStartMin;
+      sdate.sec  = 0;
+     }
+   else
+      Print("Error in Converting Time: ",GetLastError());
+   newYorkStartTrading = StructToTime(sdate);
+
+   sessionStart = newYorkStartTrading;
+   sessionEnd   = newYorkEndTrading;
+  }
+//+------------------------------------------------------------------+
+//|                                                                  |
+//+------------------------------------------------------------------+