AVWAP Crossover by Naya
609 downloads / 365 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
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);
}
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302#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.;