AdvancedSessionVWAPStepped by Naya
729 downloads / 369 views / Created: 31.05.2025 Average Rating: 0
Indicator Description
Indicator Name:AdvancedSessionVWAPStepped
Description:
AdvancedSessionVWAPStepped is a custom VWAP (Volume Weighted Average Price) indicator designed for session-based trading. It calculates VWAP starting from a user-defined anchor time and includes a stepped reset feature, which allows the VWAP to reset periodically within the same session (e.g., every 30 minutes, every hour).
This is useful for intraday traders and scalpers who want VWAP values that reflect more recent price and volume activity instead of one continuous calculation across the full day or session.
Key Features:
* Anchored VWAP starting from a specific hour and minute.
* Optional reset of VWAP at a fixed interval (e.g., every N minutes).
* Works across different time periods: Daily, Weekly, Monthly, or Custom Session.
* Option to shift the VWAP value forward or backward by a number of bars.
* Option to use the VWAP from the previous period instead of the current one.
* Can be used in any slot: Open, Open Filter, Close, Close Filter.
Calculation Logic:
* The indicator starts VWAP calculation at the user-specified hour and minute.
* Within each trading period (like a day), the VWAP can be reset at defined time intervals (e.g., every 30 minutes).
* VWAP is calculated as:
VWAP = (Sum of (Price × Volume)) / (Sum of Volume)
where Price is typically the average of Open, High, Low, and Close.
* The indicator stores VWAP values in a buffer and applies optional shifting.
* If "Use Previous Period" is enabled, it displays the VWAP from the prior day/week/month instead of the current one.
Indicator Parameters:
* Price: Price base used for VWAP (e.g., Median, Typical).
* Period: Reset frequency scope (Daily, Weekly, Monthly, Session).
* Anchor Hour: Hour to start VWAP calculation.
* Anchor Minute: Minute to start VWAP calculation.
* Reset Period (min): Number of minutes after which VWAP resets during a session.
* Shift: Number of bars to shift VWAP value (positive or negative).
* Use Previous Period: If true, uses the VWAP from the previous period.
Use Cases:
* Intraday scalping using 30-minute stepped VWAP.
* Detecting breakouts with previous session VWAP.
* Mean reversion or pullback strategies around stepped VWAP.
* Filtering entries when price is above or below a stepped VWAP zone.
Slot Compatibility in FSB Pro:
* Open: Yes
* Open Filter: Yes
* Close: Yes
* Close Filter: Yes
Created with the help of DeepSeek AI and Claude AI
Description:
AdvancedSessionVWAPStepped is a custom VWAP (Volume Weighted Average Price) indicator designed for session-based trading. It calculates VWAP starting from a user-defined anchor time and includes a stepped reset feature, which allows the VWAP to reset periodically within the same session (e.g., every 30 minutes, every hour).
This is useful for intraday traders and scalpers who want VWAP values that reflect more recent price and volume activity instead of one continuous calculation across the full day or session.
Key Features:
* Anchored VWAP starting from a specific hour and minute.
* Optional reset of VWAP at a fixed interval (e.g., every N minutes).
* Works across different time periods: Daily, Weekly, Monthly, or Custom Session.
* Option to shift the VWAP value forward or backward by a number of bars.
* Option to use the VWAP from the previous period instead of the current one.
* Can be used in any slot: Open, Open Filter, Close, Close Filter.
Calculation Logic:
* The indicator starts VWAP calculation at the user-specified hour and minute.
* Within each trading period (like a day), the VWAP can be reset at defined time intervals (e.g., every 30 minutes).
* VWAP is calculated as:
VWAP = (Sum of (Price × Volume)) / (Sum of Volume)
where Price is typically the average of Open, High, Low, and Close.
* The indicator stores VWAP values in a buffer and applies optional shifting.
* If "Use Previous Period" is enabled, it displays the VWAP from the prior day/week/month instead of the current one.
Indicator Parameters:
* Price: Price base used for VWAP (e.g., Median, Typical).
* Period: Reset frequency scope (Daily, Weekly, Monthly, Session).
* Anchor Hour: Hour to start VWAP calculation.
* Anchor Minute: Minute to start VWAP calculation.
* Reset Period (min): Number of minutes after which VWAP resets during a session.
* Shift: Number of bars to shift VWAP value (positive or negative).
* Use Previous Period: If true, uses the VWAP from the previous period.
Use Cases:
* Intraday scalping using 30-minute stepped VWAP.
* Detecting breakouts with previous session VWAP.
* Mean reversion or pullback strategies around stepped VWAP.
* Filtering entries when price is above or below a stepped VWAP zone.
Slot Compatibility in FSB Pro:
* Open: Yes
* Open Filter: Yes
* Close: Yes
* Close Filter: Yes
Created with the help of DeepSeek AI and Claude AI
Comments
using System;
using System.Collections.Generic;
using System.Drawing;
using ForexStrategyBuilder.Infrastructure.Entities;
using ForexStrategyBuilder.Infrastructure.Enums;
using ForexStrategyBuilder.Infrastructure.Interfaces;
namespace ForexStrategyBuilder.Indicators.Custom
{
public class AdvancedSessionVWAPStepped : Indicator
{
public AdvancedSessionVWAPStepped()
{
IndicatorName = "AdvancedSessionVWAPStepped";
PossibleSlots = SlotTypes.Open | SlotTypes.OpenFilter | SlotTypes.Close | SlotTypes.CloseFilter;
IndicatorAuthor = "NAYA,+237674724684";
IndicatorVersion = "1.0";
IndicatorDescription = "Combines AVWAP with Session-based VWAP using stepped time intervals.";
}
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 AdvancedSessionVWAPStepped" };
break;
case SlotTypes.OpenFilter:
IndParam.ListParam[0].ItemList = new[]
{
"The AdvancedSessionVWAPStepped rises",
"The AdvancedSessionVWAPStepped falls",
"The bar opens above the AdvancedSessionVWAPStepped",
"The bar opens below the AdvancedSessionVWAPStepped",
"The bar opens above the AdvancedSessionVWAPStepped after opening below it",
"The bar opens below the AdvancedSessionVWAPStepped after opening above it",
};
break;
case SlotTypes.Close:
IndParam.ListParam[0].ItemList = new[] { "Exit the market at the AdvancedSessionVWAPStepped" };
break;
case SlotTypes.CloseFilter:
IndParam.ListParam[0].ItemList = new[]
{
"The AdvancedSessionVWAPStepped rises",
"The AdvancedSessionVWAPStepped falls",
"The bar closes below the AdvancedSessionVWAPStepped",
"The bar closes above the AdvancedSessionVWAPStepped",
};
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 AdvancedSessionVWAPStepped.";
// 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 (for Session)
IndParam.ListParam[2].Caption = "Anchor Hour";
var hours = new List();
for (int i = 0; i <= 23; i++)
hours.Add(i.ToString("00"));
IndParam.ListParam[2].ItemList = hours.ToArray();
IndParam.ListParam[2].Index = 0;
IndParam.ListParam[2].Text = IndParam.ListParam[2].ItemList[0];
IndParam.ListParam[2].Enabled = true;
IndParam.ListParam[2].ToolTip = "Hour component (00-23) of the anchor time (Session only).";
// Anchor Minute (for Session)
IndParam.ListParam[3].Caption = "Anchor Minute";
var minutes = new List();
for (int i = 0; i <= 45; i += 15)
minutes.Add(i.ToString("00"));
IndParam.ListParam[3].ItemList = minutes.ToArray();
IndParam.ListParam[3].Index = 0;
IndParam.ListParam[3].Text = IndParam.ListParam[3].ItemList[0];
IndParam.ListParam[3].Enabled = true;
IndParam.ListParam[3].ToolTip = "Minute component (00,15,30,45) of the anchor time (Session only).";
// Reset Period (minutes, for Session)
IndParam.ListParam[4].Caption = "Reset Period (minutes)";
var periods = new List();
for (int i = 60; i <= 1440; i += 60)
periods.Add(i.ToString());
IndParam.ListParam[4].ItemList = periods.ToArray();
IndParam.ListParam[4].Index = 0;
IndParam.ListParam[4].Text = IndParam.ListParam[4].ItemList[0];
IndParam.ListParam[4].Enabled = true;
IndParam.ListParam[4].ToolTip = "Session reset period in minutes (60-1440 in steps of 60, Session only).";
// Shift (bars)
IndParam.NumParam[0].Caption = "Shift (bars)";
IndParam.NumParam[0].Value = 0;
IndParam.NumParam[0].Min = 0;
IndParam.NumParam[0].Max = 2;
IndParam.NumParam[0].Enabled = false;
IndParam.NumParam[0].ToolTip = "Number of bars to shift the VWAP.";
// 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.";
}
public override void Calculate(IDataSet dataSet)
{
DataSet = dataSet;
int bars = Bars;
int firstBar = 3;
// Read parameters
int periodIndex = IndParam.ListParam[1].Index;
int anchorHour = int.Parse(IndParam.ListParam[2].Text);
int anchorMinute = int.Parse(IndParam.ListParam[3].Text);
int resetPeriod = int.Parse(IndParam.ListParam[4].Text);
int shift = (int)IndParam.NumParam[0].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]; // Use MT4 CSV timestamp (bar opening time)
DateTime periodStart;
if (periodIndex < 3)
{
// Daily/Weekly/Monthly AVWAP logic
periodStart = GetAnchorStartTime(barTime, periodIndex + 1);
}
else
{
// Session VWAP with stepped times
DateTime barEndTime = barTime.AddMinutes((int)Period); // Bar end time
periodStart = GetLastResetTimeStepped(barEndTime, 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)
{
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
Component[0] = new IndicatorComp
{
CompName = "AdvancedSessionVWAPStepped Value",
DataType = IndComponentType.IndicatorValue,
ChartType = IndChartType.Line,
ChartColor = Color.DarkBlue,
FirstBar = firstBar + shift,
Value = shiftedVWAP
};
// Assign names and data types
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 AdvancedSessionVWAPStepped rises":
IndicatorRisesLogic(firstBar + shift, usePrev, shiftedVWAP, ref Component[1], ref Component[2]);
break;
case "The AdvancedSessionVWAPStepped falls":
IndicatorFallsLogic(firstBar + shift, usePrev, shiftedVWAP, ref Component[1], ref Component[2]);
break;
case "The bar opens above the AdvancedSessionVWAPStepped":
BarOpensAboveIndicatorLogic(firstBar + shift, usePrev, shiftedVWAP, ref Component[1], ref Component[2]);
break;
case "The bar opens below the AdvancedSessionVWAPStepped":
BarOpensBelowIndicatorLogic(firstBar + shift, usePrev, shiftedVWAP, ref Component[1], ref Component[2]);
break;
case "The bar opens above the AdvancedSessionVWAPStepped after opening below it":
BarOpensAboveIndicatorAfterOpeningBelowLogic(firstBar + shift, usePrev, shiftedVWAP, ref Component[1], ref Component[2]);
break;
case "The bar opens below the AdvancedSessionVWAPStepped after opening above it":
BarOpensBelowIndicatorAfterOpeningAboveLogic(firstBar + shift, usePrev, shiftedVWAP, ref Component[1], ref Component[2]);
break;
case "The position opens above the AdvancedSessionVWAPStepped":
Component[0].PosPriceDependence = PositionPriceDependence.BuyHigherSellLower;
Component[0].UsePreviousBar = usePrev;
Component[1].ShowInDynInfo = false;
Component[2].ShowInDynInfo = false;
break;
case "The position opens below the AdvancedSessionVWAPStepped":
Component[0].PosPriceDependence = PositionPriceDependence.BuyLowerSellHigher;
Component[0].UsePreviousBar = usePrev;
Component[1].ShowInDynInfo = false;
Component[2].ShowInDynInfo = false;
break;
case "The bar closes below the AdvancedSessionVWAPStepped":
BarClosesBelowIndicatorLogic(firstBar + shift, usePrev, shiftedVWAP, ref Component[1], ref Component[2]);
break;
case "The bar closes above the AdvancedSessionVWAPStepped":
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: return currentTime.Date;
case 2:
DateTime monday = currentTime.Date;
while (monday.DayOfWeek != DayOfWeek.Monday)
monday = monday.AddDays(-1);
return monday;
case 3: return new DateTime(currentTime.Year, currentTime.Month, 1);
default: return currentTime.Date;
}
}
private DateTime GetLastResetTimeStepped(DateTime currentTime, int anchorHour, int anchorMinute, int resetPeriod)
{
DateTime anchorTimeToday = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, anchorHour, anchorMinute, 0);
DateTime anchorTimeYesterday = anchorTimeToday.AddDays(-1);
int currentMinutes = currentTime.Hour * 60 + currentTime.Minute;
int anchorMinutes = anchorHour * 60 + anchorMinute;
if (currentMinutes >= anchorMinutes)
{
int minutesSinceAnchor = currentMinutes - anchorMinutes;
int periodsSinceAnchor = minutesSinceAnchor / resetPeriod;
return anchorTimeToday.AddMinutes(periodsSinceAnchor * resetPeriod);
}
else
{
int minutesSinceMidnight = currentMinutes;
int minutesSincePrevDayAnchor = (1440 - anchorMinutes) + minutesSinceMidnight;
int periodsSincePrevDayAnchor = minutesSincePrevDayAnchor / resetPeriod;
return anchorTimeYesterday.AddMinutes(periodsSincePrevDayAnchor * resetPeriod);
}
}
public override void SetDescription()
{
string periodText = IndParam.ListParam[1].Text;
string description = periodText == "Session"
? "AdvancedSessionVWAPStepped (Session {IndParam.ListParam[2].Text.PadLeft(2, '0')}:{IndParam.ListParam[3].Text.PadLeft(2, '0')}, Reset: {IndParam.ListParam[4].Text} min)"
: "AdvancedSessionVWAPStepped ({periodText})";
EntryPointLongDescription = "at the " + description;
EntryPointShortDescription = "at the " + description;
ExitPointLongDescription = "at the " + description;
ExitPointShortDescription = "at the " + description;
string logic = IndParam.ListParam[0].Text;
switch (logic)
{
case "The AdvancedSessionVWAPStepped rises":
EntryFilterLongDescription = "the " + description + " rises";
EntryFilterShortDescription = "the " + description + " falls";
ExitFilterLongDescription = "the " + description + " rises";
ExitFilterShortDescription = "the " + description + " falls";
break;
case "The AdvancedSessionVWAPStepped falls":
EntryFilterLongDescription = "the " + description + " falls";
EntryFilterShortDescription = "the " + description + " rises";
ExitFilterLongDescription = "the " + description + " falls";
ExitFilterShortDescription = "the " + description + " rises";
break;
case "The bar opens above the AdvancedSessionVWAPStepped":
EntryFilterLongDescription = "the bar opens above the " + description;
EntryFilterShortDescription = "the bar opens below the " + description;
break;
case "The bar opens below the AdvancedSessionVWAPStepped":
EntryFilterLongDescription = "the bar opens below the " + description;
EntryFilterShortDescription = "the bar opens above the " + description;
break;
case "The position opens above the AdvancedSessionVWAPStepped":
EntryFilterLongDescription = "the position opening price is higher than the " + description;
EntryFilterShortDescription = "the position opening price is lower than the " + description;
break;
case "The position opens below the AdvancedSessionVWAPStepped":
EntryFilterLongDescription = "the position opening price is lower than the " + description;
EntryFilterShortDescription = "the position opening price is higher than the " + description;
break;
case "The bar closes above the AdvancedSessionVWAPStepped":
ExitFilterLongDescription = "the bar closes above the " + description;
ExitFilterShortDescription = "the bar closes below the " + description;
break;
case "The bar closes below the AdvancedSessionVWAPStepped":
ExitFilterLongDescription = "the bar closes below the " + description;
ExitFilterShortDescription = "the bar closes above the " + description;
break;
}
}
public override string ToString()
{
string periodText = IndParam.ListParam[1].Text;
if (periodText == "Session")
{
return "{IndicatorName} (Session {IndParam.ListParam[2].Text.PadLeft(2, '0')}:{IndParam.ListParam[3].Text.PadLeft(2, '0')}, Reset: {IndParam.ListParam[4].Text} min, Shift: {IndParam.NumParam[0].Value})";
}
return "{IndicatorName} ({periodText}, Shift: {IndParam.NumParam[0].Value})";
}
}
}
#property copyright "Copyright (C) 2025 NAYA +237674724684" #property link "NAYA +237674724684" #property version "1.0" #property strict #include <Forexsb.com/Indicator.mqh> #include <Forexsb.com/Enumerations.mqh> class AdvancedSessionVWAPStepped : public Indicator { public: AdvancedSessionVWAPStepped(SlotTypes slotType); virtual void Calculate(DataSet &dataSet); private: datetime GetAnchorStartTime(datetime currentTime, int anchorType); datetime GetLastResetTimeStepped(datetime currentTime, int anchorHour, int anchorMinute, int resetPeriod); int TimeDayCount(const MqlDateTime &dt); }; void AdvancedSessionVWAPStepped::AdvancedSessionVWAPStepped(SlotTypes slotType) { SlotType = slotType; IndicatorName = "AdvancedSessionVWAPStepped"; WarningMessage = "Combines AVWAP with Session-based VWAP using stepped time intervals."; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = false; IsDiscreteValues = false; IsDefaultGroupAll = false; } void AdvancedSessionVWAPStepped::Calculate(DataSet &dataSet) { Data = GetPointer(dataSet); // Reading parameters int periodIndex = ListParam[1].Index; // 0=Daily,1=Weekly,2=Monthly,3=Session int anchorHour = (int)StringToInteger(ListParam[2].Text); // Anchor Hour (0-23) int anchorMinute = (int)StringToInteger(ListParam[3].Text); // Anchor Minute (0,15,30,45) int resetPeriod = (int)StringToInteger(ListParam[4].Text); // Reset Period in minutes (240-1440 in steps of 240) int shift = (int)NumParam[0].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]; // MT4 bar opening time datetime periodStart; if(periodIndex < 3) { // Daily / Weekly / Monthly AVWAP logic periodStart = GetAnchorStartTime(barTime, periodIndex + 1); } else { // Session VWAP with stepped times datetime barEndTime = barTime + (Period() * 60); // Bar end time periodStart = GetLastResetTimeStepped(barEndTime, 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 = "AdvancedSessionVWAPStepped 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 AdvancedSessionVWAPStepped rises") IndicatorRisesLogic(firstBar + shift, previous, shiftedVWAP, Component[1], Component[2]); else if(ListParam[0].Text == "The AdvancedSessionVWAPStepped falls") IndicatorFallsLogic(firstBar + shift, previous, shiftedVWAP, Component[1], Component[2]); else if(ListParam[0].Text == "The bar opens above the AdvancedSessionVWAPStepped") BarOpensAboveIndicatorLogic(firstBar + shift, previous, shiftedVWAP, Component[1], Component[2]); else if(ListParam[0].Text == "The bar opens below the AdvancedSessionVWAPStepped") BarOpensBelowIndicatorLogic(firstBar + shift, previous, shiftedVWAP, Component[1], Component[2]); else if(ListParam[0].Text == "The bar opens above the AdvancedSessionVWAPStepped after opening below it") BarOpensAboveIndicatorAfterOpeningBelowLogic(firstBar + shift, previous, shiftedVWAP, Component[1], Component[2]); else if(ListParam[0].Text == "The bar opens below the AdvancedSessionVWAPStepped after opening above it") BarOpensBelowIndicatorAfterOpeningAboveLogic(firstBar + shift, previous, shiftedVWAP, Component[1], Component[2]); else if(ListParam[0].Text == "The position opens above the AdvancedSessionVWAPStepped") { 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 AdvancedSessionVWAPStepped") { 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 AdvancedSessionVWAPStepped") BarClosesBelowIndicatorLogic(firstBar + shift, previous, shiftedVWAP, Component[1], Component[2]); else if(ListParam[0].Text == "The bar closes above the AdvancedSessionVWAPStepped") BarClosesAboveIndicatorLogic(firstBar + shift, previous, shiftedVWAP, Component[1], Component[2]); } } datetime AdvancedSessionVWAPStepped::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 AdvancedSessionVWAPStepped::GetLastResetTimeStepped(datetime currentTime, int anchorHour, int anchorMinute, int resetPeriod) { MqlDateTime currentMqlTime; TimeToStruct(currentTime, currentMqlTime); // Create anchor time for today MqlDateTime anchorToday = currentMqlTime; anchorToday.hour = anchorHour; anchorToday.min = anchorMinute; anchorToday.sec = 0; datetime anchorTimeToday = StructToTime(anchorToday); // Calculate minutes int currentMinutes = currentMqlTime.hour * 60 + currentMqlTime.min; int anchorMinutes = anchorHour * 60 + anchorMinute; if(currentMinutes >= anchorMinutes) { // Today's anchor has passed int minutesSinceAnchor = currentMinutes - anchorMinutes; int periodsSinceAnchor = minutesSinceAnchor / resetPeriod; return anchorTimeToday + (periodsSinceAnchor * resetPeriod * 60); } else { // Today's anchor hasn't occurred yet int minutesSinceMidnight = currentMinutes; int minutesSincePrevDayAnchor = (1440 - anchorMinutes) + minutesSinceMidnight; int periodsSincePrevDayAnchor = minutesSincePrevDayAnchor / resetPeriod; // Get yesterday's anchor time MqlDateTime anchorYesterday = currentMqlTime; anchorYesterday.day--; if(anchorYesterday.day == 0) { anchorYesterday.mon--; if(anchorYesterday.mon == 0) { anchorYesterday.mon = 12; anchorYesterday.year--; } anchorYesterday.day = TimeDayCount(anchorYesterday); } anchorYesterday.hour = anchorHour; anchorYesterday.min = anchorMinute; anchorYesterday.sec = 0; return StructToTime(anchorYesterday) + (periodsSincePrevDayAnchor * resetPeriod * 60); } } int AdvancedSessionVWAPStepped::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.;
Copyright © 2006 - 2025, Forex Software Ltd.;