-
Notifications
You must be signed in to change notification settings - Fork 2
/
IntradayVwap.cs
92 lines (81 loc) · 3.18 KB
/
IntradayVwap.cs
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
using System;
using QuantConnect.Data;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators
{
/// <summary>
/// Defines the canonical intraday VWAP indicator
/// </summary>
public class IntradayVwap : IndicatorBase<QuantConnect.Data.BaseData>
{
private DateTime _lastDate;
private decimal _sumOfVolume;
private decimal _sumOfPriceTimesVolume;
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady => _sumOfVolume > 0;
/// <summary>
/// Initializes a new instance of the <see cref="IntradayVwap"/> class
/// </summary>
/// <param name="name">The name of the indicator</param>
public IntradayVwap(string name)
: base(name)
{
}
/// <summary>
/// Computes the new VWAP
/// </summary>
protected override IndicatorResult ValidateAndComputeNextValue(QuantConnect.Data.BaseData input)
{
decimal volume, averagePrice;
if (!TryGetVolumeAndAveragePrice(input, out volume, out averagePrice))
{
return new IndicatorResult(0, IndicatorStatus.InvalidInput);
}
// reset vwap on daily boundaries
if (_lastDate != input.EndTime.Date)
{
_sumOfVolume = 0m;
_sumOfPriceTimesVolume = 0m;
_lastDate = input.EndTime.Date;
}
// running totals for Σ PiVi / Σ Vi
_sumOfVolume += volume;
_sumOfPriceTimesVolume += averagePrice * volume;
if (_sumOfVolume == 0m)
{
// if we have no trade volume then use the current price as VWAP
return input.Value;
}
return _sumOfPriceTimesVolume / _sumOfVolume;
}
/// <summary>
/// Computes the next value of this indicator from the given state.
/// NOTE: This must be overriden since it's abstract in the base, but
/// will never be invoked since we've override the validate method above.
/// </summary>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(QuantConnect.Data.BaseData input)
{
throw new NotImplementedException($"{nameof(IntradayVwap)}.{nameof(ComputeNextValue)} should never be invoked.");
}
/// <summary>
/// Determines the volume and price to be used for the current input in the VWAP computation
/// </summary>
protected bool TryGetVolumeAndAveragePrice(QuantConnect.Data.BaseData input, out decimal volume, out decimal averagePrice)
{
var tradeBar = input as TradeBar;
if (tradeBar?.IsFillForward == false)
{
volume = tradeBar.Volume;
averagePrice = (tradeBar.High + tradeBar.Low + tradeBar.Close) / 3m;
return true;
}
volume = 0;
averagePrice = 0;
return false;
}
}
}