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
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.;
Copyright © 2006 - 2025, Forex Software Ltd.;