> For the complete documentation index, see [llms.txt](https://support.tiger.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://support.tiger.com/razrabotka-dlya-tiger.trade-windows/primery-indikatorov/vwap.md).

# VWAP

```
//------------------------------------------------------------------------------
//
// Индикатор VWAP. Copyright (c) 2023 Tiger Trade Capital AG. All rights reserved.
//
//------------------------------------------------------------------------------
 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;
using System.Windows.Media;
using TigerTrade.Chart.Base;
using TigerTrade.Chart.Base.Enums;
using TigerTrade.Chart.Indicators.Common;
using TigerTrade.Chart.Indicators.Drawings;
using TigerTrade.Chart.Indicators.Drawings.Enums;
using TigerTrade.Chart.Indicators.Enums;
using TigerTrade.Core.Utils.Time;
 
namespace TigerTrade.Chart.Indicators.Custom
{
    [DataContract(Name = "VWAPIndicator", Namespace = "http://schemas.datacontract.org/2004/07/TigerTrade.Chart.Indicators.Custom")]
    [Indicator("X_VWAP", "*VWAP", true, Type = typeof(VWAPIndicator))]
    internal sealed class VWAPIndicator : IndicatorBase
    {
        private IndicatorPeriodType _period;
 
        [DataMember(Name = "Period")]
        [Category("Параметры"), DisplayName("Период")]
        public IndicatorPeriodType Period
        {
            get => _period;
            set
            {
                if (value == _period)
                {
                    return;
                }
 
                _period = value;
 
                StdDevCache.Clear();
 
                OnPropertyChanged();
            }
        }
 
        private TimeSpan? _startTime;
 
        [DataMember(Name = "StartTime")]
        [Category("Параметры"), DisplayName("Время")]
        public TimeSpan? StartTime
        {
            get => _startTime;
            set
            {
                if (value.Equals(_startTime))
                {
                    return;
                }
 
                _startTime = value;
 
                StdDevCache.Clear();
 
                OnPropertyChanged();
            }
        }
 
        private IndicatorPriceType _priceType;
 
        [DataMember(Name = "PriceType")]
        [Category("Параметры"), DisplayName("Цена")]
        public IndicatorPriceType PriceType
        {
            get => _priceType;
            set
            {
                if (value == _priceType)
                {
                    return;
                }
 
                _priceType = value;
 
                StdDevCache.Clear();
 
                OnPropertyChanged();
            }
        }
 
        private List<decimal> _stdDevs;
 
        [DataMember(Name = "StdDevs")]
        [Category("Параметры"), DisplayName("StdDevs")]
        public List<decimal> StdDevs
        {
            get => _stdDevs ?? (StdDevs = new List<decimal>());
            set
            {
                if (Equals(value, _stdDevs))
                {
                    return;
                }
 
                _stdDevs = value;
             
                OnPropertyChanged();
            }
        }
 
        private ChartSeries _vwapSeries;
 
        [DataMember(Name = "VWAP")]
        [Category("ChartIndicatorsCharts"), DisplayName("VWAP")]
        public ChartSeries VWAPSeries
        {
            get => _vwapSeries ?? (_vwapSeries = new ChartSeries(ChartSeriesType.Line, Colors.Blue));
            private set
            {
                if (Equals(value, _vwapSeries))
                {
                    return;
                }
 
                _vwapSeries = value;
 
                OnPropertyChanged();
            }
        }
 
        private ChartSeries _stdDevSeries;
     
        [DataMember(Name = "StdDev")]
        [Category("ChartIndicatorsCharts"), DisplayName("StdDev")]
        public ChartSeries StdDevSeries
        {
            get => _stdDevSeries ?? (_stdDevSeries = new ChartSeries(ChartSeriesType.Line, Colors.Red));
            private set
            {
                if (Equals(value, _stdDevSeries))
                {
                    return;
                }
 
                _stdDevSeries = value;
 
                OnPropertyChanged();
            }
        }
 
        public VWAPIndicator()
        {
            Period = IndicatorPeriodType.Day;
 
            StartTime = null;
 
            PriceType = IndicatorPriceType.Median;
 
            StdDevs.Add(1);
            StdDevs.Add(2);
        }
 
        private List<double> _stdDevCache;
     
        private List<double> StdDevCache => _stdDevCache ?? (_stdDevCache = new List<double>(1000));
 
        protected override void Execute()
        {
            var date = Helper.Date;
            var price = Helper.Price(_priceType);
            var vol = Helper.Volume;
 
            var vwap = new double[date.Length];
            var stdDev = new double[date.Length];
            var splits = new bool[date.Length];
 
            var calcStdDevs = StdDevs.Count > 0;
 
            if (date.Length < StdDevCache.Count)
            {
                StdDevCache.Clear();
            }
 
            var lastSequence = -1;
 
            var cumVolumePrice = 0.0;
            var cumVolume = 0.0;
 
            var newDayIndex = 0;
 
            double timeOffset;
 
            if (StartTime.HasValue)
            {
                var oaBaseDate = DateTime.FromOADate(0);
 
                timeOffset = -oaBaseDate.Add(StartTime.Value).ToOADate();
            }
            else
            {
                timeOffset = TimeHelper.GetSessionOffset(DataProvider.Symbol.Exchange);
            }
 
            for (var i = 0; i < date.Length; i++)
            {
                var sequence = -1;
 
                switch (Period)
                {
                    case IndicatorPeriodType.Day:
 
                        sequence = DataProvider.Period.GetSequence(ChartPeriodType.Day, 1, date[i], timeOffset);
 
                        break;
 
                    case IndicatorPeriodType.Week:
 
                        sequence = DataProvider.Period.GetSequence(ChartPeriodType.Week, 1, date[i], timeOffset);
 
                        break;
 
                    case IndicatorPeriodType.Month:
 
                        sequence = DataProvider.Period.GetSequence(ChartPeriodType.Month, 1, date[i], timeOffset);
 
                        break;
                }
 
                if (sequence != lastSequence)
                {
                    lastSequence = sequence;
 
                    newDayIndex = i;
 
                    cumVolumePrice = 0.0;
                    cumVolume = 0.0;
 
                    splits[i] = true;
                }
 
                cumVolumePrice += price[i] * vol[i];
                cumVolume += vol[i];
 
                if (cumVolume == 0)
                {
                    continue;
                }
 
                vwap[i] = cumVolumePrice / cumVolume;
 
                if (calcStdDevs)
                {
                    if (i < StdDevCache.Count)
                    {
                        stdDev[i] = StdDevCache[i];
                    }
                    else
                    {
                        var variance = 0.0;
 
                        for (var j = newDayIndex; j < i; j++)
                        {
                            variance += (vol[j]/cumVolume)*(price[j] - vwap[i])*(price[j] - vwap[i]);
                        }
 
                        stdDev[i] = Math.Sqrt(variance);
 
                        StdDevCache.Add(stdDev[i]);
                    }
                }
            }
 
            var vwapSeries = new IndicatorSeriesData(vwap, VWAPSeries)
            {
                Style =
                {
                    DisableMinMax = true
                }
            };
 
            Series.Add(vwapSeries);
 
            if (calcStdDevs)
            {
                foreach (var dev in StdDevs)
                {
                    if (dev <= 0)
                    {
                        continue;
                    }
 
                    var stdDevPos = new double[date.Length];
                    var stdDevNeg = new double[date.Length];
 
                    var d = (double) dev;
 
                    for (var i = 0; i < date.Length; i++)
                    {
                        stdDevPos[i] = vwap[i] + stdDev[i] * d;
                        stdDevNeg[i] = vwap[i] - stdDev[i] * d;
                    }
 
                    var stdDevPosSeries = new IndicatorSeriesData(stdDevPos, StdDevSeries)
                    {
                        Style = {DisableMinMax = true}
                    };
 
                    var stdDevNegSeries = new IndicatorSeriesData(stdDevNeg, StdDevSeries)
                    {
                        Style = {DisableMinMax = true}
                    };
 
                    Series.Add(stdDevPosSeries, stdDevNegSeries);
                }
            }
 
            foreach (var series in Series)
            {
                series.UserData["S"] = splits;
                series.UserData["SE"] = false;
            }
        }
 
        public override void ApplyColors(IChartTheme theme)
        {
            VWAPSeries.AllColors = theme.GetNextColor();
            StdDevSeries.AllColors = theme.GetNextColor();
 
            base.ApplyColors(theme);
        }
 
        public override void CopyTemplate(IndicatorBase indicator, bool style)
        {
            var i = (VWAPIndicator)indicator;
 
                       Period = i.Period;
            PriceType = i.PriceType;
 
            StdDevs = i.StdDevs.ToList();
 
            VWAPSeries.CopyTheme(i.VWAPSeries);
            StdDevSeries.CopyTheme(i.StdDevSeries);
 
            base.CopyTemplate(indicator, style);
        }
    }
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://support.tiger.com/razrabotka-dlya-tiger.trade-windows/primery-indikatorov/vwap.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
