AVWAP Crossover by Naya
96 downloads / 67 views / Created: 06.06.2025 Average Rating: 0
Indicator Description
AVWAP Crossover is a filter indicator that plots two Anchored Volume Weighted Average Price lines—one “fast” and one “slow”—each reset at daily, weekly, or monthly anchor points. It compares the fast and slow AVWAP values in various ways: crossing above or below, staying higher or lower, or both rising or falling together. Traders can choose a bar shift and opt to use the previous bar’s values when generating signals. Depending on the chosen logic, the indicator will allow or force entry and exit based on how the fast and slow AVWAP lines interact.
Comments
using System;
using System.Drawing;
using ForexStrategyBuilder.Infrastructure.Entities;
using ForexStrategyBuilder.Infrastructure.Enums;
using ForexStrategyBuilder.Infrastructure.Interfaces;
namespace ForexStrategyBuilder.Indicators.Store
{
public class AVWAPCrossover : Indicator
{
public AVWAPCrossover()
{
IndicatorName = "AVWAP Crossover";
PossibleSlots = SlotTypes.OpenFilter | SlotTypes.CloseFilter;
IndicatorAuthor = "NAYA +237674724684";
IndicatorVersion = "1.0";
IndicatorDescription = "Anchored VWAP crossover with configurable anchor periods";
}
public override void Initialize(SlotTypes slotType)
{
SlotType = slotType;
// Logic selection
IndParam.ListParam[0].Caption = "Logic";
IndParam.ListParam[0].ItemList = new[]
{
"Fast AVWAP crosses Slow AVWAP upward",
"Fast AVWAP crosses Slow AVWAP downward",
"Fast AVWAP is higher than Slow AVWAP",
"Fast AVWAP is lower than Slow AVWAP",
"Fast AVWAP rises, Slow AVWAP falls",
"Fast AVWAP falls, Slow AVWAP rises",
"Fast AVWAP rises, Slow AVWAP rises",
"Fast AVWAP falls, Slow AVWAP falls"
};
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.";
// Fast AVWAP parameters
IndParam.ListParam[1].Caption = "Fast Anchor Period";
IndParam.ListParam[1].ItemList = new[] { "Daily", "Weekly", "Monthly" };
IndParam.ListParam[1].Index = 0;
IndParam.ListParam[1].Text = IndParam.ListParam[1].ItemList[0];
IndParam.ListParam[1].Enabled = true;
IndParam.ListParam[1].ToolTip = "Anchor period for Fast AVWAP";
IndParam.NumParam[0].Caption = "Fast AVWAP Shift";
IndParam.NumParam[0].Value = 0;
IndParam.NumParam[0].Min = 0;
IndParam.NumParam[0].Max = 2;
IndParam.NumParam[0].Enabled = false;
IndParam.NumParam[0].ToolTip = "Shift for Fast AVWAP in bars";
// Slow AVWAP parameters
IndParam.ListParam[2].Caption = "Slow Anchor Period";
IndParam.ListParam[2].ItemList = new[] { "Daily", "Weekly", "Monthly" };
IndParam.ListParam[2].Index = 1;
IndParam.ListParam[2].Text = IndParam.ListParam[2].ItemList[1];
IndParam.ListParam[2].Enabled = true;
IndParam.ListParam[2].ToolTip = "Anchor period for Slow AVWAP";
IndParam.NumParam[1].Caption = "Slow AVWAP Shift";
IndParam.NumParam[1].Value = 0;
IndParam.NumParam[1].Min = 0;
IndParam.NumParam[1].Max = 2;
IndParam.NumParam[1].Enabled = false;
IndParam.NumParam[1].ToolTip = "Shift for Slow AVWAP in bars";
// Checkbox parameter
IndParam.CheckParam[0].Caption = "Use previous bar value";
IndParam.CheckParam[0].Enabled = true;
IndParam.CheckParam[0].ToolTip = "Use previous bar's value for signals";
}
private double[] CalculateAVWAP(int anchorPeriod, int shift)
{
double[] avwap = new double[Bars];
double cumPV = 0;
double cumV = 0;
DateTime currentAnchor = DateTime.MinValue;
for (int bar = 1; bar < Bars; bar++)
{
DateTime barTime = DataSet.Time[bar];
DateTime anchorTime = GetAnchorTime(barTime, anchorPeriod);
if (anchorTime != currentAnchor)
{
cumPV = 0;
cumV = 0;
currentAnchor = anchorTime;
}
double typicalPrice = (DataSet.Open[bar] + DataSet.High[bar] +
DataSet.Low[bar] + DataSet.Close[bar]) / 4.0;
double volume = DataSet.Volume[bar];
cumPV += typicalPrice * volume;
cumV += volume;
avwap[bar] = (cumV > 0) ? (cumPV / cumV) : 0.0;
}
// Apply shift
double[] shiftedAVWAP = new double[Bars];
for (int bar = 0; bar < Bars; bar++)
{
int sourceBar = bar - shift;
shiftedAVWAP[bar] = (sourceBar >= 0 && sourceBar < Bars) ? avwap[sourceBar] : 0;
}
return shiftedAVWAP;
}
private DateTime GetAnchorTime(DateTime currentTime, int anchorPeriod)
{
switch (anchorPeriod)
{
case 0: // Daily
return new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, 0, 0, 0);
case 1: // Weekly (Monday)
DateTime monday = currentTime.AddDays(-(int)currentTime.DayOfWeek + (int)DayOfWeek.Monday);
return new DateTime(monday.Year, monday.Month, monday.Day, 0, 0, 0);
case 2: // Monthly
return new DateTime(currentTime.Year, currentTime.Month, 1, 0, 0, 0);
default:
return DateTime.MinValue;
}
}
public override void Calculate(IDataSet dataSet)
{
DataSet = dataSet;
// Read parameters
int fastAnchor = IndParam.ListParam[1].Index;
int fastShift = (int)IndParam.NumParam[0].Value;
int slowAnchor = IndParam.ListParam[2].Index;
int slowShift = (int)IndParam.NumParam[1].Value;
int usePrev = IndParam.CheckParam[0].Checked ? 1 : 0;
// Calculate both AVWAPs
double[] fastAVWAP = CalculateAVWAP(fastAnchor, fastShift);
double[] slowAVWAP = CalculateAVWAP(slowAnchor, slowShift);
// Calculate oscillator (difference)
int firstBar = Math.Max(fastShift, slowShift) + usePrev + 2;
double[] oscillator = new double[Bars];
for (int bar = firstBar; bar < Bars; bar++)
{
oscillator[bar] = fastAVWAP[bar] - slowAVWAP[bar];
}
// Set components
Component = new IndicatorComp[4];
// Fast AVWAP line
Component[0] = new IndicatorComp
{
Value = fastAVWAP,
CompName = "Fast AVWAP",
DataType = IndComponentType.IndicatorValue,
ChartType = IndChartType.Line,
ChartColor = Color.Gold,
FirstBar = firstBar
};
// Slow AVWAP line
Component[1] = new IndicatorComp
{
Value = slowAVWAP,
CompName = "Slow AVWAP",
DataType = IndComponentType.IndicatorValue,
ChartType = IndChartType.Line,
ChartColor = Color.DarkBlue,
FirstBar = firstBar
};
// Signal components
Component[2] = new IndicatorComp
{
Value = new double[Bars],
FirstBar = firstBar
};
Component[3] = new IndicatorComp
{
Value = new double[Bars],
FirstBar = firstBar
};
// Set component types based on slot type
if (SlotType == SlotTypes.OpenFilter)
{
Component[2].DataType = IndComponentType.AllowOpenLong;
Component[2].CompName = "Is long entry allowed";
Component[3].DataType = IndComponentType.AllowOpenShort;
Component[3].CompName = "Is short entry allowed";
}
else if (SlotType == SlotTypes.CloseFilter)
{
Component[2].DataType = IndComponentType.ForceCloseLong;
Component[2].CompName = "Close out long position";
Component[3].DataType = IndComponentType.ForceCloseShort;
Component[3].CompName = "Close out short position";
}
// Calculate logic
IndicatorLogic logicRule = IndicatorLogic.It_does_not_act_as_a_filter;
switch (IndParam.ListParam[0].Text)
{
case "Fast AVWAP crosses Slow AVWAP upward":
logicRule = IndicatorLogic.The_indicator_crosses_the_level_line_upward;
break;
case "Fast AVWAP crosses Slow AVWAP downward":
logicRule = IndicatorLogic.The_indicator_crosses_the_level_line_downward;
break;
case "Fast AVWAP is higher than Slow AVWAP":
logicRule = IndicatorLogic.The_indicator_is_higher_than_the_level_line;
break;
case "Fast AVWAP is lower than Slow AVWAP":
logicRule = IndicatorLogic.The_indicator_is_lower_than_the_level_line;
break;
case "Fast AVWAP rises, Slow AVWAP falls":
for (int bar = firstBar + usePrev; bar < Bars; bar++)
{
Component[2].Value[bar] = fastAVWAP[bar-usePrev] > fastAVWAP[bar-usePrev-1] + Sigma() &&
slowAVWAP[bar-usePrev] < slowAVWAP[bar-usePrev-1] - Sigma() ? 1 : 0;
Component[3].Value[bar] = fastAVWAP[bar-usePrev] < fastAVWAP[bar-usePrev-1] - Sigma() &&
slowAVWAP[bar-usePrev] > slowAVWAP[bar-usePrev-1] + Sigma() ? 1 : 0;
}
break;
case "Fast AVWAP falls, Slow AVWAP rises":
for (int bar = firstBar + usePrev; bar < Bars; bar++)
{
Component[2].Value[bar] = fastAVWAP[bar-usePrev] < fastAVWAP[bar-usePrev-1] - Sigma() &&
slowAVWAP[bar-usePrev] > slowAVWAP[bar-usePrev-1] + Sigma() ? 1 : 0;
Component[3].Value[bar] = fastAVWAP[bar-usePrev] > fastAVWAP[bar-usePrev-1] + Sigma() &&
slowAVWAP[bar-usePrev] < slowAVWAP[bar-usePrev-1] - Sigma() ? 1 : 0;
}
break;
case "Fast AVWAP rises, Slow AVWAP rises":
for (int bar = firstBar + usePrev; bar < Bars; bar++)
{
Component[2].Value[bar] = fastAVWAP[bar-usePrev] > fastAVWAP[bar-usePrev-1] + Sigma() &&
slowAVWAP[bar-usePrev] > slowAVWAP[bar-usePrev-1] + Sigma() ? 1 : 0;
Component[3].Value[bar] = fastAVWAP[bar-usePrev] < fastAVWAP[bar-usePrev-1] - Sigma() &&
slowAVWAP[bar-usePrev] < slowAVWAP[bar-usePrev-1] - Sigma() ? 1 : 0;
}
break;
case "Fast AVWAP falls, Slow AVWAP falls":
for (int bar = firstBar + usePrev; bar < Bars; bar++)
{
Component[2].Value[bar] = fastAVWAP[bar-usePrev] < fastAVWAP[bar-usePrev-1] - Sigma() &&
slowAVWAP[bar-usePrev] < slowAVWAP[bar-usePrev-1] - Sigma() ? 1 : 0;
Component[3].Value[bar] = fastAVWAP[bar-usePrev] > fastAVWAP[bar-usePrev-1] + Sigma() &&
slowAVWAP[bar-usePrev] > slowAVWAP[bar-usePrev-1] + Sigma() ? 1 : 0;
}
break;
}
if (logicRule != IndicatorLogic.It_does_not_act_as_a_filter)
{
OscillatorLogic(firstBar, usePrev, oscillator, 0, 0, ref Component[2], ref Component[3], logicRule);
}
}
public override void SetDescription()
{
EntryFilterLongDescription = ToString() + "; Fast AVWAP ";
EntryFilterShortDescription = ToString() + "; Fast AVWAP ";
ExitFilterLongDescription = ToString() + "; Fast AVWAP ";
ExitFilterShortDescription = ToString() + "; Fast AVWAP ";
switch (IndParam.ListParam[0].Text)
{
case "Fast AVWAP crosses Slow AVWAP upward":
EntryFilterLongDescription += "crosses Slow AVWAP upward";
EntryFilterShortDescription += "crosses Slow AVWAP downward";
ExitFilterLongDescription += "crosses Slow AVWAP upward";
ExitFilterShortDescription += "crosses Slow AVWAP downward";
break;
case "Fast AVWAP crosses Slow AVWAP downward":
EntryFilterLongDescription += "crosses Slow AVWAP downward";
EntryFilterShortDescription += "crosses Slow AVWAP upward";
ExitFilterLongDescription += "crosses Slow AVWAP downward";
ExitFilterShortDescription += "crosses Slow AVWAP upward";
break;
case "Fast AVWAP is higher than Slow AVWAP":
EntryFilterLongDescription += "is higher than Slow AVWAP";
EntryFilterShortDescription += "is lower than Slow AVWAP";
ExitFilterLongDescription += "is higher than Slow AVWAP";
ExitFilterShortDescription += "is lower than Slow AVWAP";
break;
case "Fast AVWAP is lower than Slow AVWAP":
EntryFilterLongDescription += "is lower than Slow AVWAP";
EntryFilterShortDescription += "is higher than Slow AVWAP";
ExitFilterLongDescription += "is lower than Slow AVWAP";
ExitFilterShortDescription += "is higher than Slow AVWAP";
break;
case "Fast AVWAP rises, Slow AVWAP falls":
EntryFilterLongDescription += "rises while Slow AVWAP falls";
EntryFilterShortDescription += "falls while Slow AVWAP rises";
ExitFilterLongDescription += "rises while Slow AVWAP falls";
ExitFilterShortDescription += "falls while Slow AVWAP rises";
break;
case "Fast AVWAP falls, Slow AVWAP rises":
EntryFilterLongDescription += "falls while Slow AVWAP rises";
EntryFilterShortDescription += "rises while Slow AVWAP falls";
ExitFilterLongDescription += "falls while Slow AVWAP rises";
ExitFilterShortDescription += "rises while Slow AVWAP falls";
break;
case "Fast AVWAP rises, Slow AVWAP rises":
EntryFilterLongDescription += "and Slow AVWAP are both rising";
EntryFilterShortDescription += "and Slow AVWAP are both falling";
ExitFilterLongDescription += "and Slow AVWAP are both rising";
ExitFilterShortDescription += "and Slow AVWAP are both falling";
break;
case "Fast AVWAP falls, Slow AVWAP falls":
EntryFilterLongDescription += "and Slow AVWAP are both falling";
EntryFilterShortDescription += "and Slow AVWAP are both rising";
ExitFilterLongDescription += "and Slow AVWAP are both falling";
ExitFilterShortDescription += "and Slow AVWAP are both rising";
break;
}
}
public override string ToString()
{
return string.Format("{0}{1} (Fast: {2}, {3} | Slow: {4}, {5})",
IndicatorName,
IndParam.CheckParam[0].Checked ? "*" : "",
IndParam.ListParam[1].Text,
IndParam.NumParam[0].ValueToString,
IndParam.ListParam[2].Text,
IndParam.NumParam[1].ValueToString);
}
}
}
#property copyright "Copyright (C) 2024 Forex Software Ltd." #property link "http://forexsb.com" #property version "1.00" #property strict #include <Forexsb.com/Indicator.mqh> #include <Forexsb.com/Enumerations.mqh> //---------------------------------------------------------------------------------- // Class: AVWAPCrossover // - This version fixes the indexing mismatch by marking all arrays as “series”. // - Any loop that in FSB went from bar=1→Bars–1 is now in MQL from Bars–2→0. // - Shift / previous-bar logic is applied in series coordinates. //---------------------------------------------------------------------------------- class AVWAPCrossover : public Indicator { public: AVWAPCrossover(SlotTypes slotType) { SlotType = slotType; IndicatorName = "AVWAP Crossover"; WarningMessage = ""; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = false; IsDiscreteValues = false; IsDefaultGroupAll= false; } virtual void Calculate(DataSet &dataSet); private: void CalculateAVWAP(int anchorPeriod, int shift, double &avwap[]); datetime GetAnchorTime(datetime currentTime, int anchorPeriod); }; //+------------------------------------------------------------------+ //| Main calculation (MQL “series” indexing) | //+------------------------------------------------------------------+ void AVWAPCrossover::Calculate(DataSet &dataSet) { // Grab FSB DataSet pointer; in MQL we’ll only read Data.Open[], Data.Time[], Data.Volume[], etc. Data = GetPointer(dataSet); // --- 1) Read input parameters exactly as in FSB: int fastAnchorPeriod = ListParam[1].Index; // 0=Daily,1=Weekly,2=Monthly int fastShift = (int)NumParam[0].Value; // number of bars to shift int slowAnchorPeriod = ListParam[2].Index; // 0=Daily,1=Weekly,2=Monthly int slowShift = (int)NumParam[1].Value; int previous = CheckParam[0].Checked ? 1 : 0; // --- 2) Calculate what the “first valid bar” is (still in FSB’s forward‐index sense): int firstBarFSB = MathMax(fastShift, slowShift) + previous + 2; // We'll convert that to a series index in a moment. // --- 3) Build both AVWAP series in FSB‐style (0= oldest, Bars–1= newest): double fastAVWAP[]; CalculateAVWAP(fastAnchorPeriod, fastShift, fastAVWAP); double slowAVWAP[]; CalculateAVWAP(slowAnchorPeriod, slowShift, slowAVWAP); // --- 4) Allocate and mark MQL arrays as “series” so index 0=MOST RECENT bar: ArraySetAsSeries(fastAVWAP, true); ArraySetAsSeries(slowAVWAP, true); // We also need price/volume arrays in series order: ArraySetAsSeries(Data.Open, true); ArraySetAsSeries(Data.High, true); ArraySetAsSeries(Data.Low, true); ArraySetAsSeries(Data.Close, true); ArraySetAsSeries(Data.Volume, true); ArraySetAsSeries(Data.Time, true); // --- 5) Create an oscillator buffer (also in series order): double oscillator[]; ArrayResize(oscillator, Data.Bars); ArraySetAsSeries(oscillator, true); ArrayInitialize(oscillator, 0.0); // We must convert firstBarFSB (FSB’s “forward index”) into a series index: // In FSB: forward index i ↔ MQL series index (si) where si = (Bars–1 – i). int firstBarSeries = (Data.Bars - 1) - firstBarFSB; // Compute oscillator = fastAVWAP – slowAVWAP, bar by bar in series order: // iSeries runs 0 = today, 1 = 1 bar ago, …, up to Bars–1 = oldest. for(int iSeries = 0; iSeries <= firstBarSeries; iSeries++) { // nothing to do for iSeries > firstBarSeries, those older bars remain zero. break; } for(int iSeries = firstBarSeries; iSeries >= 0; iSeries--) { oscillator[iSeries] = fastAVWAP[iSeries] - slowAVWAP[iSeries]; } // --- 6) Populate the indicator’s four components (all in series order): // [0] = Fast AVWAP line, [1] = Slow AVWAP line, [2] = Long‐filter, [3] = Short‐filter ArrayResize(Component[0].Value, Data.Bars); ArraySetAsSeries(Component[0].Value, true); Component[0].CompName = "Fast AVWAP"; Component[0].DataType = IndComponentType_IndicatorValue; Component[0].FirstBar = firstBarSeries; // in series indexing ArrayCopy(Component[0].Value, fastAVWAP); ArrayResize(Component[1].Value, Data.Bars); ArraySetAsSeries(Component[1].Value, true); Component[1].CompName = "Slow AVWAP"; Component[1].DataType = IndComponentType_IndicatorValue; Component[1].FirstBar = firstBarSeries; ArrayCopy(Component[1].Value, slowAVWAP); ArrayResize(Component[2].Value, Data.Bars); ArraySetAsSeries(Component[2].Value, true); Component[2].FirstBar = firstBarSeries; ArrayResize(Component[3].Value, Data.Bars); ArraySetAsSeries(Component[3].Value, true); Component[3].FirstBar = firstBarSeries; // Assign DataType/CompName for the two filter buffers: if(SlotType == SlotTypes_OpenFilter) { Component[2].DataType = IndComponentType_AllowOpenLong; Component[2].CompName = "Is long entry allowed"; Component[3].DataType = IndComponentType_AllowOpenShort; Component[3].CompName = "Is short entry allowed"; } else // CloseFilter { Component[2].DataType = IndComponentType_ForceCloseLong; Component[2].CompName = "Close out long position"; Component[3].DataType = IndComponentType_ForceCloseShort; Component[3].CompName = "Close out short position"; } // --- 7) Now apply the chosen logic. Each “cross/above/below” condition expects // a level line of 0.0 on the oscillator (series indexing). IndicatorLogic indLogic = IndicatorLogic_It_does_not_act_as_a_filter; string logic = ListParam[0].Text; if(logic == "Fast AVWAP crosses Slow AVWAP upward") indLogic = IndicatorLogic_The_indicator_crosses_the_level_line_upward; else if(logic == "Fast AVWAP crosses Slow AVWAP downward") indLogic = IndicatorLogic_The_indicator_crosses_the_level_line_downward; else if(logic == "Fast AVWAP is higher than Slow AVWAP") indLogic = IndicatorLogic_The_indicator_is_higher_than_the_level_line; else if(logic == "Fast AVWAP is lower than Slow AVWAP") indLogic = IndicatorLogic_The_indicator_is_lower_than_the_level_line; else if(logic == "Fast AVWAP rises, Slow AVWAP falls") { // Since everything is already in series order, “bar–1” means “one older bar”: for(int iSeries = firstBarSeries - previous; iSeries >= 1; iSeries--) { bool fastRises = fastAVWAP[iSeries - previous] > fastAVWAP[iSeries - previous - 1] + Sigma(); bool slowFalls = slowAVWAP[iSeries - previous] < slowAVWAP[iSeries - previous - 1] - Sigma(); Component[2].Value[iSeries] = (fastRises && slowFalls) ? 1.0 : 0.0; bool fastFalls = fastAVWAP[iSeries - previous] < fastAVWAP[iSeries - previous - 1] - Sigma(); bool slowRises = slowAVWAP[iSeries - previous] > slowAVWAP[iSeries - previous - 1] + Sigma(); Component[3].Value[iSeries] = (fastFalls && slowRises) ? 1.0 : 0.0; } } else if(logic == "Fast AVWAP falls, Slow AVWAP rises") { for(int iSeries = firstBarSeries - previous; iSeries >= 1; iSeries--) { bool fastFalls = fastAVWAP[iSeries - previous] < fastAVWAP[iSeries - previous - 1] - Sigma(); bool slowRises = slowAVWAP[iSeries - previous] > slowAVWAP[iSeries - previous - 1] + Sigma(); Component[2].Value[iSeries] = (fastFalls && slowRises) ? 1.0 : 0.0; bool fastRises = fastAVWAP[iSeries - previous] > fastAVWAP[iSeries - previous - 1] + Sigma(); bool slowFalls = slowAVWAP[iSeries - previous] < slowAVWAP[iSeries - previous - 1] - Sigma(); Component[3].Value[iSeries] = (fastRises && slowFalls) ? 1.0 : 0.0; } } else if(logic == "Fast AVWAP rises, Slow AVWAP rises") { for(int iSeries = firstBarSeries - previous; iSeries >= 1; iSeries--) { bool fastRises = fastAVWAP[iSeries - previous] > fastAVWAP[iSeries - previous - 1] + Sigma(); bool slowRises = slowAVWAP[iSeries - previous] > slowAVWAP[iSeries - previous - 1] + Sigma(); Component[2].Value[iSeries] = (fastRises && slowRises) ? 1.0 : 0.0; bool fastFalls = fastAVWAP[iSeries - previous] < fastAVWAP[iSeries - previous - 1] - Sigma(); bool slowFalls = slowAVWAP[iSeries - previous] < slowAVWAP[iSeries - previous - 1] - Sigma(); Component[3].Value[iSeries] = (fastFalls && slowFalls) ? 1.0 : 0.0; } } else if(logic == "Fast AVWAP falls, Slow AVWAP falls") { for(int iSeries = firstBarSeries - previous; iSeries >= 1; iSeries--) { bool fastFalls = fastAVWAP[iSeries - previous] < fastAVWAP[iSeries - previous - 1] - Sigma(); bool slowFalls = slowAVWAP[iSeries - previous] < slowAVWAP[iSeries - previous - 1] - Sigma(); Component[2].Value[iSeries] = (fastFalls && slowFalls) ? 1.0 : 0.0; bool fastRises = fastAVWAP[iSeries - previous] > fastAVWAP[iSeries - previous - 1] + Sigma(); bool slowRises = slowAVWAP[iSeries - previous] > slowAVWAP[iSeries - previous - 1] + Sigma(); Component[3].Value[iSeries] = (fastRises && slowRises) ? 1.0 : 0.0; } } // --- 8) If the selected logic was one of the first four (“crosses” / “higher” / “lower”), apply OscillatorLogic: if(indLogic != IndicatorLogic_It_does_not_act_as_a_filter) { OscillatorLogic( firstBarSeries, // series‐indexed first bar previous, // use previous bar value oscillator, // oscillator is already in series order 0.0, // level‐line = zero (series) 0.0, // unused Component[2], // long‐filter buffer (series) Component[3], // short‐filter buffer (series) indLogic ); } } //+------------------------------------------------------------------+ //| Calculate a single AVWAP buffer, in FSB “forward” indexing. | //| After computing, we flip to series order at caller. | //+------------------------------------------------------------------+ void AVWAPCrossover::CalculateAVWAP(int anchorPeriod, int shift, double &avwap[]) { int totalBars = Data.Bars; ArrayResize(avwap, totalBars); ArrayInitialize(avwap, 0.0); double cumPV = 0.0; double cumVol = 0.0; datetime currentAnchor = 0; // FSB “forward” loop: 0=oldest, Bars–1=newest for(int bar = 1; bar < totalBars; bar++) { datetime barTime = Data.Time[bar]; datetime anchorTime = GetAnchorTime(barTime, anchorPeriod); if(anchorTime != currentAnchor) { cumPV = 0.0; cumVol = 0.0; currentAnchor = anchorTime; } double typicalPrice = (Data.Open[bar] + Data.High[bar] + Data.Low[bar] + Data.Close[bar]) / 4.0; double volume = (double)Data.Volume[bar]; cumPV += typicalPrice * volume; cumVol += volume; avwap[bar] = (cumVol > 0.0) ? (cumPV / cumVol) : 0.0; } // Apply the FSB‐style “shift” in forward indexing, // then at caller we’ll flip the entire array to series. double temp[]; ArrayResize(temp, totalBars); ArrayCopy(temp, avwap); for(int bar = 0; bar < totalBars; bar++) { int src = bar - shift; if(src >= 0 && src < totalBars) avwap[bar] = temp[src]; else avwap[bar] = 0.0; } } //+------------------------------------------------------------------+ //| Get the anchor‐start time (daily, weekly, or monthly) in forward | //| indexing. Returns a datetime that changes whenever a new period | //| begins (FSB style). | //+------------------------------------------------------------------+ datetime AVWAPCrossover::GetAnchorTime(datetime currentTime, int anchorPeriod) { MqlDateTime dt; TimeToStruct(currentTime, dt); switch(anchorPeriod) { case 0: // Daily dt.hour = 0; dt.min = 0; dt.sec = 0; break; case 1: // Weekly (Monday) while(dt.day_of_week != 1) // Monday == 1 { currentTime -= 86400; // subtract one day TimeToStruct(currentTime, dt); } dt.hour = 0; dt.min = 0; dt.sec = 0; break; case 2: // Monthly dt.day = 1; dt.hour = 0; dt.min = 0; dt.sec = 0; break; } return StructToTime(dt); }
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.;