Skip to content

Commit a159950

Browse files
authored
Fix: refresh symbol properties using right type for security. (#8087)
Fix for live trading SPDB refresh
1 parent 4ca5cbc commit a159950

File tree

5 files changed

+111
-2
lines changed

5 files changed

+111
-2
lines changed

Common/Securities/IndexOption/IndexOption.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,16 @@ protected override void UpdateConsumersMarketPrice(BaseData data)
8383
base.UpdateConsumersMarketPrice(data);
8484
((IndexOptionSymbolProperties)SymbolProperties).UpdateMarketPrice(data);
8585
}
86+
87+
/// <summary>
88+
/// Updates the symbol properties of this security
89+
/// </summary>
90+
internal override void UpdateSymbolProperties(SymbolProperties symbolProperties)
91+
{
92+
if (symbolProperties != null)
93+
{
94+
SymbolProperties = new IndexOptionSymbolProperties(symbolProperties);
95+
}
96+
}
8697
}
8798
}

Common/Securities/Option/Option.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,5 +668,16 @@ private void SetFilterImp(Func<OptionFilterUniverse, OptionFilterUniverse> unive
668668
return result.ApplyTypesFilter();
669669
});
670670
}
671+
672+
/// <summary>
673+
/// Updates the symbol properties of this security
674+
/// </summary>
675+
internal override void UpdateSymbolProperties(SymbolProperties symbolProperties)
676+
{
677+
if (symbolProperties != null)
678+
{
679+
SymbolProperties = new OptionSymbolProperties(symbolProperties);
680+
}
681+
}
671682
}
672683
}

Common/Securities/Security.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public Cash QuoteCurrency
100100
public SymbolProperties SymbolProperties
101101
{
102102
get;
103-
internal set;
103+
protected set;
104104
}
105105

106106
/// <summary>
@@ -1146,5 +1146,16 @@ internal void ApplySplit(Split split)
11461146
Cache.ApplySplit(split);
11471147
UpdateMarketPrice(Cache.GetData());
11481148
}
1149+
1150+
/// <summary>
1151+
/// Updates the symbol properties of this security
1152+
/// </summary>
1153+
internal virtual void UpdateSymbolProperties(SymbolProperties symbolProperties)
1154+
{
1155+
if (symbolProperties != null)
1156+
{
1157+
SymbolProperties = symbolProperties;
1158+
}
1159+
}
11491160
}
11501161
}

Engine/RealTime/LiveTradingRealTimeHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ protected virtual void UpdateSymbolProperties(Security security)
242242
{
243243
var symbolProperties = SymbolPropertiesDatabase.GetSymbolProperties(security.Symbol.ID.Market, security.Symbol,
244244
security.Symbol.ID.SecurityType, security.QuoteCurrency.Symbol);
245-
security.SymbolProperties = symbolProperties;
245+
security.UpdateSymbolProperties(symbolProperties);
246246
}
247247

248248
/// <summary>

Tests/Engine/RealTime/LiveTradingRealTimeHandlerTests.cs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
using QuantConnect.Lean.Engine.HistoricalData;
3636
using QuantConnect.Lean.Engine.DataFeeds;
3737
using QuantConnect.Util;
38+
using QuantConnect.Securities.Option;
39+
using QuantConnect.Securities.IndexOption;
3840

3941
namespace QuantConnect.Tests.Engine.RealTime
4042
{
@@ -202,6 +204,80 @@ public void RefreshesSymbolProperties(string refreshPeriodStr)
202204
}
203205
}
204206

