//+------------------------------------------------------------------+ //| valFvgMt5.mq5 | //| Copyright 2025, MQL Development | //| https://www.mqldevelopment.com/ | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MQL Development" #property link "https://www.mqldevelopment.com/" #property version "1.1" #include CTrade trade; #resource "\\Indicators\\SequentialVolumeProfileWithFVG.ex5" #define previousBullish "previousBullish" #define previousBearish "previousBearish" #define buy "buy" #define sell "sell" //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ enum lotcalculator { fix, //Fixed Lot Size rsk, //Risk Percentage }; enum tp_options { zone_based, // Zone Based Tp risk_reward_based, // Risk to Reward }; enum sl_options { zone_based_sl, // Zone Based Sl fvg_third, // FVG third candle high and low + buffer }; enum max_trades_option { one_trade, // One Trade one_buy_sell, // One Buy One Sell }; enum abs_high_low_touch { disable_abs, // Trade Normally single_touch_abs, // Disable Same Side Trading both_touch_abs, // Disable Both Side Trading }; sinput string string_0 = "<><><><><><> General SETTINGS <><><><><><>"; //__ input int magic_no = 333; // Magic no input tp_options select_tp = zone_based; // Select Tp input sl_options select_sl = zone_based_sl; // Select Sl input double stoploss = 4; // FVG Third High/Low Stop Loss in Buffer input double tpMultiplier = 2; // Take Profit Multiplier Risk to Reward input max_trades_option selectTradeCountOption = one_trade; // Select Max Trades at a Time input abs_high_low_touch selectAbsTouch = single_touch_abs;// Action on Absolute Touch input string string_0_3 = "<><><><><><> Lot Management<><><><><><>"; //__ input double lot_size = 0.1; // Lot Size input lotcalculator lot_calculator = fix; // Lot Size Calculator input double risk = 0.1; // Risk in Percentage % 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 fvg_setting = "<><><><><> FVG Color Setting <><><><><>"; //_ input color bullish_color = clrAqua; // Bullish FVG Color input color bearish_color = clrYellow; // Bearish FVG Color sinput string string_1 = "<><><><><><> Sequential Volume Indicator SETTINGS <><><><><><>"; //__ input int BinsCount = 100; // Number of price bins input double ValueAreaPercent = 70; // Value Area percentage (70% default) input color VALColor = clrYellow; // Value Area Low color input color VAHColor = clrYellow; // Value Area High color input color AbsLowColor = clrDarkOrange; // Absolute Low color input color AbsHighColor = clrDarkOrange; // Absolute High color input color TimeLineColor = clrRed; // Time marker line color input int LineWidth = 2; // Line width for all value lines input int TimeLineWidth = 2; // Line width for time marker lines input int MaxDaysBack = 30; // Maximum number of trading days to look back input ENUM_LINE_STYLE VALStyle = STYLE_SOLID; // Value Area Low line style input ENUM_LINE_STYLE VAHStyle = STYLE_SOLID; // Value Area High line style input ENUM_LINE_STYLE AbsLowStyle = STYLE_SOLID; // Absolute Low line style input ENUM_LINE_STYLE AbsHighStyle = STYLE_SOLID; // Absolute High line style input bool ShowLabels = true; // Show price labels input bool ShowComment = true; // Show comment with most recent levels input bool ShowFVG = false; // Enable Fair Value Gap detection input color BullishFVGColor = clrLime; // Bullish FVG color input color BearishFVGColor = clrDeepPink; // Bearish FVG color input double MinFVGSize = 0.0; // Minimum FVG size in points (0 = any size) input int MaxBarsBack = 300; // How many bars to look back for FVG input string startHour = "23"; // Start Hour input string startMin = "59"; // Start Minutes input string endHour = "00"; // End Hour input string endMin = "05"; // End Minutes // Global Variables int sequential_handler; datetime startTradingTime = 0, endTradingTime = 0; string sep = ":"; // A separator as a character ushort u_sep; // The code of the separator character string result1[]; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { //--- trade.SetExpertMagicNumber(magic_no); trade.SetDeviationInPoints(10); trade.SetTypeFilling(ORDER_FILLING_IOC); trade.LogLevel(LOG_LEVEL_ALL); trade.SetAsyncMode(false); sequential_handler = iCustom(Symbol(), PERIOD_CURRENT, "::Indicators\\SequentialVolumeProfileWithFVG.ex5", BinsCount, ValueAreaPercent, VALColor, VAHColor, AbsLowColor, AbsHighColor, TimeLineColor, LineWidth, TimeLineWidth, MaxDaysBack, VALStyle, VAHStyle, AbsLowStyle, AbsHighStyle, ShowLabels, ShowComment, ShowFVG, BullishFVGColor, BearishFVGColor, MinFVGSize, MaxBarsBack, startHour, startMin, endHour, endMin); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Print(" DeInIt "); ObjectsDeleteAll(0, 0, OBJ_RECTANGLE); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- // double values[]; // CopyBuffer(sequential_handler,0,0,3,values); // Print("Val: ", val, " Vah: ", vah, " AbsHigh: ", absHigh, " AbsLow: ", absLow); // double Ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK); // double Bid = SymbolInfoDouble(Symbol(),SYMBOL_BID); if(newBar()) { timeConversion(); if((EnableTimeFilter && TimeCurrent() >= startTradingTime && TimeCurrent() < endTradingTime) || !EnableTimeFilter) { double val = lines("VAL"); double vah = lines("VAH"); double absHigh = lines("AbsHigh"); double absLow = lines("AbsLow"); string gapCreated = fvg_gap(); if((selectTradeCountOption == one_buy_sell && todayTradesCount(DEAL_TYPE_BUY) == 0) || (selectTradeCountOption == one_trade && todayTradesCount(DEAL_TYPE_BUY) == 0 && todayTradesCount(DEAL_TYPE_SELL) == 0)) { if(gapCreated == previousBullish) { double open_2 = iOpen(Symbol(), PERIOD_CURRENT, 2); double close_2 = iClose(Symbol(), PERIOD_CURRENT, 2); double upper_price = MathMax(open_2, close_2); double lower_price = MathMin(open_2, close_2); if(((upper_price > absLow) && (lower_price > absLow))) if(((upper_price > val) && (lower_price < val)) || ((upper_price < val) && (lower_price < val))) { if((selectAbsTouch == single_touch_abs && candleNotTouchingHigh(absLow, buy)) || (selectAbsTouch == both_touch_abs && candleNotTouchingHigh(absLow, buy) && candleNotTouchingHigh(absHigh, sell)) || (selectAbsTouch == disable_abs)) { Print("Buy Trade. Val: ", val, " Vah: ", vah, " AbsHigh: ", absHigh, " AbsLow: ", absLow); placeBuyTrade(); } } } } if((selectTradeCountOption == one_buy_sell && todayTradesCount(DEAL_TYPE_SELL) == 0) || (selectTradeCountOption == one_trade && todayTradesCount(DEAL_TYPE_BUY) == 0 && todayTradesCount(DEAL_TYPE_SELL) == 0)) { if(gapCreated == previousBearish) { double open_2 = iOpen(Symbol(), PERIOD_CURRENT, 2); double close_2 = iClose(Symbol(), PERIOD_CURRENT, 2); double upper_price = MathMax(open_2, close_2); double lower_price = MathMin(open_2, close_2); if(((upper_price < absHigh) && (lower_price < absHigh))) if(((upper_price > vah) && (lower_price < vah)) || ((upper_price > vah) && (lower_price > vah))) { if((selectAbsTouch == single_touch_abs && candleNotTouchingHigh(absHigh, sell)) || (selectAbsTouch == both_touch_abs && candleNotTouchingHigh(absLow, buy) && candleNotTouchingHigh(absHigh, sell)) || (selectAbsTouch == disable_abs)) { Print("Sell Trade. Val: ", val, " Vah: ", vah, " AbsHigh: ", absHigh, " AbsLow: ", absLow); placeSellTrade(); } } } } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void timeConversion() { MqlDateTime date, date1; TimeToStruct(iTime(Symbol(),PERIOD_CURRENT,0),date); u_sep=StringGetCharacter(sep,0); StringSplit(startTime,u_sep,result1); date.hour = (int)StringToInteger(result1[0]); date.min = (int)StringToInteger(result1[1]); startTradingTime = StructToTime(date); TimeToStruct(iTime(Symbol(),PERIOD_CURRENT,0),date1); StringSplit(endTime,u_sep,result1); date.hour = (int)StringToInteger(result1[0]); date.min = (int)StringToInteger(result1[1]); endTradingTime = StructToTime(date); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double lines(string name) { datetime todayStart = iTime(Symbol(), PERIOD_D1, 0); datetime nextDayStart = todayStart + 86400; datetime latestObjectTime = 0; for(int i = 0; i < ObjectsTotal(0, 0, OBJ_TREND); i++) { string object_name = ObjectName(0, i, 0, OBJ_TREND); datetime object_time = (datetime)ObjectGetInteger(0, object_name, OBJPROP_TIME, 1); if(object_time > todayStart && object_time < nextDayStart) { // Print(" Object Name: ", object_name, " Day Start Time: ", todayStart, " Next Day Time: ", nextDayStart); if((StringFind(object_name, name) != -1)) { double objectPrice = ObjectGetDouble(0, object_name, OBJPROP_PRICE, 0); return objectPrice; } } } return 0; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool fvgOverLap(string name, double price_overlap) { datetime todayStart = iTime(Symbol(), PERIOD_D1, 0); datetime nextDayStart = todayStart + 86400; for(int i = 0; i < ObjectsTotal(0, 0, OBJ_RECTANGLE); i++) { string object_name = ObjectName(0, i, 0, OBJ_RECTANGLE); datetime object_time1 = (datetime)ObjectGetInteger(0, object_name, OBJPROP_TIME, 1); datetime object_time0 = (datetime)ObjectGetInteger(0, object_name, OBJPROP_TIME, 0); double object_price0 = ObjectGetDouble(0, object_name, OBJPROP_PRICE, 0); double object_price1 = ObjectGetDouble(0, object_name, OBJPROP_PRICE, 1); if(object_time1 > todayStart && object_time1 < nextDayStart) { if((StringFind(object_name, name) != -1)) { double fvg_top = MathMax(object_price0, object_price1); double fvg_bottom = MathMin(object_price0, object_price1); if(fvg_top > price_overlap && fvg_bottom < price_overlap) { Print(" Called By: (", name, ") Object Name: ", object_name, " | Time 0: ", TimeToString(object_time0), " | Price 0: ", object_price0, " | Time 1: ", TimeToString(object_time1), " | Price 0: ", object_price0, " | Price 1: ", object_price1, " | \n FVG Top: ", fvg_top, " | FVG Bottom: ", fvg_bottom); return true; } } } } return false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int todayTradesCount(ENUM_DEAL_TYPE dealType) { int count = 0; ulong ticket_deal_Out=0, ticket_deal_In = 0; if(HistorySelect(iTime(Symbol(),PERIOD_D1,0), TimeCurrent())) { int total = HistoryDealsTotal(); for(int i = total-1; i >= 0 ; i--) { ticket_deal_In = HistoryDealGetTicket(i); if((HistoryDealGetInteger(ticket_deal_In,DEAL_MAGIC) == magic_no) && HistoryDealGetInteger(ticket_deal_In,DEAL_ENTRY) == DEAL_ENTRY_IN && HistoryDealGetString(ticket_deal_In,DEAL_SYMBOL) == Symbol()) // here is the problem solved after break { if(HistoryDealGetInteger(ticket_deal_In, DEAL_TYPE) == dealType) { count++; } } } } return count; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void placeBuyTrade() { 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 * 10 * Point()); // } if(select_sl == zone_based_sl) { buySL = lines("AbsLow"); } if(select_sl == fvg_third) { //if(stoploss != 0) { buySL = iLow(Symbol(), PERIOD_CURRENT, 3) - (stoploss * 10 * Point()); } } if(select_tp == zone_based) { buyTp = lines("VAH"); } if(select_tp == risk_reward_based) { double distance = MathAbs((Ask - buySL) / Point()); distance = (distance * tpMultiplier); buyTp = Ask + (distance * Point()); } //if(takeprofit != 0) // { // buyTp = Ask + (takeprofit * 10 * Point()); // } double distance_sl = MathAbs((Ask - buySL) / Point()); if(trade.PositionOpen(Symbol(),ORDER_TYPE_BUY,getlot(distance_sl),Ask,buySL,buyTp,"Buy Trade Placed")) { Print("Buy Trade Placed: ",trade.ResultOrder()); } else { Print("Error in placing Buy: "+Symbol()+" ",GetLastError()); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void placeSellTrade() { double sellSL = 0, sellTp = 0; //openPrice = SymbolInfoDouble(Symbol(),SYMBOL_BID); double Ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK); double Bid = SymbolInfoDouble(Symbol(),SYMBOL_BID); //if(stoploss != 0) // { // sellSL = Bid + (stoploss * 10 * Point()); // } if(select_sl == zone_based_sl) { sellSL = lines("AbsHigh"); } if(select_sl == fvg_third) { //if(stoploss != 0) { sellSL = iHigh(Symbol(), PERIOD_CURRENT, 3) + (stoploss * 10 * Point()); } } //if(takeprofit != 0) // { // sellTp = Bid - (takeprofit * 10 * Point()); // } if(select_tp == zone_based) { sellTp = lines("VAL"); } if(select_tp == risk_reward_based) { double distance = MathAbs((Bid - sellSL) / Point()); distance = (distance * tpMultiplier); sellTp = Bid - (distance * Point()); } double distance_sl = MathAbs((Bid - sellSL) / Point()); if(trade.PositionOpen(Symbol(),ORDER_TYPE_SELL,getlot(distance_sl),Bid,sellSL,sellTp,"Sell Trade Placed")) { Print("Sell Trade PLaced: ",trade.ResultOrder()); } else { Print("Error in placing Sell: "+Symbol()+" ",GetLastError()); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ 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_size; if(lot_calculator==rsk) //calculating risk { double riskamount=(risk/100)*AccountInfoDouble(ACCOUNT_BALANCE); 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 open) { bullishCount++; } else if(close < open) { bearishCount++; } } // Output the result if(bullishCount > bearishCount) { return previousBullish; } else if(bearishCount > bullishCount) { return previousBearish; } else { return NULL; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string fvg_gap() { //Print("Imbalance: "); // if(check_bearish_bullish() == previousBullish) { if(iLow(Symbol(), PERIOD_CURRENT, 1) > iHigh(Symbol(), PERIOD_CURRENT, 3)) { //double fvg_body = imbalance_gap * 10; // FVG Body double fvg_size = MathAbs((iLow(Symbol(), PERIOD_CURRENT, 1) - iHigh(Symbol(), PERIOD_CURRENT, 3))/Point()); //fvg_size = fvg_size * 10 * Point(); //if(fvg_size > fvg_body) { if(!ObjectCreate(0, "Buy" + (string) TimeCurrent(), OBJ_RECTANGLE, 0, iTime(Symbol(), PERIOD_CURRENT, 3), iHigh(Symbol(), PERIOD_CURRENT, 3), iTime(Symbol(), PERIOD_CURRENT, 1), iLow(Symbol(), PERIOD_CURRENT, 1))) { Print(" Error in Drawing Buy Rectangle : "," rectangle "+(string)iTime(Symbol(),PERIOD_CURRENT,1)," ",GetLastError()); } else { ObjectSetInteger(0, "Buy"+ (string) TimeCurrent(), OBJPROP_COLOR, bullish_color); ObjectSetInteger(0,"Buy"+ (string) TimeCurrent(), OBJPROP_FILL, true); //ObjectSetInteger(0,"Range",OBJPROP_BACK,false); Print("Bullish Fvg Body Size: ", fvg_size, " Name: ", "Buy" + (string) TimeCurrent()); return previousBullish; } } } } // if(check_bearish_bullish() == previousBearish) { if(iLow(Symbol(), PERIOD_CURRENT, 3) > iHigh(Symbol(), PERIOD_CURRENT, 1)) { //double fvg_body = imbalance_gap * 10; // FVG Body double fvg_size = MathAbs((iLow(Symbol(), PERIOD_CURRENT, 3) - iHigh(Symbol(), PERIOD_CURRENT, 1))/Point()); //fvg_size = fvg_size * 10 * Point(); //if(fvg_size > fvg_body) { if(!ObjectCreate(0, "Sell" + (string) TimeCurrent(), OBJ_RECTANGLE, 0, iTime(Symbol(), PERIOD_CURRENT, 3), iLow(Symbol(), PERIOD_CURRENT, 3), iTime(Symbol(), PERIOD_CURRENT, 1), iHigh(Symbol(), PERIOD_CURRENT, 1))) { Print(" Error in Drawing Sell Rectangle : "," rectangle "+(string)iTime(Symbol(),PERIOD_CURRENT,1)," ",GetLastError()); } else { ObjectSetInteger(0, "Sell"+ (string) TimeCurrent(), OBJPROP_COLOR, bearish_color); ObjectSetInteger(0,"Sell"+ (string) TimeCurrent(), OBJPROP_FILL, true); //ObjectSetInteger(0,"Range",OBJPROP_BACK,false); Print("Bearish Fvg Body Size: ", fvg_size, " Name: ", "Buy" + (string) TimeCurrent()); return previousBearish; } } } } return NULL; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool newBar() { static datetime lastbar; datetime curbar = iTime(Symbol(), PERIOD_CURRENT, 0); if(lastbar != curbar) { lastbar = curbar; Print("<<<<<<<<>>>>>>>>>>>>New Bar Time V1.1. ", curbar, "<<<<<<<<>>>>>>>>>>>>"); return (true); } else { return (false); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool candleNotTouchingHigh(double priceToBreak, string calledBy) { int index = iBarShift(Symbol(), PERIOD_CURRENT, iTime(Symbol(), PERIOD_D1, 0), false); for(int i = 0; i <= index; i++) { if(calledBy == "buy") { double low = iLow(Symbol(), PERIOD_CURRENT, i); if(low < priceToBreak) return false; } else if(calledBy == "sell") { double high = iHigh(Symbol(), PERIOD_CURRENT, i); if(high > priceToBreak) return false; } } return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+