Skip to content

Commit

Permalink
Period consolidator adjusments (QuantConnect#6444)
Browse files Browse the repository at this point in the history
- Replace logic to convert TimeSpan based PeriodConsolidator into count
  based, by an override of the 'potentialStartTime' in the case we could
  be falling into a look ahead consolidated bar end time
  • Loading branch information
Martin-Molinero authored Jun 27, 2022
1 parent 630503b commit 5c6a779
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 23 deletions.
4 changes: 2 additions & 2 deletions Common/Data/Consolidators/DynamicDataConsolidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ protected override void AggregateBar(ref TradeBar workingBar, DynamicData data)
workingBar = new TradeBar
{
Symbol = data.Symbol,
Time = GetRoundedBarTime(data.Time),
Time = GetRoundedBarTime(data),
Open = open,
High = high,
Low = low,
Expand All @@ -112,4 +112,4 @@ private static decimal GetNamedPropertyOrValueProperty(DynamicData data, string
return data.GetProperty(propertyName).ConvertInvariant<decimal>();
}
}
}
}
6 changes: 3 additions & 3 deletions Common/Data/Consolidators/OpenInterestConsolidator.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
Expand Down Expand Up @@ -104,7 +104,7 @@ protected override void AggregateBar(ref OpenInterest workingBar, Tick tick)
workingBar = new OpenInterest
{
Symbol = tick.Symbol,
Time = GetRoundedBarTime(tick.Time),
Time = GetRoundedBarTime(tick),
Value = tick.Value
};

Expand All @@ -116,4 +116,4 @@ protected override void AggregateBar(ref OpenInterest workingBar, Tick tick)
}
}
}
}
}
29 changes: 20 additions & 9 deletions Common/Data/Consolidators/PeriodCountConsolidatorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,7 @@ public override void Update(T data)
// only do this check once
_validateTimeSpan = true;
var dataLength = data.EndTime - data.Time;
if (dataLength == _period)
{
// if the user is consolidating period 'X' with data of length 'X', be gentle, and transform into a bar of count 1 consolidation, we want to avoid issues like #3062
_maxCount = 1;
_periodSpecification = new BarCountPeriodSpecification();
_period = _periodSpecification.Period;
}
else if (dataLength > _period)
if (dataLength > _period)
{
throw new ArgumentException($"For Symbol {data.Symbol} can not consolidate bars of period: {_period}, using data of the same or higher period: {data.EndTime - data.Time}");
}
Expand Down Expand Up @@ -194,7 +187,7 @@ public override void Update(T data)
if (_period.HasValue)
{
// we're in time span mode and initialized
if (_workingBar != null && data.Time - _workingBar.Time >= _period.Value && GetRoundedBarTime(data.Time) > _lastEmit)
if (_workingBar != null && data.Time - _workingBar.Time >= _period.Value && GetRoundedBarTime(data) > _lastEmit)
{
fireDataConsolidated = true;
}
Expand Down Expand Up @@ -305,6 +298,24 @@ protected DateTime GetRoundedBarTime(DateTime time)
return startTime;
}

/// <summary>
/// Gets a rounded-down bar start time. Called by AggregateBar in derived classes.
/// </summary>
/// <param name="inputData">The input data point</param>
/// <returns>The rounded bar start time</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected DateTime GetRoundedBarTime(IBaseData inputData)
{
var potentialStartTime = GetRoundedBarTime(inputData.Time);
if(_period.HasValue && potentialStartTime + _period < inputData.EndTime)
{
// whops! the end time we were giving is beyond our potential end time, so let's use the giving bars star time instead
potentialStartTime = inputData.Time;
}

return potentialStartTime;
}

/// <summary>
/// Event invocator for the <see cref="DataConsolidated"/> event
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion Common/Data/Consolidators/QuoteBarConsolidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ protected override void AggregateBar(ref QuoteBar workingBar, QuoteBar data)

