diff --git a/MyCustomDataProvider.cs b/MyCustomDataProvider.cs
index 2ff770d..724ba7f 100644
--- a/MyCustomDataProvider.cs
+++ b/MyCustomDataProvider.cs
@@ -28,7 +28,7 @@ namespace QuantConnect.Lean.DataSource.MyCustom
///
/// Implementation of Custom Data Provider
///
- public class MyCustomDataProvider : SynchronizingHistoryProvider, IDataQueueHandler
+ public class MyCustomDataProvider : SynchronizingHistoryProvider, IDataQueueHandler, IDataQueueUniverseProvider
{
///
///
@@ -157,5 +157,20 @@ private bool CanSubscribe(Symbol symbol)
throw new NotImplementedException();
}
+
+ public IEnumerable LookupSymbols(Symbol symbol, bool includeExpired, string securityCurrency = null)
+ {
+ if (!symbol.SecurityType.IsOption())
+ {
+ throw new ArgumentException($"Unsupported security type: {symbol.SecurityType}", nameof(symbol));
+ }
+
+ throw new NotImplementedException();
+ }
+
+ public bool CanPerformSelection()
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/tests/MyCustomDataQueueHandlerTests.cs b/tests/MyCustomDataQueueHandlerTests.cs
index 2e0afbd..2bf70ac 100644
--- a/tests/MyCustomDataQueueHandlerTests.cs
+++ b/tests/MyCustomDataQueueHandlerTests.cs
@@ -25,6 +25,7 @@
using System.Threading.Tasks;
using QuantConnect.Data.Market;
using System.Collections.Generic;
+using System.Collections.Concurrent;
using QuantConnect.Lean.DataSource.MyCustom;
namespace QuantConnect.DataLibrary.Tests
@@ -74,6 +75,57 @@ public void StreamsData(Symbol symbol, Resolution resolution)
Thread.Sleep(1_000);
}
+ [TestCaseSource(nameof(TestParameters))]
+ public void StreamsOptionChainData(Symbol symbol, Resolution resolution)
+ {
+ Assert.Pass();
+
+ var canonicalOption = Symbol.CreateCanonicalOption(symbol);
+
+ var dataProvider = new MyCustomDataProvider();
+
+ var configs = dataProvider.LookupSymbols(canonicalOption, true).SelectMany(optionContract => GetSubscriptionDataConfigs(optionContract, resolution)).ToList();
+
+ var symbolOpenInterest = new ConcurrentDictionary>();
+
+ foreach (var config in configs)
+ {
+ symbolOpenInterest[config.Symbol] = new Dictionary
+ {
+ [typeof(QuoteBar)] = 0,
+ [typeof(TradeBar)] = 0
+ };
+
+ ProcessFeed(
+ dataProvider.Subscribe(config, (s, e) => { }),
+ (baseData) =>
+ {
+ if (baseData != null)
+ {
+ Log.Trace($"{baseData}");
+ switch (baseData)
+ {
+ case QuoteBar qb:
+ symbolOpenInterest[qb.Symbol][typeof(QuoteBar)] += 1;
+ break;
+ case TradeBar tb:
+ symbolOpenInterest[tb.Symbol][typeof(TradeBar)] += 1;
+ break;
+ }
+ }
+ });
+ }
+
+ Thread.Sleep(1_000);
+
+ foreach (var config in configs)
+ {
+ dataProvider.Unsubscribe(config);
+ }
+
+ Thread.Sleep(1_000);
+ }
+
private IEnumerable GetSubscriptionDataConfigs(Symbol symbol, Resolution resolution)
{
if (resolution == Resolution.Tick)