Skip to content

Commit

Permalink
Fix multiple coarse selection algorithms (QuantConnect#5927)
Browse files Browse the repository at this point in the history
- Fix for live trading multiple coarse selections. Adding unit test
  reproducing issue.
  • Loading branch information
Martin-Molinero authored Sep 14, 2021
1 parent e13df5c commit 0931ae8
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 29 deletions.
9 changes: 2 additions & 7 deletions Common/Data/UniverseSelection/CoarseFundamental.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,11 @@ public override BaseData Clone()
/// Creates the symbol used for coarse fundamental data
/// </summary>
/// <param name="market">The market</param>
/// <param name="addGuid">True, will add a random GUID to allow uniqueness</param>
/// <returns>A coarse universe symbol for the specified market</returns>
public static Symbol CreateUniverseSymbol(string market, bool addGuid = true)
public static Symbol CreateUniverseSymbol(string market)
{
market = market.ToLowerInvariant();
var ticker = $"qc-universe-coarse-{market}";
if (addGuid)
{
ticker += $"-{Guid.NewGuid()}";
}
var ticker = $"qc-universe-coarse-{market}-{Guid.NewGuid()}";
var sid = SecurityIdentifier.GenerateEquity(SecurityIdentifier.DefaultDate, ticker, market);
return new Symbol(sid, ticker);
}
Expand Down
10 changes: 3 additions & 7 deletions Engine/DataFeeds/LiveTradingDataFeed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -304,10 +304,6 @@ private Subscription CreateUniverseSubscription(SubscriptionRequest request)
{
Log.Trace($"LiveTradingDataFeed.CreateUniverseSubscription(): Creating coarse universe: {config.Symbol.ID}");

// we subscribe using a normalized symbol, without a random GUID,
// since the ticker plant will send the coarse data using this symbol
var normalizedSymbol = CoarseFundamental.CreateUniverseSymbol(config.Symbol.ID.Market, false);

// Will try to pull coarse data from the data folder every 10min, file with today's date.
// If lean is started today it will trigger initial coarse universe selection
var factory = new LiveCustomDataSubscriptionEnumeratorFactory(_timeProvider,
Expand All @@ -318,11 +314,11 @@ private Subscription CreateUniverseSubscription(SubscriptionRequest request)
var enumeratorStack = factory.CreateEnumerator(request, _dataProvider);

// aggregates each coarse data point into a single BaseDataCollection
var aggregator = new BaseDataCollectionAggregatorEnumerator(enumeratorStack, normalizedSymbol, true);
_customExchange.AddEnumerator(normalizedSymbol, aggregator);
var aggregator = new BaseDataCollectionAggregatorEnumerator(enumeratorStack, config.Symbol, true);
_customExchange.AddEnumerator(config.Symbol, aggregator);

var enqueable = new EnqueueableEnumerator<BaseData>();
_customExchange.SetDataHandler(normalizedSymbol, data =>
_customExchange.SetDataHandler(config.Symbol, data =>
{
var coarseData = data as BaseDataCollection;
enqueable.Enqueue(new BaseDataCollection(coarseData.Time, config.Symbol, coarseData.Data));
Expand Down
37 changes: 22 additions & 15 deletions Tests/Engine/DataFeeds/LiveTradingDataFeedTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -833,28 +833,32 @@ public void CustomUniverseFineFundamentalDataGetsPipedCorrectly()
Assert.IsTrue(fineWasCalled);
}


[Test]
public void FineCoarseFundamentalDataGetsPipedCorrectly()
[TestCase(1)]
[TestCase(2)]
public void FineCoarseFundamentalDataGetsPipedCorrectly(int numberOfUniverses)
{
_startDate = new DateTime(2014, 3, 25);
CustomMockedFileBaseData.StartDate = _startDate;
_manualTimeProvider.SetCurrentTimeUtc(_startDate);

var feed = RunDataFeed(getNextTicksFunction: fdqh => Enumerable.Empty<BaseData>());

var fineWasCalled = false;
_algorithm.AddUniverse(coarse => coarse
.Where(x => x.Symbol.ID.Symbol.Contains("AAPL")).Select((fundamental, i) => fundamental.Symbol),
fine =>
{
var symbol = fine.First().Symbol;
if (symbol == Symbols.AAPL)
var fineWasCalled = new List<bool> { false, false };
for (var i = 0; i < numberOfUniverses; i++)
{
var index = i;
_algorithm.AddUniverse(coarse => coarse
.Where(x => x.Symbol.ID.Symbol.Contains("AAPL")).Select((fundamental, i) => fundamental.Symbol),
fine =>
{
fineWasCalled = true;
}
return new[] { symbol };
});
var symbol = fine.First().Symbol;
if (symbol == Symbols.AAPL)
{
fineWasCalled[index] = true;
}
return new[] { symbol };
});
}

var receivedFundamentalsData = false;
ConsumeBridge(feed, TimeSpan.FromSeconds(5), ts =>
Expand All @@ -869,7 +873,10 @@ public void FineCoarseFundamentalDataGetsPipedCorrectly()
}, sendUniverseData: true, alwaysInvoke: true, secondsTimeStep: 3600, endDate: _startDate.AddDays(10));

Assert.IsTrue(receivedFundamentalsData);
Assert.IsTrue(fineWasCalled);
for (var i = 0; i < numberOfUniverses; i++)
{
Assert.IsTrue(fineWasCalled[i]);
}
}

[TestCase(SecurityType.Future)]
Expand Down

0 comments on commit 0931ae8

Please sign in to comment.