207+
[TestCase(SecurityType.Equity, typeof(SymbolProperties))]
208+
[TestCase(SecurityType.Forex, typeof(SymbolProperties))]
209+
[TestCase(SecurityType.Future, typeof(SymbolProperties))]
210+
[TestCase(SecurityType.FutureOption, typeof(SymbolProperties))]
211+
[TestCase(SecurityType.Cfd, typeof(SymbolProperties))]
212+
[TestCase(SecurityType.Crypto, typeof(SymbolProperties))]
213+
[TestCase(SecurityType.CryptoFuture, typeof(SymbolProperties))]
214+
[TestCase(SecurityType.Index, typeof(SymbolProperties))]
215+
[TestCase(SecurityType.Option, typeof(OptionSymbolProperties))]
216+
[TestCase(SecurityType.IndexOption, typeof(IndexOptionSymbolProperties))]
217+
public void SecuritySymbolPropertiesTypeIsRespectedAfterRefresh(SecurityType securityType, Type expectedSymbolPropertiesType)
218+
{
219+
using var realTimeHandler = new SPDBTestLiveTradingRealTimeHandler();
220+
221+
var timeProvider = realTimeHandler.PublicTimeProvider;
222+
timeProvider.SetCurrentTimeUtc(new DateTime(2023, 5, 30));
223+
224+
var algorithm = new AlgorithmStub();
225+
var refreshPeriod = TimeSpan.FromDays(1);
226+
algorithm.Settings.DatabasesRefreshPeriod = refreshPeriod;
227+
228+
var symbol = GetSymbol(securityType);
229+
var security = algorithm.AddSecurity(symbol);
230+
231+
Assert.IsInstanceOf(expectedSymbolPropertiesType, security.SymbolProperties);
232+
233+
realTimeHandler.Setup(algorithm,
234+
new AlgorithmNodePacket(PacketType.AlgorithmNode),
235+
new BacktestingResultHandler(),
236+
null,
237+
new TestTimeLimitManager());
238+
realTimeHandler.SpdbRefreshed.Reset();
239+
realTimeHandler.SecuritySymbolPropertiesUpdated.Reset();
240+
241+
algorithm.SetFinishedWarmingUp();
242+
realTimeHandler.SetTime(timeProvider.GetUtcNow());
243+
244+
var previousSymbolProperties = security.SymbolProperties;
245+
246+
// Refresh the spdb
247+
timeProvider.Advance(refreshPeriod);
248+
Assert.IsTrue(realTimeHandler.SpdbRefreshed.WaitOne(1000));
249+
Assert.IsTrue(realTimeHandler.SecuritySymbolPropertiesUpdated.WaitOne(1000));
250+
251+
// Access the symbol properties again
252+
// The instance must have been changed
253+
Assert.AreNotSame(security.SymbolProperties, previousSymbolProperties);
254+
Assert.IsInstanceOf(expectedSymbolPropertiesType, security.SymbolProperties);
255+
}
256+
257+
private static Symbol GetSymbol(SecurityType securityType)
258+
{
259+
return securityType switch
260+
{
261+
SecurityType.Equity => Symbols.SPY,
262+
SecurityType.Forex => Symbols.USDJPY,
263+
SecurityType.Future => Symbols.Future_ESZ18_Dec2018,
264+
SecurityType.FutureOption => Symbol.CreateOption(
265+
Symbols.Future_ESZ18_Dec2018,
266+
Market.CME,
267+
OptionStyle.American,
268+
OptionRight.Call,
269+
4000m,
270+
new DateTime(2023, 6, 16)),
271+
SecurityType.Cfd => Symbols.DE10YBEUR,
272+
SecurityType.Crypto => Symbols.BTCUSD,
273+
SecurityType.CryptoFuture => Symbol.Create("BTCUSD", securityType, Market.Binance),
274+
SecurityType.Index => Symbols.SPX,
275+
SecurityType.Option => Symbols.SPY_C_192_Feb19_2016,
276+
SecurityType.IndexOption => Symbol.Create("SPX", securityType, Market.USA),
277+
_ => throw new ArgumentOutOfRangeException(nameof(securityType), securityType, null)
278+
};
279+
}
280+
205281
private class TestTimeLimitManager : IIsolatorLimitResultProvider
206282
{
207283
public IsolatorLimitResult IsWithinLimit()

0 commit comments

Comments
 (0)