if (workingBar == null)
{
workingBar = new QuoteBar(GetRoundedBarTime(data.Time), data.Symbol, null, 0, null, 0, IsTimeBased && Period.HasValue ? Period : data.Period);
workingBar = new QuoteBar(GetRoundedBarTime(data), data.Symbol, null, 0, null, 0, IsTimeBased && Period.HasValue ? Period : data.Period);

// open ask and bid should match previous close ask and bid
if (Consolidated != null)
Expand Down
4 changes: 2 additions & 2 deletions Common/Data/Consolidators/TickConsolidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ protected override void AggregateBar(ref TradeBar workingBar, Tick data)
{
if (workingBar == null)
{
workingBar = new TradeBar(GetRoundedBarTime(data.Time),
workingBar = new TradeBar(GetRoundedBarTime(data),
data.Symbol,
data.Value,
data.Value,
Expand All @@ -110,4 +110,4 @@ protected override void AggregateBar(ref TradeBar workingBar, Tick data)
}
}
}
}
}
4 changes: 2 additions & 2 deletions Common/Data/Consolidators/TickQuoteBarConsolidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ protected override void AggregateBar(ref QuoteBar workingBar, Tick data)
{
if (workingBar == null)
{
workingBar = new QuoteBar(GetRoundedBarTime(data.Time), data.Symbol, null, decimal.Zero, null, decimal.Zero, Period);
workingBar = new QuoteBar(GetRoundedBarTime(data), data.Symbol, null, decimal.Zero, null, decimal.Zero, Period);

// open ask and bid should match previous close ask and bid
if (Consolidated != null)
Expand All @@ -107,4 +107,4 @@ protected override void AggregateBar(ref QuoteBar workingBar, Tick data)
if (!Period.HasValue) workingBar.EndTime = GetRoundedBarTime(data.EndTime);
}
}
}
}
6 changes: 3 additions & 3 deletions Common/Data/Consolidators/TradeBarConsolidator.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
Expand Down Expand Up @@ -97,7 +97,7 @@ protected override void AggregateBar(ref TradeBar workingBar, TradeBar data)
{
workingBar = new TradeBar
{
Time = GetRoundedBarTime(data.Time),
Time = GetRoundedBarTime(data),
Symbol = data.Symbol,
Open = data.Open,
High = data.High,
Expand All @@ -119,4 +119,4 @@ protected override void AggregateBar(ref TradeBar workingBar, TradeBar data)
}
}
}
}
}
58 changes: 58 additions & 0 deletions Tests/Common/Data/QuoteBarConsolidatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,62 @@ public void ThrowsWhenPeriodIsSmallerThanDataPeriod()
Assert.Throws<ArgumentException>(() => creator.Update(bar1));
}

[Test]
public void MultipleResolutionConsolidation()
{
QuoteBar quoteBar = null;
using var creator = new QuoteBarConsolidator(Time.OneDay);
creator.DataConsolidated += (sender, args) =>
{
quoteBar = args;
};

var time = new DateTime(2022, 6, 6);
var bar1 = new QuoteBar
{
Time = time,
Symbol = Symbols.SPY,
Bid = new Bar(1, 2, 0.75m, 1.25m),
LastBidSize = 3,
Ask = null,
LastAskSize = 0,
Value = 1,
Period = TimeSpan.FromDays(1)
};
creator.Update(bar1);
Assert.IsNull(quoteBar);
creator.Scan(bar1.EndTime);
Assert.IsNotNull(quoteBar);
quoteBar = null;

// now let's send in other resolution data
var previousBar = bar1;
for (int i = 0; i <= 24; i++)
{
previousBar = new QuoteBar
{
Time = previousBar.EndTime,
Symbol = Symbols.SPY,
Bid = new Bar(1, 2, 0.75m, 1.25m),
LastBidSize = 3,
Ask = null,
LastAskSize = 0,
Value = 1,
Period = TimeSpan.FromHours(1)
};
creator.Update(previousBar);

if (i < 24)
{
Assert.IsNull(quoteBar, $"{i} {previousBar.EndTime}");
}
else
{
Assert.IsNotNull(quoteBar, $"{i} {previousBar.EndTime}");
}
}
}

[Test]
public void GentlyHandlesPeriodAndDataAreSameResolution()
{
Expand All @@ -71,6 +127,8 @@ public void GentlyHandlesPeriodAndDataAreSameResolution()
Period = TimeSpan.FromDays(1)
};
creator.Update(bar1);
Assert.IsNull(quoteBar);
creator.Scan(bar1.EndTime);
Assert.IsNotNull(quoteBar);

Assert.AreEqual(bar1.Symbol, quoteBar.Symbol);
Expand Down
7 changes: 6 additions & 1 deletion Tests/Common/Data/TradeBarConsolidatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -438,11 +438,16 @@ public void GentlyHandlesPeriodAndDataAreSameResolution()
};

var reference = new DateTime(2015, 04, 13);
var bar = new TradeBar { Time = reference, Period = Time.OneDay };
consolidator.Update(bar);

consolidator.Update(new TradeBar { Time = reference, Period = Time.OneDay });
Assert.IsNull(consolidated);
consolidator.Scan(bar.EndTime);
Assert.IsNotNull(consolidated);

Assert.IsNotNull(consolidated);
Assert.AreEqual(reference, consolidated.Time);
Assert.AreEqual(Time.OneDay, consolidated.Period);
}

[Test]
Expand Down

0 comments on commit 5c6a779

Please sign in to comment.