AVWAP (Anchored Volume Weighted Average Price) by Naya

95 downloads / 66 views / Created: 06.06.2025
 Average Rating: 0

Indicator Description

AVWAP (Anchored Volume Weighted Average Price) is a custom indicator for Forex Strategy Builder that calculates the volume-weighted average price from a defined anchor point (Daily, Weekly, or Monthly). It helps traders identify fair value zones based on volume concentration. AVWAP can be used to enter or exit trades or as a filter to confirm price direction, trend strength, or breakout conditions. The indicator supports logic for rising/falling trends, bar open/close positions relative to AVWAP, and customizable signal timing with shift and previous bar options.

Comments

//============================================================== // Forex Strategy Builder // Copyright (c) Miroslav Popov. All rights reserved. //============================================================== // THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, // EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE. //============================================================== using System; using System.Drawing; using ForexStrategyBuilder.Infrastructure.Entities; using ForexStrategyBuilder.Infrastructure.Enums; using ForexStrategyBuilder.Infrastructure.Interfaces; namespace ForexStrategyBuilder.Indicators.Store { public class AVWAP : Indicator { public AVWAP() { IndicatorName = "AVWAP"; PossibleSlots = SlotTypes.Open | SlotTypes.OpenFilter | SlotTypes.Close | SlotTypes.CloseFilter; IndicatorAuthor = "NAYA +237674724684"; IndicatorVersion = "1.0"; IndicatorDescription = "Anchored Volume Weighted Average Price"; } 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 AVWAP" }; break; case SlotTypes.OpenFilter: IndParam.ListParam[0].ItemList = new[] { "The AVWAP rises", "The AVWAP falls", "The bar opens above the AVWAP", "The bar opens below the AVWAP", "The bar opens above the AVWAP after opening below it", "The bar opens below the AVWAP after opening above it", "The position opens above the AVWAP", "The position opens below the AVWAP", }; break; case SlotTypes.Close: IndParam.ListParam[0].ItemList = new[] { "Exit the market at the AVWAP" }; break; case SlotTypes.CloseFilter: IndParam.ListParam[0].ItemList = new[] { "The AVWAP rises", "The AVWAP falls", "The bar closes below the AVWAP", "The bar closes above the AVWAP", }; 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 AVWAP."; // --- Anchor period selection IndParam.ListParam[1].Caption = "Anchor Period"; IndParam.ListParam[1].ItemList = new[] { "Daily", "Weekly", "Monthly" }; IndParam.ListParam[1].Index = 0; IndParam.ListParam[1].Text = "Daily"; IndParam.ListParam[1].Enabled = true; IndParam.ListParam[1].ToolTip = "Anchor period for AVWAP calculation."; // --- Shift parameter (now in bars) IndParam.NumParam[0].Caption = "Shift (bars)"; IndParam.NumParam[0].Value = 0; IndParam.NumParam[0].Min = 0; IndParam.NumParam[0].Max = 2; IndParam.NumParam[0].Enabled = true; IndParam.NumParam[0].ToolTip = "Number of bars to shift the AVWAP."; // --- Use previous bar? 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 AVWAP value."; return; } public override void Calculate(IDataSet dataSet) { DataSet = dataSet; int anchorType = IndParam.ListParam[1].Index + 1; // 1=Daily,2=Weekly,3=Monthly int shift = (int)IndParam.NumParam[0].Value; int usePrev = IndParam.CheckParam[0].Checked ? 1 : 0; int firstBar = 3; int bars = Bars; double[] avwapBuffer = new double[bars]; // Cumulative PV and V double cumPV = 0; double cumV = 0; DateTime currentAnchorDate = DateTime.MinValue; // Main loop for (int iBar = firstBar; iBar < bars; iBar++) { DateTime barTime = Time[iBar]; DateTime anchorStart = GetAnchorStartTime(barTime, anchorType); // New anchor period? if (anchorStart != currentAnchorDate) { cumPV = 0; cumV = 0; currentAnchorDate = anchorStart; } // Typical price = (O+H+L+C)/4 double typicalPrice = (Open[iBar] + High[iBar] + Low[iBar] + Close[iBar]) / 4.0; double volume = Volume[iBar]; // Update cumulatives cumPV += typicalPrice * volume; cumV += volume; // Compute AVWAP avwapBuffer[iBar] = (cumV > 0) ? (cumPV / cumV) : 0.0; } // Apply shift double[] shiftedAVWAP = new double[bars]; for (int bar = 0; bar < bars; bar++) { int sourceBar = bar - shift; if (sourceBar >= 0 && sourceBar < bars) shiftedAVWAP[bar] = avwapBuffer[sourceBar]; else if (bar >= shift) shiftedAVWAP[bar] = avwapBuffer[bar - shift]; } // Build components if (SlotType == SlotTypes.Open || SlotType == SlotTypes.Close) { Component = new IndicatorComp[2]; Component[1] = new IndicatorComp { Value = new double[bars] }; // Entry/Exit price logic for (int iBar = firstBar + shift; iBar < bars; iBar++) { // current and previous AVWAP (with shift and optional prev-bar offset) double v0 = shiftedAVWAP[iBar - usePrev]; double v1 = shiftedAVWAP[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 { Component = new IndicatorComp[3]; // No-chart filter buffers 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 AVWAP line Component[0] = new IndicatorComp { CompName = "AVWAP Value", DataType = IndComponentType.IndicatorValue, ChartType = IndChartType.Line, ChartColor= Color.DodgerBlue, FirstBar = firstBar + shift, Value = shiftedAVWAP }; // Assign names and types switch (SlotType) { case SlotTypes.Open: Component[1].CompName = "Position opening price"; Component[1].DataType = IndComponentType.OpenPrice; break; case SlotTypes.OpenFilter: Component[1].CompName = "Is long entry allowed"; Component[1].DataType = IndComponentType.AllowOpenLong; Component[2].CompName = "Is short entry allowed"; Component[2].DataType = IndComponentType.AllowOpenShort; break; case SlotTypes.Close: Component[1].CompName = "Position closing price"; Component[1].DataType = IndComponentType.ClosePrice; break; case SlotTypes.CloseFilter: Component[1].CompName = "Close out long position"; Component[1].DataType = IndComponentType.ForceCloseLong; Component[2].CompName = "Close out short position"; Component[2].DataType = IndComponentType.ForceCloseShort; break; } // Apply filter logic if needed if (SlotType == SlotTypes.OpenFilter || SlotType == SlotTypes.CloseFilter) { switch (IndParam.ListParam[0].Text) { case "The AVWAP rises": IndicatorRisesLogic(firstBar + shift, usePrev, shiftedAVWAP, ref Component[1], ref Component[2]); break; case "The AVWAP falls": IndicatorFallsLogic(firstBar + shift, usePrev, shiftedAVWAP, ref Component[1], ref Component[2]); break; case "The bar opens above the AVWAP": BarOpensAboveIndicatorLogic(firstBar + shift, usePrev, shiftedAVWAP, ref Component[1], ref Component[2]); break; case "The bar opens below the AVWAP": BarOpensBelowIndicatorLogic(firstBar + shift, usePrev, shiftedAVWAP, ref Component[1], ref Component[2]); break; case "The bar opens above the AVWAP after opening below it": BarOpensAboveIndicatorAfterOpeningBelowLogic(firstBar + shift, usePrev, shiftedAVWAP, ref Component[1], ref Component[2]); break; case "The bar opens below the AVWAP after opening above it": BarOpensBelowIndicatorAfterOpeningAboveLogic(firstBar + shift, usePrev, shiftedAVWAP, ref Component[1], ref Component[2]); break; case "The position opens above the AVWAP": Component[0].PosPriceDependence = PositionPriceDependence.BuyHigherSellLower; Component[0].UsePreviousBar = usePrev; Component[1].ShowInDynInfo = false; Component[2].ShowInDynInfo = false; break; case "The position opens below the AVWAP": Component[0].PosPriceDependence = PositionPriceDependence.BuyLowerSellHigher; Component[0].UsePreviousBar = usePrev; Component[1].ShowInDynInfo = false; Component[2].ShowInDynInfo = false; break; case "The bar closes below the AVWAP": BarClosesBelowIndicatorLogic(firstBar + shift, usePrev, shiftedAVWAP, ref Component[1], ref Component[2]); break; case "The bar closes above the AVWAP": BarClosesAboveIndicatorLogic(firstBar + shift, usePrev, shiftedAVWAP, ref Component[1], ref Component[2]); break; } } } private DateTime GetAnchorStartTime(DateTime currentTime, int anchorType) { 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; } } 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 AVWAP rises": EntryFilterLongDescription = "the " + ToString() + " rises"; EntryFilterShortDescription = "the " + ToString() + " falls"; ExitFilterLongDescription = "the " + ToString() + " rises"; ExitFilterShortDescription = "the " + ToString() + " falls"; break; case "The AVWAP falls": EntryFilterLongDescription = "the " + ToString() + " falls"; EntryFilterShortDescription = "the " + ToString() + " rises"; ExitFilterLongDescription = "the " + ToString() + " falls"; ExitFilterShortDescription = "the " + ToString() + " rises"; break; case "The bar opens above the AVWAP": EntryFilterLongDescription = "the bar opens above the " + ToString(); EntryFilterShortDescription = "the bar opens below the " + ToString(); break; case "The bar opens below the AVWAP": EntryFilterLongDescription = "the bar opens below the " + ToString(); EntryFilterShortDescription = "the bar opens above the " + ToString(); break; case "The position opens above the AVWAP": 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 AVWAP": 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 AVWAP": ExitFilterLongDescription = "the bar closes above the " + ToString(); ExitFilterShortDescription = "the bar closes below the " + ToString(); break; case "The bar closes below the AVWAP": ExitFilterLongDescription = "the bar closes below the " + ToString(); ExitFilterShortDescription = "the bar closes above the " + ToString(); break; } } public override string ToString() { return IndicatorName + (IndParam.CheckParam[0].Checked ? "* (" : " (") + IndParam.ListParam[1].Text + ", " + IndParam.NumParam[0].ValueToString + ")"; } } }
//+--------------------------------------------------------------------+ //| Copyright: (C) 2024, Indicator Author | //| Website: http://example.com | //| Support: http://example.com/forum/ | //| License: Proprietary under the following circumstances: | //| | //| This code is a part of Forex Strategy Builder. It is free for | //| use as an integral part of Forex Strategy Builder. | //| One can modify it in order to improve the code or to fit it for | //| personal use. This code or any part of it cannot be used in | //| other applications without a permission. | //| | //| NO LIABILITY FOR CONSEQUENTIAL DAMAGES | //| | //| In no event shall the author be liable for any damages whatsoever | //| (including, without limitation, incidental, direct, indirect and | //| consequential damages, damages for loss of business profits, | //| business interruption, loss of business information, or other | //| pecuniary loss) arising out of the use or inability to use this | //| product, even if advised of the possibility of such damages. | //+--------------------------------------------------------------------+ #property copyright "Copyright (C) 2024, Indicator Author" #property link "http://example.com" #property version "1.00" #property strict #include <Forexsb.com/Indicator.mqh> #include <Forexsb.com/Enumerations.mqh> //+------------------------------------------------------------------+ //| AVWAP: Anchored VWAP indicator | //+------------------------------------------------------------------+ class AVWAP : public Indicator { public: //--- constructor: set up slot type, names, defaults AVWAP(SlotTypes slotType) { SlotType = slotType; IndicatorName = "AVWAP"; WarningMessage = ""; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = false; IsDiscreteValues = false; IsDeafultGroupAll= false; } virtual void Calculate(DataSet &dataSet); private: datetime GetAnchorStartTime(datetime currentTime, int anchorType); }; //+------------------------------------------------------------------+ //| Calculate() each tick/bar | //+------------------------------------------------------------------+ void AVWAP::Calculate(DataSet &dataSet) { Data = GetPointer(dataSet); // --- read user parameters int anchorPeriod = ListParam[1].Index + 1; // 1=Daily,2=Weekly,3=Monthly int shift = (int)NumParam[0].Value; // Shift in bars int prvs = CheckParam[0].Checked ? 1 : 0; const int firstBar = 3; // --- prepare AVWAP buffer double cumPV = 0.0, cumV = 0.0; datetime currentAnchorTime = 0; double avwapBuffer[]; ArrayResize(avwapBuffer, Data.Bars); double shiftedAVWAP[]; ArrayResize(shiftedAVWAP, Data.Bars); // --- main loop for(int iBar = firstBar; iBar < Data.Bars; iBar++) { // find anchor start datetime barTime = Data.Time[iBar]; datetime anchorStart = GetAnchorStartTime(barTime, anchorPeriod); if(anchorStart != currentAnchorTime) { cumPV = 0.0; cumV = 0.0; currentAnchorTime= anchorStart; } // typical price = (O+H+L+C)/4 double typicalPrice = (Data.Open[iBar] + Data.High[iBar] + Data.Low[iBar] + Data.Close[iBar]) / 4.0; double volume = (double)Volume[iBar]; cumPV += typicalPrice * volume; cumV += volume; avwapBuffer[iBar] = (cumV > 0.0) ? (cumPV / cumV) : 0.0; } // Apply shift for(int bar = 0; bar < Data.Bars; bar++) { int sourceBar = bar - shift; if(sourceBar >= 0 && sourceBar < Data.Bars) shiftedAVWAP[bar] = avwapBuffer[sourceBar]; else if(bar >= shift) shiftedAVWAP[bar] = avwapBuffer[bar - shift]; } // --- now copy into FSB Pro components if(SlotType == SlotTypes_Open || SlotType == SlotTypes_Close) { ArrayResize(Component[1].Value, Data.Bars); for(int bar = firstBar + shift; bar < Data.Bars; bar++) { double v0 = shiftedAVWAP[bar - prvs]; double v1 = shiftedAVWAP[bar - prvs - 1]; double tempVal = v0; if((v1 > Data.High[bar-1] && v0 < Data.Open[bar]) || (v1 < Data.Low[bar-1] && v0 > Data.Open[bar]) || (Data.Close[bar-1] < v0 && v0 < Data.Open[bar]) || (Data.Close[bar-1] > v0 && v0 > Data.Open[bar])) tempVal = Data.Open[bar]; Component[1].Value[bar] = tempVal; } } else { ArrayResize(Component[1].Value, Data.Bars); Component[1].FirstBar = firstBar + shift; ArrayResize(Component[2].Value, Data.Bars); Component[2].FirstBar = firstBar + shift; } ArrayResize(Component[0].Value, Data.Bars); Component[0].CompName = "AVWAP Value"; Component[0].DataType = IndComponentType_IndicatorValue; Component[0].FirstBar = firstBar + shift; ArrayCopy(Component[0].Value, shiftedAVWAP); // Sets Component's type if(SlotType == SlotTypes_Open) { Component[1].DataType = IndComponentType_OpenLongPrice; Component[1].CompName = "Long position entry price"; Component[2].DataType = IndComponentType_OpenShortPrice; Component[2].CompName = "Short position entry price"; } else if(SlotType == SlotTypes_Close) { Component[1].DataType = IndComponentType_CloseLongPrice; Component[1].CompName = "Long position closing price"; Component[2].DataType = IndComponentType_CloseShortPrice; Component[2].CompName = "Short position closing price"; } else if(SlotType == SlotTypes_OpenFilter) { Component[1].DataType = IndComponentType_AllowOpenLong; Component[1].CompName = "Is long entry allowed"; Component[2].DataType = IndComponentType_AllowOpenShort; Component[2].CompName = "Is short entry allowed"; } else if(SlotType == SlotTypes_CloseFilter) { Component[1].DataType = IndComponentType_ForceCloseLong; Component[1].CompName = "Close out long position"; Component[2].DataType = IndComponentType_ForceCloseShort; Component[2].CompName = "Close out short position"; } // Calculation of the logic if(SlotType == SlotTypes_OpenFilter || SlotType == SlotTypes_CloseFilter) { if(ListParam[0].Text=="The AVWAP rises") IndicatorRisesLogic(firstBar+shift,prvs,shiftedAVWAP,Component[1],Component[2]); else if(ListParam[0].Text=="The AVWAP falls") IndicatorFallsLogic(firstBar+shift,prvs,shiftedAVWAP,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens above the AVWAP") BarOpensAboveIndicatorLogic(firstBar+shift,prvs,shiftedAVWAP,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens below the AVWAP") BarOpensBelowIndicatorLogic(firstBar+shift,prvs,shiftedAVWAP,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens above the AVWAP after opening below it") BarOpensAboveIndicatorAfterOpeningBelowLogic(firstBar+shift,prvs,shiftedAVWAP,Component[1],Component[2]); else if(ListParam[0].Text=="The bar opens below the AVWAP after opening above it") BarOpensBelowIndicatorAfterOpeningAboveLogic(firstBar+shift,prvs,shiftedAVWAP,Component[1],Component[2]); else if(ListParam[0].Text=="The position opens above the AVWAP") { Component[0].PosPriceDependence=PositionPriceDependence_BuyHigherSellLower; Component[0].UsePreviousBar=prvs; Component[1].ShowInDynInfo=false; Component[2].ShowInDynInfo=false; } else if(ListParam[0].Text=="The position opens below the AVWAP") { Component[0].PosPriceDependence=PositionPriceDependence_BuyLowerSellHigher; Component[0].UsePreviousBar=prvs; Component[1].ShowInDynInfo=false; Component[2].ShowInDynInfo=false; } else if(ListParam[0].Text=="The bar closes below the AVWAP") BarClosesBelowIndicatorLogic(firstBar+shift,prvs,shiftedAVWAP,Component[1],Component[2]); else if(ListParam[0].Text=="The bar closes above the AVWAP") BarClosesAboveIndicatorLogic(firstBar+shift,prvs,shiftedAVWAP,Component[1],Component[2]); } } //+------------------------------------------------------------------+ //| Compute start of anchor period | //+------------------------------------------------------------------+ datetime AVWAP::GetAnchorStartTime(datetime currentTime, int anchorType) { 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; } return StructToTime(s); } //+------------------------------------------------------------------+
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.;