AdvancedSessionVWAP by Naya

661 downloads / 376 views / Created: 31.05.2025
 Average Rating: 0

Indicator Description

This indicator combines traditional VWAP (Volume Weighted Average Price) calculations with flexible session-based anchoring to provide dynamic support/resistance levels across different time horizons.

Key Features:

Multiple anchoring options:

Daily (resets at midnight)

Weekly (Monday-start)

Monthly (1st of month)

Custom session-based (user-defined start time and reset period)

Volume-weighted price calculation using (O + H + L + C) / 4 formula

Adjustable shift parameter to offset the VWAP line

Option to use previous bar's value for signal generation

Configuration Options:

Anchor Period selection (Daily / Weekly / Monthly / Session)

For Session mode:

Custom anchor time (hour and minute)

Adjustable reset period (1–1440 minutes)

Universal shift parameter (0–2 bars)

Previous bar value toggle

Available Signals:

For Entries:

Enter at VWAP price

Filter by VWAP direction (rising / falling)

Filter by price position relative to VWAP

Filter by price crosses through VWAP

For Exits:

Exit at VWAP price

Filter by VWAP direction

Filter by closing price relative to VWAP

Visual Representation:

MediumSeaGreen line showing current VWAP value

Automatic gap handling for price-based entries/exits

Practical Applications:

Identifying fair value prices

Session-based trading strategies

Mean-reversion systems

Breakout confirmation

Volume-profile analysis

Technical Notes:

Handles price gaps intelligently

Works across all timeframes

Suitable for both intraday and swing trading

Combines price and volume information

Author: NAYA

The indicator provides traders with a versatile tool for incorporating volume-weighted price analysis into their strategies, with particular strength in session-based trading approaches. The multiple anchoring options make it adaptable to various trading styles and time horizons.

Created with the help of DeepSeek AI and Claude AI

Comments

