Session VWAP MACD Stepped by Naya
556 downloads / 292 views / Created: 11.06.2025 Average Rating: 0
Indicator Description
This indicator applies MACD calculations to session-based VWAP prices with stepped reset periods. It helps identify trend direction and momentum shifts within defined trading sessions.
Key Features:
- Calculates VWAP starting from a customizable anchor time (hour/minute)
- Resets VWAP at adjustable intervals (15-1440 minutes in 15-min steps)
- Applies MACD to VWAP values with configurable periods:
- Slow MA (2-50 periods)
- Fast MA (2-50 periods)
- Signal line (2-50 periods)
- Multiple logic options for entry/exit filters
Trading Uses:
- Filter trades when MACD line rises/falls
- Identify zero-line crossovers (bullish/bearish)
- Detect signal line crossovers (momentum shifts)
- Track MACD direction changes
Works in Forex Strategy Builder for OpenFilter and CloseFilter slots.
Key Features:
- Calculates VWAP starting from a customizable anchor time (hour/minute)
- Resets VWAP at adjustable intervals (15-1440 minutes in 15-min steps)
- Applies MACD to VWAP values with configurable periods:
- Slow MA (2-50 periods)
- Fast MA (2-50 periods)
- Signal line (2-50 periods)
- Multiple logic options for entry/exit filters
Trading Uses:
- Filter trades when MACD line rises/falls
- Identify zero-line crossovers (bullish/bearish)
- Detect signal line crossovers (momentum shifts)
- Track MACD direction changes
Works in Forex Strategy Builder for OpenFilter and CloseFilter slots.
Comments
using System;
using System.Drawing;
using ForexStrategyBuilder.Infrastructure.Entities;
using ForexStrategyBuilder.Infrastructure.Enums;
using ForexStrategyBuilder.Infrastructure.Interfaces;
namespace ForexStrategyBuilder.Indicators.Custom
{
public class SessionVWAPMACDStepped : Indicator
{
public SessionVWAPMACDStepped()
{
IndicatorName = "SessionVWAPMACDStepped";
PossibleSlots = SlotTypes.OpenFilter | SlotTypes.CloseFilter;
SeparatedChart = true;
IndicatorAuthor = "NAYA,+237674724684";
IndicatorVersion = "1.0";
IndicatorDescription = "MACD calculated from SessionVWAPStepped price with stepped reset periods";
}
public override void Initialize(SlotTypes slotType)
{
SlotType = slotType;
// Logic parameter
IndParam.ListParam[0].Caption = "Logic";
IndParam.ListParam[0].ItemList = new[]
{
"MACD line rises",
"MACD line falls",
"MACD line is higher than zero",
"MACD line is lower than zero",
"MACD line crosses the zero line upward",
"MACD line crosses the zero line downward",
"MACD line changes its direction upward",
"MACD line changes its direction downward",
"MACD line crosses the Signal line upward",
"MACD line crosses the Signal line downward",
"MACD line is higher than the Signal line",
"MACD line is lower than the Signal line"
};
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 indicator.";
// Anchor Hour
IndParam.ListParam[1].Caption = "Anchor Hour (0-23)";
var hourList = new System.Collections.Generic.List();
for (int h = 0; h <= 23; h++)
hourList.Add(h.ToString("00"));
IndParam.ListParam[1].ItemList = hourList.ToArray();
IndParam.ListParam[1].Index = 0;
IndParam.ListParam[1].Text = IndParam.ListParam[1].ItemList[0];
IndParam.ListParam[1].Enabled = true;
IndParam.ListParam[1].ToolTip = "Hour component of the anchor time (0-23).";
// Anchor Minute
IndParam.ListParam[2].Caption = "Anchor Minute (0-59)";
var minuteList = new System.Collections.Generic.List();
for (int m = 0; m <= 45; m += 15)
minuteList.Add(m.ToString("00"));
IndParam.ListParam[2].ItemList = minuteList.ToArray();
IndParam.ListParam[2].Index = 0;
IndParam.ListParam[2].Text = IndParam.ListParam[2].ItemList[0];
IndParam.ListParam[2].Enabled = true;
IndParam.ListParam[2].ToolTip = "Minute component of the anchor time (0-59).";
// Reset Period
IndParam.ListParam[3].Caption = "Reset Period (minutes)";
var resetList = new System.Collections.Generic.List();
for (int m = 60; m <= 1440; m += 30)
resetList.Add(m.ToString());
IndParam.ListParam[3].ItemList = resetList.ToArray();
int defaultResetIndex = resetList.IndexOf("60");
if (defaultResetIndex < 0) defaultResetIndex = 3;
IndParam.ListParam[3].Index = defaultResetIndex;
IndParam.ListParam[3].Text = resetList[defaultResetIndex];
IndParam.ListParam[3].Enabled = true;
IndParam.ListParam[3].ToolTip = "Select how many minutes before VWAP resets (15-1440 by 15).";
// MACD Parameters
IndParam.NumParam[0].Caption = "Slow MA period";
IndParam.NumParam[0].Value = 26;
IndParam.NumParam[0].Min = 2;
IndParam.NumParam[0].Max = 50;
IndParam.NumParam[0].Enabled = true;
IndParam.NumParam[0].ToolTip = "The period of Slow MA.";
IndParam.NumParam[1].Caption = "Fast MA period";
IndParam.NumParam[1].Value = 12;
IndParam.NumParam[1].Min = 2;
IndParam.NumParam[1].Max = 50;
IndParam.NumParam[1].Enabled = true;
IndParam.NumParam[1].ToolTip = "The period of Fast MA.";
IndParam.NumParam[2].Caption = "Signal line period";
IndParam.NumParam[2].Value = 9;
IndParam.NumParam[2].Min = 2;
IndParam.NumParam[2].Max = 50;
IndParam.NumParam[2].Enabled = true;
IndParam.NumParam[2].ToolTip = "The period of Signal line.";
// Use previous bar value
IndParam.CheckParam[0].Caption = "Use previous bar value";
IndParam.CheckParam[0].Enabled = true;
IndParam.CheckParam[0].ToolTip = "Use the indicator value from the previous bar.";
}
public override void Calculate(IDataSet dataSet)
{
DataSet = dataSet;
// Read parameters
int anchorHour = int.Parse(IndParam.ListParam[1].Text);
int anchorMinute = int.Parse(IndParam.ListParam[2].Text);
int resetPeriod = int.Parse(IndParam.ListParam[3].Text);
int slowPeriod = (int)IndParam.NumParam[0].Value;
int fastPeriod = (int)IndParam.NumParam[1].Value;
int signalPeriod = (int)IndParam.NumParam[2].Value;
int previous = IndParam.CheckParam[0].Checked ? 1 : 0;
// Calculate SessionVWAPStepped price
double[] vwapPrice = CalculateVWAPPrice(anchorHour, anchorMinute, resetPeriod);
// Calculate MACD components
double[] maSlow = MovingAverage(slowPeriod, 0, MAMethod.Exponential, vwapPrice);
double[] maFast = MovingAverage(fastPeriod, 0, MAMethod.Exponential, vwapPrice);
var macd = new double[Bars];
for (int bar = slowPeriod - 1; bar < Bars; bar++)
{
macd[bar] = maFast[bar] - maSlow[bar];
}
double[] maSignalLine = MovingAverage(signalPeriod, 0, MAMethod.Simple, macd);
var histogram = new double[Bars];
for (int bar = slowPeriod + signalPeriod - 1; bar < Bars; bar++)
{
histogram[bar] = macd[bar] - maSignalLine[bar];
}
int firstBar = slowPeriod + signalPeriod + previous + 2;
// Saving the components
Component = new IndicatorComp[5];
Component[0] = new IndicatorComp
{
CompName = "Histogram",
DataType = IndComponentType.IndicatorValue,
ChartType = IndChartType.Histogram,
FirstBar = firstBar,
Value = histogram
};
Component[1] = new IndicatorComp
{
CompName = "Signal line",
DataType = IndComponentType.IndicatorValue,
ChartType = IndChartType.Line,
ChartColor = Color.Gold,
FirstBar = firstBar,
Value = maSignalLine
};
Component[2] = new IndicatorComp
{
CompName = "MACD line",
DataType = IndComponentType.IndicatorValue,
ChartType = IndChartType.Line,
ChartColor = Color.Blue,
FirstBar = firstBar,
Value = macd
};
Component[3] = new IndicatorComp
{
ChartType = IndChartType.NoChart,
FirstBar = firstBar,
Value = new double[Bars]
};
Component[4] = new IndicatorComp
{
ChartType = IndChartType.NoChart,
FirstBar = firstBar,
Value = new double[Bars]
};
// Sets the Component's type
if (SlotType == SlotTypes.OpenFilter)
{
Component[3].DataType = IndComponentType.AllowOpenLong;
Component[3].CompName = "Is long entry allowed";
Component[4].DataType = IndComponentType.AllowOpenShort;
Component[4].CompName = "Is short entry allowed";
}
else if (SlotType == SlotTypes.CloseFilter)
{
Component[3].DataType = IndComponentType.ForceCloseLong;
Component[3].CompName = "Close out long position";
Component[4].DataType = IndComponentType.ForceCloseShort;
Component[4].CompName = "Close out short position";
}
// Apply logic
switch (IndParam.ListParam[0].Text)
{
case "MACD line rises":
OscillatorLogic(firstBar, previous, macd, 0, 0, ref Component[3], ref Component[4],
IndicatorLogic.The_indicator_rises);
break;
case "MACD line falls":
OscillatorLogic(firstBar, previous, macd, 0, 0, ref Component[3], ref Component[4],
IndicatorLogic.The_indicator_falls);
break;
case "MACD line is higher than zero":
OscillatorLogic(firstBar, previous, macd, 0, 0, ref Component[3], ref Component[4],
IndicatorLogic.The_indicator_is_higher_than_the_level_line);
break;
case "MACD line is lower than zero":
OscillatorLogic(firstBar, previous, macd, 0, 0, ref Component[3], ref Component[4],
IndicatorLogic.The_indicator_is_lower_than_the_level_line);
break;
case "MACD line crosses the zero line upward":
OscillatorLogic(firstBar, previous, macd, 0, 0, ref Component[3], ref Component[4],
IndicatorLogic.The_indicator_crosses_the_level_line_upward);
break;
case "MACD line crosses the zero line downward":
OscillatorLogic(firstBar, previous, macd, 0, 0, ref Component[3], ref Component[4],
IndicatorLogic.The_indicator_crosses_the_level_line_downward);
break;
case "MACD line changes its direction upward":
OscillatorLogic(firstBar, previous, macd, 0, 0, ref Component[3], ref Component[4],
IndicatorLogic.The_indicator_changes_its_direction_upward);
break;
case "MACD line changes its direction downward":
OscillatorLogic(firstBar, previous, macd, 0, 0, ref Component[3], ref Component[4],
IndicatorLogic.The_indicator_changes_its_direction_downward);
break;
case "MACD line crosses the Signal line upward":
OscillatorLogic(firstBar, previous, histogram, 0, 0, ref Component[3], ref Component[4],
IndicatorLogic.The_indicator_crosses_the_level_line_upward);
break;
case "MACD line crosses the Signal line downward":
OscillatorLogic(firstBar, previous, histogram, 0, 0, ref Component[3], ref Component[4],
IndicatorLogic.The_indicator_crosses_the_level_line_downward);
break;
case "MACD line is higher than the Signal line":
OscillatorLogic(firstBar, previous, histogram, 0, 0, ref Component[3], ref Component[4],
IndicatorLogic.The_indicator_is_higher_than_the_level_line);
break;
case "MACD line is lower than the Signal line":
OscillatorLogic(firstBar, previous, histogram, 0, 0, ref Component[3], ref Component[4],
IndicatorLogic.The_indicator_is_lower_than_the_level_line);
break;
}
}
private double[] CalculateVWAPPrice(int anchorHour, int anchorMinute, int resetPeriod)
{
int firstBar = 3;
int bars = Bars;
double[] vwapBuffer = new double[bars];
double cumPV = 0.0;
double cumV = 0.0;
DateTime currentReset = DateTime.MinValue;
for (int iBar = firstBar; iBar < bars; iBar++)
{
DateTime barTime = Time[iBar]; // CHANGED: Removed AddMinutes(Period) to use raw bar opening time
DateTime lastReset = GetLastResetTime(barTime, anchorHour, anchorMinute, resetPeriod);
if (lastReset != currentReset)
{
cumPV = 0.0;
cumV = 0.0;
currentReset = lastReset;
}
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;
}
return vwapBuffer;
}
private DateTime GetLastResetTime(DateTime currentTime, int anchorHour, int anchorMinute, int resetPeriod)
{
int currentMinutes = currentTime.Hour * 60 + currentTime.Minute;
int anchorMinutes = anchorHour * 60 + anchorMinute;
DateTime lastReset;
if (currentMinutes >= anchorMinutes)
{
int periods = (currentMinutes - anchorMinutes) / resetPeriod;
lastReset = new DateTime(
currentTime.Year, currentTime.Month, currentTime.Day,
anchorHour, anchorMinute, 0
).AddMinutes(periods * resetPeriod);
}
else
{
DateTime prevDayAnchor = new DateTime(
currentTime.Year, currentTime.Month, currentTime.Day,
anchorHour, anchorMinute, 0
).AddDays(-1);
int minutesSincePrev = (1440 - anchorMinutes) + currentMinutes;
int periods = minutesSincePrev / resetPeriod;
lastReset = prevDayAnchor.AddMinutes(periods * resetPeriod);
}
return lastReset;
}
public override void SetDescription()
{
EntryFilterLongDescription = ToString() + "; MACD line ";
EntryFilterShortDescription = ToString() + "; MACD line ";
ExitFilterLongDescription = ToString() + "; MACD line ";
ExitFilterShortDescription = ToString() + "; MACD line ";
switch (IndParam.ListParam[0].Text)
{
case "MACD line rises":
EntryFilterLongDescription += "rises";
EntryFilterShortDescription += "falls";
ExitFilterLongDescription += "rises";
ExitFilterShortDescription += "falls";
break;
case "MACD line falls":
EntryFilterLongDescription += "falls";
EntryFilterShortDescription += "rises";
ExitFilterLongDescription += "falls";
ExitFilterShortDescription += "rises";
break;
case "MACD line is higher than zero":
EntryFilterLongDescription += "is higher than the zero line";
EntryFilterShortDescription += "is lower than the zero line";
ExitFilterLongDescription += "is higher than the zero line";
ExitFilterShortDescription += "is lower than the zero line";
break;
case "MACD line is lower than zero":
EntryFilterLongDescription += "is lower than the zero line";
EntryFilterShortDescription += "is higher than the zero line";
ExitFilterLongDescription += "is lower than the zero line";
ExitFilterShortDescription += "is higher than the zero line";
break;
case "MACD line crosses the zero line upward":
EntryFilterLongDescription += "crosses the zero line upward";
EntryFilterShortDescription += "crosses the zero line downward";
ExitFilterLongDescription += "crosses the zero line upward";
ExitFilterShortDescription += "crosses the zero line downward";
break;
case "MACD line crosses the zero line downward":
EntryFilterLongDescription += "crosses the zero line downward";
EntryFilterShortDescription += "crosses the zero line upward";
ExitFilterLongDescription += "crosses the zero line downward";
ExitFilterShortDescription += "crosses the zero line upward";
break;
case "MACD line changes its direction upward":
EntryFilterLongDescription += "changes its direction upward";
EntryFilterShortDescription += "changes its direction downward";
ExitFilterLongDescription += "changes its direction upward";
ExitFilterShortDescription += "changes its direction downward";
break;
case "MACD line changes its direction downward":
EntryFilterLongDescription += "changes its direction downward";
EntryFilterShortDescription += "changes its direction upward";
ExitFilterLongDescription += "changes its direction downward";
ExitFilterShortDescription += "changes its direction upward";
break;
case "MACD line is higher than the Signal line":
EntryFilterLongDescription += "is higher than the Signal line";
EntryFilterShortDescription += "is lower than the Signal line";
ExitFilterLongDescription += "is higher than the Signal line";
ExitFilterShortDescription += "is lower than the Signal line";
break;
case "MACD line is lower than the Signal line":
EntryFilterLongDescription += "is lower than the Signal line";
EntryFilterShortDescription += "is higher than the Signal line";
ExitFilterLongDescription += "is lower than the Signal line";
ExitFilterShortDescription += "is higher than the Signal line";
break;
case "MACD line crosses the Signal line upward":
EntryFilterLongDescription += "crosses the Signal line upward";
EntryFilterShortDescription += "crosses the Signal line downward";
ExitFilterLongDescription += "crosses the Signal line upward";
ExitFilterShortDescription += "crosses the Signal line downward";
break;
case "MACD line crosses the Signal line downward":
EntryFilterLongDescription += "crosses the Signal line downward";
EntryFilterShortDescription += "crosses the Signal line upward";
ExitFilterLongDescription += "crosses the Signal line downward";
ExitFilterShortDescription += "crosses the Signal line upward";
break;
}
}
public override string ToString()
{
return string.Format("{0}{1} (Anchor: {2}:{3}, Reset: {4} min, Slow: {5}, Fast: {6}, Signal: {7})",
IndicatorName,
(IndParam.CheckParam[0].Checked ? "*" : ""),
IndParam.ListParam[1].Text,
IndParam.ListParam[2].Text,
IndParam.ListParam[3].Text,
IndParam.NumParam[0].ValueToString,
IndParam.NumParam[1].ValueToString,
IndParam.NumParam[2].ValueToString);
}
}
}
#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 SessionVWAPMACDStepped : public Indicator { public: SessionVWAPMACDStepped(SlotTypes slotType) { SlotType = slotType; IndicatorName = "SessionVWAPMACDStepped"; WarningMessage = "MACD calculated from SessionVWAPStepped price with stepped reset periods."; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = true; IsDiscreteValues = false; IsDefaultGroupAll = false; } virtual void Calculate(DataSet &dataSet); private: void CalculateVWAP(double &vwapBuffer[], int anchorHour, int anchorMinute, int resetPeriod); datetime GetLastResetTime(datetime currentTime, int anchorHour, int anchorMinute, int resetPeriod); }; //+------------------------------------------------------------------+ void SessionVWAPMACDStepped::Calculate(DataSet &dataSet) { Data = GetPointer(dataSet); //--- parameters string logic = ListParam[0].Text; int anchorHour = (int)StringToInteger(ListParam[1].Text); int anchorMinute = (int)StringToInteger(ListParam[2].Text); int resetPeriod = (int)StringToInteger(ListParam[3].Text); int slowPeriod = (int)NumParam[0].Value; int fastPeriod = (int)NumParam[1].Value; int signalPeriod = (int)NumParam[2].Value; int previous = CheckParam[0].Checked ? 1 : 0; const int firstStepped = 3; int bars = Data.Bars; //--- 1) Compute stepped VWAP using GetLastResetTime double vwapBuffer[]; ArrayResize(vwapBuffer, bars); CalculateVWAP(vwapBuffer, anchorHour, anchorMinute, resetPeriod); //--- 2) MACD on vwapBuffer double maSlow[], maFast[]; ArrayResize(maSlow, bars); ArrayResize(maFast, bars); MovingAverage(slowPeriod, 0, MAMethod_Exponential, vwapBuffer, maSlow); MovingAverage(fastPeriod, 0, MAMethod_Exponential, vwapBuffer, maFast); double macd[]; ArrayResize(macd, bars); for(int bar = slowPeriod - 1; bar < bars; bar++) macd[bar] = maFast[bar] - maSlow[bar]; double maSignal[]; ArrayResize(maSignal, bars); MovingAverage(signalPeriod, 0, MAMethod_Simple, macd, maSignal); double histogram[]; ArrayResize(histogram, bars); for(int bar = slowPeriod + signalPeriod - 1; bar < bars; bar++) histogram[bar] = macd[bar] - maSignal[bar]; int firstBar = slowPeriod + signalPeriod + previous + 2; //--- 3) Prepare 5 components // Histogram ArrayResize(Component[0].Value, bars); Component[0].CompName = "Histogram"; Component[0].DataType = IndComponentType_IndicatorValue; Component[0].FirstBar = firstBar; ArrayCopy(Component[0].Value, histogram); // Signal line ArrayResize(Component[1].Value, bars); Component[1].CompName = "Signal line"; Component[1].DataType = IndComponentType_IndicatorValue; Component[1].FirstBar = firstBar; ArrayCopy(Component[1].Value, maSignal); // MACD line ArrayResize(Component[2].Value, bars); Component[2].CompName = "MACD line"; Component[2].DataType = IndComponentType_IndicatorValue; Component[2].FirstBar = firstBar; ArrayCopy(Component[2].Value, macd); // Two no-chart buffers for open/close filters ArrayResize(Component[3].Value, bars); Component[3].FirstBar = firstBar; ArrayInitialize(Component[3].Value,0.0); ArrayResize(Component[4].Value, bars); Component[4].FirstBar = firstBar; ArrayInitialize(Component[4].Value,0.0); //--- 4) Assign types based on slot if(SlotType == SlotTypes_OpenFilter) { Component[3].DataType = IndComponentType_AllowOpenLong; Component[3].CompName = "Is long entry allowed"; Component[4].DataType = IndComponentType_AllowOpenShort; Component[4].CompName = "Is short entry allowed"; } else if(SlotType == SlotTypes_CloseFilter) { Component[3].DataType = IndComponentType_ForceCloseLong; Component[3].CompName = "Close out long position"; Component[4].DataType = IndComponentType_ForceCloseShort; Component[4].CompName = "Close out short position"; } //--- 5) Apply chosen logic (uses macd[] or histogram[]) if(SlotType == SlotTypes_OpenFilter || SlotType == SlotTypes_CloseFilter) { if(logic == "MACD line rises") OscillatorLogic(firstBar, previous, macd, 0,0, Component[3], Component[4], IndicatorLogic_The_indicator_rises); else if(logic == "MACD line falls") OscillatorLogic(firstBar, previous, macd, 0,0, Component[3], Component[4], IndicatorLogic_The_indicator_falls); else if(logic == "MACD line is higher than zero") OscillatorLogic(firstBar, previous, macd, 0,0, Component[3], Component[4], IndicatorLogic_The_indicator_is_higher_than_the_level_line); else if(logic == "MACD line is lower than zero") OscillatorLogic(firstBar, previous, macd, 0,0, Component[3], Component[4], IndicatorLogic_The_indicator_is_lower_than_the_level_line); else if(logic == "MACD line crosses the zero line upward") OscillatorLogic(firstBar, previous, macd, 0,0, Component[3], Component[4], IndicatorLogic_The_indicator_crosses_the_level_line_upward); else if(logic == "MACD line crosses the zero line downward") OscillatorLogic(firstBar, previous, macd, 0,0, Component[3], Component[4], IndicatorLogic_The_indicator_crosses_the_level_line_downward); else if(logic == "MACD line changes its direction upward") OscillatorLogic(firstBar, previous, macd, 0,0, Component[3], Component[4], IndicatorLogic_The_indicator_changes_its_direction_upward); else if(logic == "MACD line changes its direction downward") OscillatorLogic(firstBar, previous, macd, 0,0, Component[3], Component[4], IndicatorLogic_The_indicator_changes_its_direction_downward); else if(logic == "MACD line crosses the Signal line upward") OscillatorLogic(firstBar, previous, histogram, 0,0, Component[3], Component[4], IndicatorLogic_The_indicator_crosses_the_level_line_upward); else if(logic == "MACD line crosses the Signal line downward") OscillatorLogic(firstBar, previous, histogram, 0,0, Component[3], Component[4], IndicatorLogic_The_indicator_crosses_the_level_line_downward); else if(logic == "MACD line is higher than the Signal line") OscillatorLogic(firstBar, previous, histogram, 0,0, Component[3], Component[4], IndicatorLogic_The_indicator_is_higher_than_the_level_line); else if(logic == "MACD line is lower than the Signal line") OscillatorLogic(firstBar, previous, histogram, 0,0, Component[3], Component[4], IndicatorLogic_The_indicator_is_lower_than_the_level_line); } } //+------------------------------------------------------------------+ void SessionVWAPMACDStepped::CalculateVWAP(double &vwapBuffer[], int anchorHour, int anchorMinute, int resetPeriod) { const int firstStepped = 3; double cumPV = 0.0, cumV = 0.0; datetime currentReset = 0; int bars = Data.Bars; for(int bar = firstStepped; bar < bars; bar++) { // CHANGED: Removed Period()*60 adjustment to use raw bar opening time datetime barTime = Data.Time[bar]; datetime lastReset = GetLastResetTime(barTime, anchorHour, anchorMinute, resetPeriod); if(lastReset != currentReset) { cumPV = 0.0; cumV = 0.0; currentReset = lastReset; } double tp = (Data.Open[bar] + Data.High[bar] + Data.Low[bar] + Data.Close[bar]) / 4.0; double vol = (double)Data.Volume[bar]; cumPV += tp * vol; cumV += vol; vwapBuffer[bar] = (cumV > 0.0) ? (cumPV / cumV) : 0.0; } } //+------------------------------------------------------------------+ datetime SessionVWAPMACDStepped::GetLastResetTime(datetime currentTime, int anchorHour, int anchorMinute, int resetPeriod) { MqlDateTime tm; TimeToStruct(currentTime, tm); int currentMinutes = tm.hour*60 + tm.min; int anchorMinutes = anchorHour*60 + anchorMinute; datetime lastReset; if(currentMinutes >= anchorMinutes) { tm.hour = anchorHour; tm.min = anchorMinute; tm.sec = 0; datetime anchorToday = StructToTime(tm); int periods = (currentMinutes - anchorMinutes) / resetPeriod; lastReset = anchorToday + (datetime)(periods * resetPeriod * 60); } else { tm.hour = anchorHour; tm.min = anchorMinute; tm.sec = 0; datetime anchorPrev = StructToTime(tm) - 86400; int minutesSincePrev = (1440 - anchorMinutes) + currentMinutes; int periods = minutesSincePrev / resetPeriod; lastReset = anchorPrev + (datetime)(periods * resetPeriod * 60); } return(lastReset); } //+------------------------------------------------------------------+
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.;