//+------------------------------------------------------------------+ //| 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.10" #define MaxOrders 100 #include CTrade trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ enum NewsCloseOrder { CloseAllRunningOrder=0, LetTheOrderRun=1, }; enum selectLine { LineOnNewsBar =0, LineOnNewsStop=1 }; enum selectDay { prev, // Previous Day curr, // Current Day }; #import "volHedgeNewsFilter.ex5" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void initiateNews(bool master = false); int returnNewsStatus(bool High_Impact_News=true ,int High_Start_Time=60//Stop Trade before high News (min) ,int High_Stop_Time=15 //Stop Trade after high News (min) ,bool show_high_line=true//Show verticle Line when high news comes ,bool Medium_Impact_News=true ,int Medium_Start_Time=60//Stop Trade before medium News (min) ,int Medium_Stop_Time=15 //Stop Trade after medium News (min) ,bool show_medium_line=true//Show verticle Line when medium news comes ,bool Low_Impact_News=true ,int Low_Start_Time=60//Stop Trade before low News (min) ,int Low_Stop_Time=15 //Stop Trade after low News (min) ,bool show_low_line=true//Show verticle Line when low news comes ,string symbol="" ,string expert="" ,int GMT_Broker_Time=2 ,selectLine sl=0 ,string extraSymbol="" ,bool isMaster = false ); bool checkDate(string &lastNewsTitle, string &symbolNews, string &impactNews, string &news1, string &news2, string &news3, datetime &timeRemaining, datetime date,string expertname = "",string symbol = "",string extraSymbol="", int gmt=2,string description_1 = "",int candle = 0); void PrintStructure(); #import struct new_trade_store { ulong buy_ticket; // Buy Ticket ulong sell_ticket; // Sell Ticket string symbol; // Symbol double price; // Price 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 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; } }; new_trade_store newTradeStore[MaxOrders]; enum lotcalculator { fix, //Fixed Lot Size rsk, //Risk in Percentage dollar, // Risk in Dollars }; enum optionsEaTyp { client, // Client EA master, // Master EA }; sinput string string_0 = "<><><><><><> General SETTINGS <><><><><><>"; //__ input int magic_no = 333; // Magic no input bool useTpSlPips = false; // Use Relative Tp/Sl in Points input double stopLoss = 1000; // Fixed Stop Loss in Points input double takeProfit = 1000; // Fixed Take Profit in Points input bool bothHitsSl = false; // Enable Topped & Tailed Pre-Demand Level input int maxTrades = 2; // Max Concurrent Trades input int maxSlippage = 5; // Max Slippage (Points) input bool enableSpreadFilter = false; // Enable Spread Filter input double maximumSpread = 10; // Maximum Spread (Points) input string tradeComment = "Trade Placed"; // Trade Comment Prefix input string dataFileName = "vol_hedge_data.csv"; // CSV File Name input bool enableDrawLevels = false; // Draw Levels input optionsEaTyp selectEaType = master; // Master EA / Client EA 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 time_setting = "<><><><><> Time Filter Settings <><><><><>"; //_ input bool enableTimeFilter = false; // Enable Time Filter input string startTime = "03:00"; // Start Time Session input string endTime = "09:00"; // End Time Session input string weekFilterSettings = "<><><><><> Week Filter Settings <><><><><>"; //_ input bool enableWeekFilter = false; // Enable Week Filter (true/false) input int filterMonthNumber = 9; // Month number to apply week filter (1..12) input int filterWeekNumber = 2; // Week number of month to block (1..5) input string monthFilterSettings = "<><><><><> Month Filter Settings <><><><><>"; //_ input bool allowJanuary = true; // Allow Trading in January input bool allowFebruary = true; // Allow Trading in February input bool allowMarch = true; // Allow Trading in March input bool allowApril = true; // Allow Trading in April input bool allowMay = true; // Allow Trading in May input bool allowJune = true; // Allow Trading in June input bool allowJuly = true; // Allow Trading in July input bool allowAugust = true; // Allow Trading in August input bool allowSeptember = true; // Allow Trading in September input bool allowOctober = true; // Allow Trading in October input bool allowNovember = true; // Allow Trading in November input bool allowDecember = true; // Allow Trading in December input string string_0_2 = "<><><><><><> Trailing Setting<><><><><><>"; //__ input bool indivial_trailing = false; // Indiviual Trailing input double ts_sl = 150; // Trailing Start in Points input double ts = 50; // Trailing Stop in Points input string strMA14 ="<><><><><><> BreakEven Settings <><><><><><>";//_ input bool UseBreakEven = false; // Use Break Even input int breakEvenPoints = 150; // BreakEven Trigger Points input int breakStopPoint = 50; // BreakEven Above OpenPrice Points 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 input int High_Start_Time = 60; //Stop Trade before high News (min) input int High_Stop_Time = 15; //Stop Trade after high News (min) input bool show_high_line = true; //Show verticle Line when high news comes input selectLine Select_News_Line = 0; //News Line input bool mobileAlert = true; //Mobile Alert input bool Medium_Impact_News = true; // Medium Impact News input int Medium_Start_Time = 60; // Stop Trade before medium News (min) input int Medium_Stop_Time = 15; // Stop Trade after medium News (min) input bool show_medium_line = true; // Show vertical Line when medium news comes input bool Low_Impact_News = true; // Low Impact News input int Low_Start_Time = 60; // Stop Trade before low News (min) input int Low_Stop_Time = 15; // Stop Trade after low News (min) input bool show_low_line = true; // Show vertical Line when low news comes // Global Variables static double tickCurrentBid = 0; double tickPreviousBid = 0; static double tickCurrentAsk = 0; double tickPreviousAsk = 0; int newYorkStartTime = 0, newYorkStartMin = 0, newYorkEndHour = 0, newYorkEndMin = 0; datetime newYorkStartTrading = 0, newYorkEndTrading = 0; 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[]; selectDay newYorkSessionDay = curr; // Select Day for Start Time //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { //--- Print(" OnInIt. "); trade.SetExpertMagicNumber(magic_no); trade.SetDeviationInPoints(maxSlippage); trade.SetTypeFilling(ORDER_FILLING_IOC); trade.LogLevel(LOG_LEVEL_ALL); trade.SetAsyncMode(false); if(!MQLInfoInteger(MQL_TESTER)) { loadNewTradeStoreFile(); } int filehandle = FileOpen(dataFileName, 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) >= 8) { 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_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[6]); datetime end_local = StringToTime(orderData[7]); if(orderData[6] == "0" || orderData[6] == NULL) { start_local = 0; } if(orderData[7] == "0" || orderData[7] == NULL) { end_local = 0; } 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 if(!level_present(price_local)) { Print(" --------------- Price: ", price_local, " Start Time: ", start_local, " End Time: ", end_local, " --------------------"); addToNewTradeStore(buy_ticket_local, sell_ticket_local, symbol_local, price_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); } else { Print("Level is already Present. Level: ", price_local); } } } } FileClose(filehandle); } else { Print(" InValid Handler. Error: ", GetLastError()); } struct_level_check(); string time[]; StringSplit(startTime,':',time); newYorkStartTime = (int)StringToInteger(time[0]); newYorkStartMin = (int)StringToInteger(time[1]); Print("NewYork Start Time Hour: ",newYorkStartTime," Start Time Min: ",newYorkStartMin); time[0] = ""; time[1] = ""; StringSplit(endTime,':',time); newYorkEndHour = (int)StringToInteger(time[0]); newYorkEndMin = (int)StringToInteger(time[1]); Print("NewYork End Time Hour: ",newYorkEndHour," End Time Min: ",newYorkEndMin); StringSplit(startTime,':',time); int 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]); 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); datetime start_Time = 0, end_Time = 0; if(startDateTime > endDateTime) { Print(" --------------------------- Previous -------------------------------------- "); newYorkSessionDay = prev; } else { Print(" --------------------------- Current -------------------------------------- "); newYorkSessionDay = curr; } timeFilter(true); int timeDifference = (int)TimeCurrent() - (int)TimeGMT(); Print("Time Difference is: ", timeDifference); if(timeDifference > 0) { GMT_Broker_Time = (int)MathRound((double)timeDifference / 3600.0); } else if(timeDifference < 0) { GMT_Broker_Time = (int)MathRound((double)timeDifference / 3600.0); } else // timeDifference == 0 { GMT_Broker_Time = 0; } Print("Gmt Time: ", TimeGMT(), " Broker Gmt Time: ", GMT_Broker_Time); gmt = GMT_Broker_Time; if(!MQLInfoInteger(MQL_TESTER)) { if(selectEaType == master) { initiateNews(true); // change here } else { initiateNews(false); } } if(enableDrawLevels) { drawLevels(); } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- ObjectsDeleteAll(0, 0, OBJ_HLINE); if(!MQLInfoInteger(MQL_TESTER)) { saveNewTradeStoreFile(); } } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { bool masterSide = false; if(selectEaType == master) { masterSide = true; } else { masterSide = false; } static int status=-1,preStatus=-1; if(!MQLInfoInteger(MQL_TESTER)) { status=returnNewsStatus(High_Impact_News ,High_Start_Time ,High_Stop_Time ,show_high_line ,Medium_Impact_News ,Medium_Start_Time ,Medium_Stop_Time ,show_medium_line ,Low_Impact_News ,Low_Start_Time ,Low_Stop_Time ,show_low_line ,Symbol() ,MQLInfoString(MQL_PROGRAM_NAME) ,GMT_Broker_Time ,Select_News_Line ,"", masterSide ); } else status=0; if(status==0) { mainActivity(); } if(status==1 || status==2 || status==3) { if(newsClose==0) { if(orderCount_1(POSITION_TYPE_BUY,magic_no)>0) closeTrades(POSITION_TYPE_BUY,magic_no); if(orderCount_1(POSITION_TYPE_SELL,magic_no)>0) closeTrades(POSITION_TYPE_SELL,magic_no); } else if(newsClose==1) { if((orderCount_1(POSITION_TYPE_BUY,magic_no)>0) || (orderCount_1(POSITION_TYPE_SELL,magic_no)>0)) { mainActivity(); } } } if(status!=preStatus) { if(status==0 && preStatus!=-1) { // if(ObjectFind(0,Lname)) { // ObjectSetInteger(0,Lname,OBJPROP_COLOR,clrRed); ObjectSetString(0,Lname,OBJPROP_TEXT,""); } Alert("Trading is start"); if(mobileAlert) SendNotification("Trading is start"); preStatus=status; } else if(status==1) { ObjectSetInteger(0,Lname,OBJPROP_COLOR,clrRed); ObjectSetString(0,Lname,OBJPROP_TEXT,"High Impact News"); Alert("Trading Stop due to high impact news"); if(mobileAlert) SendNotification("Trading Stop due to high impact news"); preStatus=status; } else if(status==2) { ObjectSetInteger(0,Lname,OBJPROP_COLOR,clrBlue); ObjectSetString(0,Lname,OBJPROP_TEXT,"Medium Impact News"); Alert("Trading Stop due to medium impact news"); if(mobileAlert) SendNotification("Trading Stop due to medium impact news"); preStatus=status; } else if(status==3) { ObjectSetInteger(0,Lname,OBJPROP_COLOR,clrGreen); ObjectSetString(0,Lname,OBJPROP_TEXT,"Low Impact News"); Alert("Trading Stop due to low impact news"); if(mobileAlert) SendNotification("Trading Stop due to low impact news"); preStatus=status; } } else { mainActivity(); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void mainActivity() { //--- newBar(); if(indivial_trailing) { Individual_Trailing(); } if(UseBreakEven) { breakEven(); } 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; } timeFilter(false); // Comment(" Session Start = ", newYorkStartTrading, " Asian Session End = ", newYorkEndTrading); if((enableTimeFilter && TimeCurrent() >= newYorkStartTrading && TimeCurrent() <= newYorkEndTrading) || !enableTimeFilter) { removeFromStructure(); if(bothHitsSl) { virtualSLHitCheck(); } tradePlacingCheck(); } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool isTradingAllowedByWeek() { if(!enableWeekFilter) // filter disabled -> allow trading return true; // validate inputs quickly if(filterMonthNumber < 1 || filterMonthNumber > 12) { PrintFormat("⚠️ filterMonthNumber out of range (%d). Week filter disabled.", filterMonthNumber); return true; } if(filterWeekNumber < 1 || filterWeekNumber > 5) { PrintFormat("⚠️ filterWeekNumber out of range (%d). Week filter disabled.", filterWeekNumber); return true; } MqlDateTime t; TimeToStruct(TimeCurrent(), t); // t.mon (1..12), t.day (1..31) // if the months don't match, week filter doesn't apply -> allow if(t.mon != filterMonthNumber) return true; // compute week of month: days 1-7 -> week 1, 8-14 -> week 2, etc. int weekOfMonth = ((t.day - 1) / 7) + 1; // yields 1..5 // if current week equals the filtered week -> block trading (return false) if(weekOfMonth == filterWeekNumber) { return false; // trading NOT allowed this week of the specified month } return true; // otherwise allow trading } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool newBar() { static datetime lastbar; datetime curbar = iTime(Symbol(), PERIOD_CURRENT, 0); if(lastbar != curbar) { lastbar = curbar; Print(" ---------------------- New Bar :: ---------------------- ",lastbar); return (true); } else { return (false); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void closeTrades(int type,int magicno) { Print("Total order: ",OrdersTotal()); for(int i= PositionsTotal()-1; i>=0; i--) { // Print(" Selection: ",OrderSelect(i,SELECT_BY_POS)," i: ",i," OrdersTotal(): ", OrdersTotal()); ulong ticket = PositionGetTicket(i); if(PositionSelectByTicket(ticket)) { if(PositionGetInteger(POSITION_TYPE) == type) { if(PositionGetInteger(POSITION_MAGIC) == magicno && PositionGetString(POSITION_SYMBOL) == Symbol()) { //trade.PositionClose(PositionGetInteger(POSITION_TICKET)) if(!trade.PositionClose(PositionGetInteger(POSITION_TICKET))) {Print("Problem in closing order order ",PositionGetInteger(POSITION_TICKET)); } else { Print("Order Closed by closeTrades() new filter",PositionGetInteger(POSITION_TICKET)); } } } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int orderCount_1(int type,int magic) { int count1=0; for(int i= PositionsTotal()-1; i>=0; i--) { // Print(" Selection: ",OrderSelect(i,SELECT_BY_POS)," i: ",i," OrdersTotal(): ", OrdersTotal()); ulong ticket = PositionGetTicket(i); if(PositionSelectByTicket(ticket)) { // if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY || PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) if(PositionGetInteger(POSITION_MAGIC) == magic && PositionGetString(POSITION_SYMBOL) == Symbol()) { //trade.PositionClose(PositionGetInteger(POSITION_TICKET)) if(PositionGetInteger(POSITION_TYPE) == type) { count1++; } } } } return count1; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int orderCount(int type) { int count = 0; for(int i= PositionsTotal()-1; i>=0; i--) { ulong ticket = PositionGetTicket(i); if(PositionSelectByTicket(ticket)) { if(PositionGetInteger(POSITION_MAGIC) == magic_no && PositionGetString(POSITION_SYMBOL) == Symbol()) { if(PositionGetInteger(POSITION_TYPE) == type) { count++; } } } } return count; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ 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_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; } } } return; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void addToNewTradeStore(ulong r_buy_ticket, ulong r_sell_ticket, string r_symbol, double r_price, 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. "); 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) { 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_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; 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 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, " | Sell Virtual Sl Hit: ", newTradeStore[i].sell_hit_virtual_sl); 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) { if((TimeCurrent() > newTradeStore[i].start_time && TimeCurrent() < newTradeStore[i].end_time) || (newTradeStore[i].start_time == 0 || newTradeStore[i].end_time == 0)) { if(newTradeStore[i].buy_hit_virtual_sl == true && newTradeStore[i].sell_hit_virtual_sl == true) { double levelPriceIs = newTradeStore[i].price; if((tickPreviousBid > levelPriceIs && tickCurrentBid < levelPriceIs) || (tickPreviousBid < levelPriceIs && tickCurrentBid > levelPriceIs)) { if(isTradingAllowedByWeek()) { if((enableSpreadFilter && spreadFilter()) || !enableSpreadFilter) { ulong buyTicket = -1, sellTicket = -1; if(countLiveTrades() < maxTrades) { buyTicket = placeBuyTrade(newTradeStore[i].stop_loss_buy, newTradeStore[i].take_profit_buy); sellTicket = placeSellTrade(newTradeStore[i].stop_loss_sell, newTradeStore[i].take_profit_sell); newTradeStore[i].buy_ticket = buyTicket; newTradeStore[i].sell_ticket = sellTicket; } } } } } } } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void draw_lines(string name, datetime dateTime, double price, color selectColor, long lineStyle) { if(!ObjectCreate(0, name, OBJ_HLINE, 0, dateTime, price)) { Print(" Error in creating ", name," : ","line: "," ",GetLastError()); } else { ObjectSetInteger(0, name, OBJPROP_COLOR, selectColor); ObjectSetInteger(0, name, OBJPROP_STYLE, lineStyle); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void drawLevels() { for(int i = 0; i < MaxOrders; i++) { if(newTradeStore[i].price > 0) { draw_lines("level" + (string)newTradeStore[i].price, TimeCurrent(), newTradeStore[i].price, clrAqua, STYLE_SOLID); } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ 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(useTpSlPips) { if(stopLoss != 0) { buySL = Ask - (stopLoss * Point()); } if(takeProfit != 0) { buyTp = Ask + (takeProfit * Point()); } } else { if(stoploss > 0) { buySL = stoploss; } if(takeprofit > 0) { buyTp = takeprofit; } } double distance = MathAbs((Ask - buySL) / Point()); if(trade.PositionOpen(Symbol(),ORDER_TYPE_BUY,getLot(distance),Ask,buySL,buyTp,tradeComment+" Buy")) { 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(useTpSlPips) { if(stopLoss != 0) { sellSL = Bid + (stopLoss * Point()); } if(takeProfit != 0) { sellTp = Bid - (takeProfit * Point()); } } else { 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,tradeComment+ " Sell")) { 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= newYorkEndTrading && newYorkEndTrading != 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 = newYorkStartTime; sdate.min = newYorkStartMin; sdate.sec = 0; } else Print("Error in Converting Time: ",GetLastError()); newYorkStartTrading = StructToTime(sdate); // if(onInit) //Print("NewYork Start Time ",newYorkStartTrading,"End Date: ",newYorkEndTrading); //Print("Edate: ",edate.hour," ",edate.min," Sdate: ",sdate.hour," ",sdate.min); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void removeFromStructure() { for(int i = 0 ; i < MaxOrders ; i++) { bool isBuyPresent=false, isSellPresent=false; if(newTradeStore[i].buy_ticket != -1 && newTradeStore[i].sell_ticket != -1) { for(int j = PositionsTotal()-1; j>=0; j--) { ulong ticket = PositionGetTicket(j); if(PositionSelectByTicket(ticket)) { if(ticket == newTradeStore[i].buy_ticket) { isBuyPresent=true; } } } for(int j = PositionsTotal()-1; j>=0; j--) { ulong ticket = PositionGetTicket(j); if(PositionSelectByTicket(ticket)) { if(ticket == newTradeStore[i].sell_ticket) { isSellPresent = true; } } } if(!isBuyPresent && !isSellPresent) { 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) { 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; } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void virtualSLHitCheck() { for(int i = 0 ; i < MaxOrders ; i++) { if(newTradeStore[i].buy_ticket == -1 && newTradeStore[i].sell_ticket == -1) { if(TimeCurrent() > newTradeStore[i].start_time && TimeCurrent() < newTradeStore[i].end_time) { 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 = stopLoss != 0 ? newTradeStore[i].price - (stopLoss * Point()) : 0; sell_sl = stopLoss != 0 ? newTradeStore[i].price + (stopLoss * Point()) : 0; } if(newTradeStore[i].buy_hit_virtual_sl == false) { 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()); } } } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int countLiveTrades() { int count = 0; for(int i = 0; i < PositionsTotal(); i++) { ulong ticket = PositionGetTicket(i); if(PositionSelectByTicket(ticket)) { if(PositionGetInteger(POSITION_MAGIC) == magic_no) { if(PositionGetString(POSITION_SYMBOL) == Symbol()) { if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY || PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) { count++; } } } } } return count; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool spreadFilter() { long spreadIs = SymbolInfoInteger(Symbol(), SYMBOL_SPREAD); if(spreadIs > maximumSpread) { return false; } return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ 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) { if(isCounterpartOpen(ticket)) { // counterpart still open -> skip trailing for this position continue; } //========================================================Buy Condition========================================================================= if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { mySL = PositionGetDouble(POSITION_PRICE_OPEN) + (breakEvenPoints * SymbolTickSize); if(SymbolInfoDouble(Symbol(),SYMBOL_BID) >= mySL && PositionGetDouble(POSITION_PRICE_OPEN) > PositionGetDouble(POSITION_SL)) { newSL= PositionGetDouble(POSITION_PRICE_OPEN) + (breakStopPoint * 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 * SymbolTickSize); if(SymbolInfoDouble(Symbol(),SYMBOL_ASK) <= mySL && PositionGetDouble(POSITION_SL) > PositionGetDouble(POSITION_PRICE_OPEN)) { newSL = PositionGetDouble(POSITION_PRICE_OPEN) - (breakStopPoint * SymbolTickSize); if(trade.PositionModify(ticket,newSL,PositionGetDouble(POSITION_TP))) { Print("Order Sell BreakEven Successfully "); } else { Print("Error in BreakEven Sell Position ",GetLastError()); } } } } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool isCounterpartOpen(ulong ticket) { // scan stored pairs for(int k=0; k 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; double mySL,myResult; openedpositions=PositionsTotal(); if((openedpositions>0)) { int totalorders=PositionsTotal(); for(int i=0; i 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 { mySL=NormalizeDouble(SymbolAsk-(ts*SymbolTickSize),Digits()); // new SL double startSl=PositionGetDouble(POSITION_PRICE_OPEN)+(ts_sl*SymbolTickSize); if(PositionGetDouble(POSITION_SL) != mySL) if(mySL>PositionGetDouble(POSITION_SL) && SymbolAsk>=startSl) { myResult=trade.PositionModify(ticket,mySL,PositionGetDouble(POSITION_TP)); //OrderModify(OrderTicket(),OrderOpenPrice(),mySL,OrderTakeProfit(),0,clrGreen); if(!myResult) { Print(" Buy Trade Trailing Error: ",GetLastError()); } } } if(type==POSITION_TYPE_SELL) { mySL=NormalizeDouble(SymbolBid+(ts*SymbolTickSize),Digits()); // new SL double startSlSell=PositionGetDouble(POSITION_PRICE_OPEN)-(ts_sl*SymbolTickSize); if(PositionGetDouble(POSITION_SL) != mySL) if(((mySL 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 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) : ""; 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 + "," + slBuyStr + "," + tpBuyStr + "," + slSellStr + "," + tpSellStr + "," + 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_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; 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 >= 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_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[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[10] == "true") { bHit = true; } else { bHit = false; } if(tokens[11] == "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 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, " 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, "'."); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+