//+------------------------------------------------------------------+ //| 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 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 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; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+