Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions Indicators/RelativeDailyVolume.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace QuantConnect.Indicators
///
/// Current volume from open to current time of day / Average over the past x days from open to current time of day
/// </summary>
public class RelativeDailyVolume : TradeBarIndicator
public class RelativeDailyVolume : TradeBarIndicator, IIndicatorWarmUpPeriodProvider
{
private readonly SortedDictionary<TimeSpan, SimpleMovingAverage> _relativeData;
private readonly Dictionary<DateTime, decimal> _currentData;
Expand All @@ -39,6 +39,18 @@ public class RelativeDailyVolume : TradeBarIndicator
/// </summary>
public override bool IsReady => _days >= _period;

/// <summary>
/// Required period, in data points, for the indicator to be ready and fully initialized.
/// </summary>
/// <remarks>
/// This indicator is ready once it has seen <c>period</c> complete days of data, so the number of data points
/// it needs depends on the resolution it is updated with and on the market hours of the security, and it cannot
/// be derived from the period alone. It defaults to zero, which means no warm up is performed. Set it to the
/// number of bars, at the resolution the indicator is updated with, that span the required number of days to
/// have <c>WarmUpIndicator</c> warm it up.
/// </remarks>
public int WarmUpPeriod { get; set; }

/// <summary>
/// Initializes a new instance of the RelativeDailyVolume class using the specified period
/// </summary>
Expand Down Expand Up @@ -86,7 +98,7 @@ protected override decimal ComputeNextValue(TradeBar input)
}
_currentData.Clear();
_previousDay = input.Time.Day;
_days += 1; // _days is starting from -1, to reach IsReady => _days == WarmUpPeriod; also means WarmUpPeriod+1
_days += 1; // _days is starting from -1, to reach IsReady => _days == _period; also means _period+1 days
}

_currentData[input.Time] = input.Volume;
Expand Down
34 changes: 34 additions & 0 deletions Tests/Indicators/RelativeDailyVolumeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,40 @@ public override void WarmsUpProperly()
Assert.IsFalse(rdv8.IsReady);
}

[Test]
public void WarmUpPeriodDefaultsToZeroAndSkipsWarmUp()
{
var algorithm = CreateAlgorithm();
algorithm.SetDateTime(new DateTime(2013, 10, 11, 15, 0, 0));
algorithm.AddEquity("SPY", Resolution.Minute);

var rdv = new RelativeDailyVolume(2);
Assert.AreEqual(0, rdv.WarmUpPeriod);

algorithm.WarmUpIndicator(Symbols.SPY, rdv, Resolution.Minute);

Assert.IsFalse(rdv.IsReady);
Assert.AreEqual(0, rdv.Samples);
}

[TestCase(Resolution.Minute, 3 * 390)]
[TestCase(Resolution.Hour, 3 * 7)]
public void WarmsUpWithUserDefinedWarmUpPeriod(Resolution resolution, int warmUpPeriod)
{
// Regression test for GH #8629: the number of bars needed to warm up this indicator depends on the
// resolution and the market hours, so it is left for the user to define through WarmUpPeriod
var algorithm = CreateAlgorithm();
algorithm.SetDateTime(new DateTime(2013, 10, 11, 15, 0, 0));
algorithm.AddEquity("SPY", resolution);

var rdv = new RelativeDailyVolume(2) { WarmUpPeriod = warmUpPeriod };
algorithm.WarmUpIndicator(Symbols.SPY, rdv, resolution);

Assert.IsTrue(rdv.IsReady);
Assert.AreEqual(warmUpPeriod, rdv.Samples);
Assert.AreNotEqual(0m, rdv.Current.Value);
}

[Test]
public void UsesMostRecentHistoricalSlotForIntradayGap()
{
Expand Down
Loading