Skip to content

Commit

Permalink
Fix Futures SymbolRepresentation disambiguation of ticker with limite…
Browse files Browse the repository at this point in the history
…d year information (QuantConnect#5715)

* Fixes bug where future converter processing includes invalid values

* Fix issue in SymbolRepresentation

* Fixup

* Empty commit

* Empty commit
  • Loading branch information
gsalaz98 authored Jun 29, 2021
1 parent 0d45bf5 commit c9a3ad3
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 9 deletions.
10 changes: 6 additions & 4 deletions Common/SymbolRepresentation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,11 @@ public static FutureTickerProperties ParseFutureTicker(string ticker)
/// Helper method to parse and generate a future symbol from a given user friendly representation
/// </summary>
/// <param name="ticker">The future ticker, for example 'ESZ1'</param>
/// <param name="futureYear">Clarifies the year for the current future</param>
/// <returns>The future symbol or null if failed</returns>
public static Symbol ParseFutureSymbol(string ticker)
public static Symbol ParseFutureSymbol(string ticker, int? futureYear = null)
{
var disambiguatedFutureYear = futureYear ?? TodayUtc.Year;
var parsed = ParseFutureTicker(ticker);
if (parsed == null)
{
Expand All @@ -153,7 +155,7 @@ public static Symbol ParseFutureSymbol(string ticker)
var underlying = parsed.Underlying;
var expirationYearShort = parsed.ExpirationYearShort;
var expirationMonth = parsed.ExpirationMonth;
var expirationYear = GetExpirationYear(expirationYearShort);
var expirationYear = GetExpirationYear(expirationYearShort, disambiguatedFutureYear);

if (!SymbolPropertiesDatabase.FromDataFolder().TryGetMarket(underlying, SecurityType.Future, out var market))
{
Expand Down Expand Up @@ -439,10 +441,10 @@ public static OptionTickerProperties ParseOptionTickerIQFeed(string ticker)

private static IReadOnlyDictionary<int, string> _futuresMonthLookup = _futuresMonthCodeLookup.ToDictionary(kv => kv.Value, kv => kv.Key);

private static int GetExpirationYear(int year)
private static int GetExpirationYear(int year, int futureYear)
{
var baseNum = 2000;
while (baseNum + year < TodayUtc.Year)
while (baseNum + year < futureYear)
{
baseNum += 10;
}
Expand Down
8 changes: 8 additions & 0 deletions Tests/Common/SymbolRepresentationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,5 +180,13 @@ public void GenerateFutureTickerExpiringInNextMonth(string ticker, int year, int

Assert.AreEqual(expectedValue, result);
}

[TestCase("VXZ2")]
public void GenerateFutureSymbolFromTickerMissingDecadeInfo(string ticker)
{
var result = SymbolRepresentation.ParseFutureSymbol(ticker, 2012);

Assert.AreEqual(new DateTime(2012, 12, 19), result.ID.Date.Date);
}
}
}
6 changes: 6 additions & 0 deletions ToolBox/AlgoSeekFuturesConverter/AlgoSeekFuturesConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ public void Convert()
{
var tick = reader.Current as Tick;

if (tick.Symbol.ID.Symbol == "VX" && (
tick.BidPrice >= 998m || tick.AskPrice >= 998m))
{
// Invalid value for VX futures. Invalid prices in raw data are 998/999
continue;
}
//Add or create the consolidator-flush mechanism for symbol:
List<List<AlgoSeekFuturesProcessor>> symbolProcessors;
if (!processors.TryGetValue(tick.Symbol, out symbolProcessors))
Expand Down
10 changes: 5 additions & 5 deletions ToolBox/AlgoSeekFuturesConverter/AlgoSeekFuturesReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,18 +168,18 @@ private Tick Parse(string line)
return null;
}

var symbol = SymbolRepresentation.ParseFutureSymbol(ticker);
// ignoring time zones completely -- this is all in the 'data-time-zone'
var timeString = csv[_columnTimestamp];
var time = DateTime.ParseExact(timeString, "yyyyMMddHHmmssFFF", CultureInfo.InvariantCulture);

var symbol = SymbolRepresentation.ParseFutureSymbol(ticker, time.Year);

if (symbol == null || !_symbolMultipliers.ContainsKey(symbol.ID.Symbol) ||
_symbolFilter != null && !_symbolFilter.Contains(symbol.ID.Symbol, StringComparer.InvariantCultureIgnoreCase))
{
return null;
}

// ignoring time zones completely -- this is all in the 'data-time-zone'
var timeString = csv[_columnTimestamp];
var time = DateTime.ParseExact(timeString, "yyyyMMddHHmmssFFF", CultureInfo.InvariantCulture);

// detecting tick type (trade or quote)
TickType tickType;
bool isAsk = false;
Expand Down

0 comments on commit c9a3ad3

Please sign in to comment.