using System; using System.Drawing; using ForexStrategyBuilder.Infrastructure.Entities; using ForexStrategyBuilder.Infrastructure.Enums; using ForexStrategyBuilder.Infrastructure.Interfaces; namespace ForexStrategyBuilder.Indicators.Custom { public class AdvancedSessionVWAP : Indicator { public AdvancedSessionVWAP() { IndicatorName = "AdvancedSessionVWAP"; PossibleSlots = SlotTypes.Open | SlotTypes.OpenFilter | SlotTypes.Close | SlotTypes.CloseFilter; IndicatorAuthor = "NAYA +237674724684"; IndicatorVersion = "1.0"; IndicatorDescription = "Combines Daily/Weekly/Monthly AVWAP with Session-based VWAP in one indicator."; } public override void Initialize(SlotTypes slotType) { SlotType = slotType; // --- Logic selection IndParam.ListParam[0].Caption = "Logic"; switch (SlotType) { case SlotTypes.Open: IndParam.ListParam[0].ItemList = new[] { "Enter the market at the AdvancedSessionVWAP" }; break; case SlotTypes.OpenFilter: IndParam.ListParam[0].ItemList = new[] { "The AdvancedSessionVWAP rises", "The AdvancedSessionVWAP falls", "The bar opens above the AdvancedSessionVWAP", "The bar opens below the AdvancedSessionVWAP", "The bar opens above the AdvancedSessionVWAP after opening below it", "The bar opens below the AdvancedSessionVWAP after opening above it", }; break; case SlotTypes.Close: IndParam.ListParam[0].ItemList = new[] { "Exit the market at the AdvancedSessionVWAP" }; break; case SlotTypes.CloseFilter: IndParam.ListParam[0].ItemList = new[] { "The AdvancedSessionVWAP rises", "The AdvancedSessionVWAP falls", "The bar closes below the AdvancedSessionVWAP", "The bar closes above the AdvancedSessionVWAP", }; break; default: IndParam.ListParam[0].ItemList = new[] { "Not Defined" }; break; } IndParam.ListParam[0].Index = 0; IndParam.ListParam[0].Text = IndParam.ListParam[0].ItemList[0]; IndParam.ListParam[0].Enabled = true; IndParam.ListParam[0].ToolTip = "Logic of application of the AdvancedSessionVWAP."; // --- Anchor period selection IndParam.ListParam[1].Caption = "Anchor Period"; IndParam.ListParam[1].ItemList = new[] { "Daily", "Weekly", "Monthly", "Session" }; IndParam.ListParam[1].Index = 0; IndParam.ListParam[1].Text = "Daily"; IndParam.ListParam[1].Enabled = true; IndParam.ListParam[1].ToolTip = "Select the anchor period for VWAP calculation."; // --- Anchor Hour (only for Session) IndParam.NumParam[0].Caption = "Anchor Hour"; IndParam.NumParam[0].Value = 0; IndParam.NumParam[0].Min = 0; IndParam.NumParam[0].Max = 23; IndParam.NumParam[0].Enabled = true; IndParam.NumParam[0].ToolTip = "Hour component (0–23) of the anchor time (Session only)."; // --- Anchor Minute (only for Session) IndParam.NumParam[1].Caption = "Anchor Minute"; IndParam.NumParam[1].Value = 0; IndParam.NumParam[1].Min = 0; IndParam.NumParam[1].Max = 59; IndParam.NumParam[1].Enabled = true; IndParam.NumParam[1].ToolTip = "Minute component (0–59) of the anchor time (Session only)."; // --- Reset Period (minutes, only for Session) IndParam.NumParam[2].Caption = "Reset Period (minutes)"; IndParam.NumParam[2].Value = 60; IndParam.NumParam[2].Min = 1; IndParam.NumParam[2].Max = 1440; // up to 24h IndParam.NumParam[2].Enabled = true; IndParam.NumParam[2].ToolTip = "Session reset period in minutes (Session only)."; // --- Shift (bars) (applies to all VWAP types) IndParam.NumParam[3].Caption = "Shift (bars)"; IndParam.NumParam[3].Value = 0; IndParam.NumParam[3].Min = 0; IndParam.NumParam[3].Max = 2; IndParam.NumParam[3].Enabled = true; IndParam.NumParam[3].ToolTip = "Number of bars to shift the VWAP (applies to any anchor period)."; // --- Use previous bar value? IndParam.CheckParam[0].Caption = "Use previous bar value"; IndParam.CheckParam[0].Enabled = true; IndParam.CheckParam[0].ToolTip = "If checked, signals use the previous bar's VWAP value."; return; } public override void Calculate(IDataSet dataSet) { DataSet = dataSet; int bars = Bars; int firstBar = 3; // Read shared parameters int periodIndex = IndParam.ListParam[1].Index; // 0=Daily,1=Weekly,2=Monthly,3=Session int anchorHour = (int)IndParam.NumParam[0].Value; int anchorMinute = (int)IndParam.NumParam[1].Value; int resetPeriod = (int)IndParam.NumParam[2].Value; int shift = (int)IndParam.NumParam[3].Value; int usePrev = IndParam.CheckParam[0].Checked ? 1 : 0; // Buffers double[] vwapBuffer = new double[bars]; double[] shiftedVWAP = new double[bars]; // Cumulative PV and V double cumPV = 0.0; double cumV = 0.0; DateTime currentPeriodTime = DateTime.MinValue; // Main loop: calculate raw (unshifted) VWAP for (int iBar = firstBar; iBar < bars; iBar++) { DateTime barTime = Time[iBar]; DateTime periodStart; if (periodIndex < 3) { // Daily / Weekly / Monthly AVWAP logic periodStart = GetAnchorStartTime(barTime, periodIndex + 1); } else { // Session VWAP logic: adjust barTime by chart period, then get last reset DateTime adjustedTime = barTime.AddMinutes((int)Period); periodStart = GetLastResetTime(adjustedTime, anchorHour, anchorMinute, resetPeriod); } // If new anchor/reset period → reset cumulatives if (periodStart != currentPeriodTime) { cumPV = 0.0; cumV = 0.0; currentPeriodTime = periodStart; } // Typical price = (Open + High + Low + Close) / 4 double typicalPrice = (Open[iBar] + High[iBar] + Low[iBar] + Close[iBar]) / 4.0; double volume = Volume[iBar]; cumPV += typicalPrice * volume; cumV += volume; vwapBuffer[iBar] = (cumV > 0.0) ? (cumPV / cumV) : 0.0; } // Apply shift to get shiftedVWAP[] for (int bar = 0; bar < bars; bar++) { int src = bar - shift; if (src >= 0 && src < bars) shiftedVWAP[bar] = vwapBuffer[src]; else if (bar >= shift) shiftedVWAP[bar] = vwapBuffer[bar - shift]; else shiftedVWAP[bar] = 0.0; } // Build components if (SlotType == SlotTypes.Open || SlotType == SlotTypes.Close) { // Entry/Exit price logic Component = new IndicatorComp[2]; Component[1] = new IndicatorComp { Value = new double[bars] }; for (int iBar = firstBar + shift; iBar < bars; iBar++) { double v0 = shiftedVWAP[iBar - usePrev]; double v1 = shiftedVWAP[iBar - usePrev - 1]; double outPrice = v0; // Handle price gaps if ((v1 > High[iBar - 1] && v0 < Open[iBar]) || (v1 < Low[iBar - 1] && v0 > Open[iBar]) || (Close[iBar - 1] < v0 && v0 < Open[iBar]) || (Close[iBar - 1] > v0 && v0 > Open[iBar])) { outPrice = Open[iBar]; } Component[1].Value[iBar] = outPrice; } } else { // OpenFilter / CloseFilter: two no-chart buffers Component = new IndicatorComp[3]; Component[1] = new IndicatorComp { ChartType = IndChartType.NoChart, FirstBar = firstBar + shift, Value = new double[bars] }; Component[2] = new IndicatorComp { ChartType = IndChartType.NoChart, FirstBar = firstBar + shift, Value = new double[bars] }; } // Main VWAP line (always displayed as a line) Component[0] = new IndicatorComp { CompName = "AdvancedSessionVWAP Value", DataType = IndComponentType.IndicatorValue, ChartType = IndChartType.Line, ChartColor= Color.MediumSeaGreen, FirstBar = firstBar + shift, Value = shiftedVWAP }; // Assign names and data types for the second component switch (SlotType) { case SlotTypes.Open: Component[1].CompName = "Position opening price"; Component[1].DataType = IndComponentType.OpenPrice; break; case SlotTypes.OpenFilter: Component[1].CompName = "Is long entry allowed"; Component[1].DataType = IndComponentType.AllowOpenLong; Component[2].CompName = "Is short entry allowed"; Component[2].DataType = IndComponentType.AllowOpenShort; break; case SlotTypes.Close: Component[1].CompName = "Position closing price"; Component[1].DataType = IndComponentType.ClosePrice; break; case SlotTypes.CloseFilter: Component[1].CompName = "Close out long position"; Component[1].DataType = IndComponentType.ForceCloseLong; Component[2].CompName = "Close out short position"; Component[2].DataType = IndComponentType.ForceCloseShort; break; } // Apply filter logic if needed if (SlotType == SlotTypes.OpenFilter || SlotType == SlotTypes.CloseFilter) { switch (IndParam.ListParam[0].Text) { case "The AdvancedSessionVWAP rises": IndicatorRisesLogic(firstBar + shift, usePrev, shiftedVWAP, ref Component[1], ref Component[2]); break; case "The AdvancedSessionVWAP falls": IndicatorFallsLogic(firstBar + shift, usePrev, shiftedVWAP, ref Component[1], ref Component[2]); break; case "The bar opens above the AdvancedSessionVWAP": BarOpensAboveIndicatorLogic(firstBar + shift, usePrev, shiftedVWAP, ref Component[1], ref Component[2]); break; case "The bar opens below the AdvancedSessionVWAP": BarOpensBelowIndicatorLogic(firstBar + shift, usePrev, shiftedVWAP, ref Component[1], ref Component[2]); break; case "The bar opens above the AdvancedSessionVWAP after opening below it": BarOpensAboveIndicatorAfterOpeningBelowLogic(firstBar + shift, usePrev, shiftedVWAP, ref Component[1], ref Component[2]); break; case "The bar opens below the AdvancedSessionVWAP after opening above it": BarOpensBelowIndicatorAfterOpeningAboveLogic(firstBar + shift, usePrev, shiftedVWAP, ref Component[1], ref Component[2]); break; case "The position opens above the AdvancedSessionVWAP": Component[0].PosPriceDependence = PositionPriceDependence.BuyHigherSellLower; Component[0].UsePreviousBar = usePrev; Component[1].ShowInDynInfo = false; Component[2].ShowInDynInfo = false; break; case "The position opens below the AdvancedSessionVWAP": Component[0].PosPriceDependence = PositionPriceDependence.BuyLowerSellHigher; Component[0].UsePreviousBar = usePrev; Component[1].ShowInDynInfo = false; Component[2].ShowInDynInfo = false; break; case "The bar closes below the AdvancedSessionVWAP": BarClosesBelowIndicatorLogic(firstBar + shift, usePrev, shiftedVWAP, ref Component[1], ref Component[2]); break; case "The bar closes above the AdvancedSessionVWAP": BarClosesAboveIndicatorLogic(firstBar + shift, usePrev, shiftedVWAP, ref Component[1], ref Component[2]); break; } } } private DateTime GetAnchorStartTime(DateTime currentTime, int anchorType) { // 1 = Daily, 2 = Weekly (Monday), 3 = Monthly switch (anchorType) { case 1: // Daily return currentTime.Date; case 2: // Weekly (Monday) DateTime monday = currentTime.Date; while (monday.DayOfWeek != DayOfWeek.Monday) monday = monday.AddDays(-1); return monday; case 3: // Monthly return new DateTime(currentTime.Year, currentTime.Month, 1); default: return currentTime.Date; } } private DateTime GetLastResetTime(DateTime currentTime, int anchorHour, int anchorMinute, int resetPeriod) { // Based on SessionVWAP logic: // Calculate minutes since midnight for currentTime int currentMinutes = currentTime.Hour * 60 + currentTime.Minute; int anchorMinutes = anchorHour * 60 + anchorMinute; DateTime lastReset; if (currentMinutes >= anchorMinutes) { // Today's anchor has passed int minutesSinceAnchor = currentMinutes - anchorMinutes; int periodsSinceAnchor = minutesSinceAnchor / resetPeriod; int totalOffsetInMinutes = periodsSinceAnchor * resetPeriod; lastReset = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, anchorHour, anchorMinute, 0) .AddMinutes(totalOffsetInMinutes); } else { // Today's anchor hasn't occurred → look back to the previous day int minutesSinceMidnight = currentMinutes; int minutesSincePrevDayAnchor = (1440 - anchorMinutes) + minutesSinceMidnight; int periodsSincePrevDayAnchor = minutesSincePrevDayAnchor / resetPeriod; int totalOffsetFromPrevDayAnchorMin = periodsSincePrevDayAnchor * resetPeriod; DateTime prevDayAnchor = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, anchorHour, anchorMinute, 0).AddDays(-1); lastReset = prevDayAnchor.AddMinutes(totalOffsetFromPrevDayAnchorMin); } return lastReset; } public override void SetDescription() { EntryPointLongDescription = "at the " + ToString(); EntryPointShortDescription = "at the " + ToString(); ExitPointLongDescription = "at the " + ToString(); ExitPointShortDescription = "at the " + ToString(); string logic = IndParam.ListParam[0].Text; switch (logic) { case "The AdvancedSessionVWAP rises": EntryFilterLongDescription = "the " + ToString() + " rises"; EntryFilterShortDescription = "the " + ToString() + " falls"; ExitFilterLongDescription = "the " + ToString() + " rises"; ExitFilterShortDescription = "the " + ToString() + " falls"; break; case "The AdvancedSessionVWAP falls": EntryFilterLongDescription = "the " + ToString() + " falls"; EntryFilterShortDescription = "the " + ToString() + " rises"; ExitFilterLongDescription = "the " + ToString() + " falls"; ExitFilterShortDescription = "the " + ToString() + " rises"; break; case "The bar opens above the AdvancedSessionVWAP": EntryFilterLongDescription = "the bar opens above the " + ToString(); EntryFilterShortDescription = "the bar opens below the " + ToString(); break; case "The bar opens below the AdvancedSessionVWAP": EntryFilterLongDescription = "the bar opens below the " + ToString(); EntryFilterShortDescription = "the bar opens above the " + ToString(); break; case "The position opens above the AdvancedSessionVWAP": EntryFilterLongDescription = "the position opening price is higher than the " + ToString(); EntryFilterShortDescription = "the position opening price is lower than the " + ToString(); break; case "The position opens below the AdvancedSessionVWAP": EntryFilterLongDescription = "the position opening price is lower than the " + ToString(); EntryFilterShortDescription = "the position opening price is higher than the " + ToString(); break; case "The bar closes above the AdvancedSessionVWAP": ExitFilterLongDescription = "the bar closes above the " + ToString(); ExitFilterShortDescription = "the bar closes below the " + ToString(); break; case "The bar closes below the AdvancedSessionVWAP": ExitFilterLongDescription = "the bar closes below the " + ToString(); ExitFilterShortDescription = "the bar closes above the " + ToString(); break; } } public override string ToString() { string periodText = IndParam.ListParam[1].Text; if (periodText == "Session") { return IndicatorName + (IndParam.CheckParam[0].Checked ? "* (" : " (") + "Session " + IndParam.NumParam[0].Value.ToString("00") + ":" + IndParam.NumParam[1].Value.ToString("00") + ", Reset: " + IndParam.NumParam[2].Value + " min, Shift: " + IndParam.NumParam[3].Value + ")"; } else { return IndicatorName + (IndParam.CheckParam[0].Checked ? "* (" : " (") + periodText + ", Shift: " + IndParam.NumParam[3].Value + ")"; } } } }
#property copyright "NAYA 2025" #property link "NAYA +237674724684" #property version "1.0" #property strict #include <Forexsb.com/Indicator.mqh> #include <Forexsb.com/Enumerations.mqh> //+------------------------------------------------------------------+ //| AdvancedSessionVWAP: Combined AVWAP and SessionVWAP indicator | //+------------------------------------------------------------------+ class AdvancedSessionVWAP : public Indicator { public: AdvancedSessionVWAP(SlotTypes slotType) { SlotType = slotType; IndicatorName = "AdvancedSessionVWAP"; WarningMessage = "Combines Daily/Weekly/Monthly AVWAP with Session-based VWAP in one indicator."; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = false; IsDiscreteValues = false; IsDefaultGroupAll = false; } virtual void Calculate(DataSet &dataSet); private: datetime GetAnchorStartTime(datetime currentTime, int anchorType); datetime GetLastResetTime(datetime currentTime, int anchorHour, int anchorMinute, int resetPeriod); int TimeDayCount(const MqlDateTime &dt); }; void AdvancedSessionVWAP::Calculate(DataSet &dataSet) { Data = GetPointer(dataSet); // Reading parameters int periodIndex = ListParam[1].Index; // 0=Daily,1=Weekly,2=Monthly,3=Session int anchorHour = (int)NumParam[0].Value; // Anchor Hour (0-23) int anchorMinute = (int)NumParam[1].Value; // Anchor Minute (0-59) int resetPeriod = (int)NumParam[2].Value; // Reset Period in minutes int shift = (int)NumParam[3].Value; // Shift in bars int previous = CheckParam[0].Checked ? 1 : 0; // Use previous bar value const int firstBar = 3; double vwapBuffer[]; ArrayResize(vwapBuffer, Data.Bars); ArrayInitialize(vwapBuffer, 0); double shiftedVWAP[]; ArrayResize(shiftedVWAP, Data.Bars); ArrayInitialize(shiftedVWAP, 0); // Cumulative PV and V double cumPV = 0.0; double cumV = 0.0; datetime currentPeriodTime = 0; // Main loop: calculate raw (unshifted) VWAP for(int iBar = firstBar; iBar < Data.Bars; iBar++) { datetime barTime = Data.Time[iBar]; datetime periodStart; if(periodIndex < 3) { // Daily / Weekly / Monthly AVWAP logic periodStart = GetAnchorStartTime(barTime, periodIndex + 1); } else { // Session VWAP logic: adjust barTime by chart period, then get last reset datetime adjustedTime = barTime + (Period() * 60); periodStart = GetLastResetTime(adjustedTime, anchorHour, anchorMinute, resetPeriod); } // If new anchor/reset period → reset cumulatives if(periodStart != currentPeriodTime) { cumPV = 0.0; cumV = 0.0; currentPeriodTime = periodStart; } // Typical price = (Open + High + Low + Close) / 4 double typicalPrice = (Data.Open[iBar] + Data.High[iBar] + Data.Low[iBar] + Data.Close[iBar]) / 4.0; double volume = Data.Volume[iBar]; cumPV += typicalPrice * volume; cumV += volume; vwapBuffer[iBar] = (cumV > 0.0) ? (cumPV / cumV) : 0.0; } // Apply shift to get shiftedVWAP[] for(int bar = 0; bar < Data.Bars; bar++) { int src = bar - shift; if(src >= 0 && src < Data.Bars) shiftedVWAP[bar] = vwapBuffer[src]; else if(bar >= shift) shiftedVWAP[bar] = vwapBuffer[bar - shift]; else shiftedVWAP[bar] = 0.0; } // Build components if(SlotType == SlotTypes_Open || SlotType == SlotTypes_Close) { ArrayResize(Component[1].Value, Data.Bars); ArrayInitialize(Component[1].Value, 0); for(int iBar = firstBar + shift; iBar < Data.Bars; iBar++) { double v0 = shiftedVWAP[iBar - previous]; double v1 = shiftedVWAP[iBar - previous - 1]; double outPrice = v0; // Handle price gaps if((v1 > Data.High[iBar - 1] && v0 < Data.Open[iBar]) || (v1 < Data.Low[iBar - 1] && v0 > Data.Open[iBar]) || (Data.Close[iBar - 1] < v0 && v0 < Data.Open[iBar]) || (Data.Close[iBar - 1] > v0 && v0 > Data.Open[iBar])) { outPrice = Data.Open[iBar]; } Component[1].Value[iBar] = outPrice; } } else { // OpenFilter / CloseFilter: two no-chart buffers ArrayResize(Component[1].Value, Data.Bars); ArrayResize(Component[2].Value, Data.Bars); Component[1].FirstBar = firstBar + shift; Component[2].FirstBar = firstBar + shift; } // Main VWAP line (always displayed as a line) ArrayResize(Component[0].Value, Data.Bars); Component[0].CompName = "AdvancedSessionVWAP Value"; Component[0].DataType = IndComponentType_IndicatorValue; Component[0].FirstBar = firstBar + shift; ArrayCopy(Component[0].Value, shiftedVWAP); // Assign names and data types for the second component if(SlotType == SlotTypes_Open) { Component[1].CompName = "Position opening price"; Component[1].DataType = IndComponentType_OpenPrice; } else if(SlotType == SlotTypes_OpenFilter) { Component[1].CompName = "Is long entry allowed"; Component[1].DataType = IndComponentType_AllowOpenLong; Component[2].CompName = "Is short entry allowed"; Component[2].DataType = IndComponentType_AllowOpenShort; } else if(SlotType == SlotTypes_Close) { Component[1].CompName = "Position closing price"; Component[1].DataType = IndComponentType_ClosePrice; } else if(SlotType == SlotTypes_CloseFilter) { Component[1].CompName = "Close out long position"; Component[1].DataType = IndComponentType_ForceCloseLong; Component[2].CompName = "Close out short position"; Component[2].DataType = IndComponentType_ForceCloseShort; } // Apply filter logic if needed if(SlotType == SlotTypes_OpenFilter || SlotType == SlotTypes_CloseFilter) { if(ListParam[0].Text == "The AdvancedSessionVWAP rises") IndicatorRisesLogic(firstBar + shift, previous, shiftedVWAP, Component[1], Component[2]); else if(ListParam[0].Text == "The AdvancedSessionVWAP falls") IndicatorFallsLogic(firstBar + shift, previous, shiftedVWAP, Component[1], Component[2]); else if(ListParam[0].Text == "The bar opens above the AdvancedSessionVWAP") BarOpensAboveIndicatorLogic(firstBar + shift, previous, shiftedVWAP, Component[1], Component[2]); else if(ListParam[0].Text == "The bar opens below the AdvancedSessionVWAP") BarOpensBelowIndicatorLogic(firstBar + shift, previous, shiftedVWAP, Component[1], Component[2]); else if(ListParam[0].Text == "The bar opens above the AdvancedSessionVWAP after opening below it") BarOpensAboveIndicatorAfterOpeningBelowLogic(firstBar + shift, previous, shiftedVWAP, Component[1], Component[2]); else if(ListParam[0].Text == "The bar opens below the AdvancedSessionVWAP after opening above it") BarOpensBelowIndicatorAfterOpeningAboveLogic(firstBar + shift, previous, shiftedVWAP, Component[1], Component[2]); else if(ListParam[0].Text == "The position opens above the AdvancedSessionVWAP") { Component[0].PosPriceDependence = PositionPriceDependence_BuyHigherSellLower; Component[0].UsePreviousBar = previous; Component[1].ShowInDynInfo = false; Component[2].ShowInDynInfo = false; } else if(ListParam[0].Text == "The position opens below the AdvancedSessionVWAP") { Component[0].PosPriceDependence = PositionPriceDependence_BuyLowerSellHigher; Component[0].UsePreviousBar = previous; Component[1].ShowInDynInfo = false; Component[2].ShowInDynInfo = false; } else if(ListParam[0].Text == "The bar closes below the AdvancedSessionVWAP") BarClosesBelowIndicatorLogic(firstBar + shift, previous, shiftedVWAP, Component[1], Component[2]); else if(ListParam[0].Text == "The bar closes above the AdvancedSessionVWAP") BarClosesAboveIndicatorLogic(firstBar + shift, previous, shiftedVWAP, Component[1], Component[2]); } } datetime AdvancedSessionVWAP::GetAnchorStartTime(datetime currentTime, int anchorType) { // 1 = Daily, 2 = Weekly (Monday), 3 = Monthly MqlDateTime s; TimeToStruct(currentTime, s); switch(anchorType) { case 1: // Daily s.hour = s.min = s.sec = 0; break; case 2: // Weekly (Monday) while(s.day_of_week != 1) // Monday==1 { currentTime -= 86400; TimeToStruct(currentTime, s); } s.hour = s.min = s.sec = 0; break; case 3: // Monthly s.day = 1; s.hour = s.min = s.sec = 0; break; default: s.hour = s.min = s.sec = 0; break; } return StructToTime(s); } datetime AdvancedSessionVWAP::GetLastResetTime(datetime currentTime, int anchorHour, int anchorMinute, int resetPeriod) { MqlDateTime currentMqlTime; TimeToStruct(currentTime, currentMqlTime); // Calculate minutes since midnight for currentTime int currentMinutes = currentMqlTime.hour * 60 + currentMqlTime.min; int anchorMinutes = anchorHour * 60 + anchorMinute; datetime lastReset; if(currentMinutes >= anchorMinutes) { // Today's anchor has passed int minutesSinceAnchor = currentMinutes - anchorMinutes; int periodsSinceAnchor = minutesSinceAnchor / resetPeriod; int totalOffsetInMinutes = periodsSinceAnchor * resetPeriod; MqlDateTime resetTime = currentMqlTime; resetTime.hour = anchorHour; resetTime.min = anchorMinute; resetTime.sec = 0; lastReset = StructToTime(resetTime) + (totalOffsetInMinutes * 60); } else { // Today's anchor hasn't occurred → look back to the previous day int minutesSinceMidnight = currentMinutes; int minutesSincePrevDayAnchor = (1440 - anchorMinutes) + minutesSinceMidnight; int periodsSincePrevDayAnchor = minutesSincePrevDayAnchor / resetPeriod; int totalOffsetFromPrevDayAnchorMin = periodsSincePrevDayAnchor * resetPeriod; MqlDateTime prevDay = currentMqlTime; prevDay.day--; if(prevDay.day == 0) { prevDay.mon--; if(prevDay.mon == 0) { prevDay.mon = 12; prevDay.year--; } prevDay.day = TimeDayCount(prevDay); } MqlDateTime resetTime = prevDay; resetTime.hour = anchorHour; resetTime.min = anchorMinute; resetTime.sec = 0; lastReset = StructToTime(resetTime) + (totalOffsetFromPrevDayAnchorMin * 60); } return lastReset; } // Helper function to get days in month int AdvancedSessionVWAP::TimeDayCount(const MqlDateTime &dt) { if(dt.mon == 2) { // February if((dt.year % 4 == 0 && dt.year % 100 != 0) || dt.year % 400 == 0) return 29; // Leap year else return 28; } else if(dt.mon == 4 || dt.mon == 6 || dt.mon == 9 || dt.mon == 11) { return 30; } return 31; }
Risk warning: Forex, spread bets and CFD are leveraged products. They may not be suitable for you as they carry a high degree of risk to your capital and you can lose more than your initial investment. You should ensure you understand all of the risks.
Copyright © 2006 - 2025, Forex Software Ltd.;