Files
quantconnect--lean/Common/Util/LeanDataPathComponents.cs
T
Gerardo Salazar 4c085ff853 Adds Indexes and Index Options asset types (Backtesting/Live, IB only) (#5379)
* Add support for Index SecurityType  🚀 (#5364)

* Add Index SecurityType  🚀

* Extend SecurityIdentifier & Lean Data classes with Index support

* Add Index SecurityType  🚀

* Extend SecurityIdentifier & Lean Data classes with Index support

* Fixes

* Added index cross basic template demonstration

* WIP: Prototype index security type for LEAN as non tradable asset

* Re-adds Index entries to MHDB after rebase

* First steps to getting Index Options running

  * Looks at any instance where we pattern match for an option type
    and replaces it with a generic call to `.IsOption()` for easier
    extensibility in the future for additional option security types

  * Adds IndexOption security and misc. classes

  * Misc. changes, mainly related to any sort of special casing of
    equity options and made index options take the same path

* Enables index options data for backtesting

  * Adds new index options market hours to MHDB
  * Misc. bug fixes for index options
  * WIP: add live support for index options and indexes
  * Use OptionMarginModel for Index Options because they both use the
    same calculation for margin requirements

* Fixes contract not found errors on SPX index options and SPX index in IB

  * Turns out index options' last trading day is the day before expiry,
    which IB was expecting the last trading day.

* Add index option test cases (temp)

* LiveOptionChainProvider fix, use Symbol vs. ticker

  * Description updates to regression algorithms

* Fixes bug in live trading for indexes and index options

  * Adds overridable minimum price variation symbol property
  * Adds variable sized minimum price variation for index options
  * Adjusts symbol properties for index options
  * Misc. bug fixes

* Fixes option assignment simulation for European options

  * Updates index options regression algorithms (WIP)

* Fixes bug where index option exercise would trade index underlying

  * Fixes bugs where SecurityType.Index was getting flagged as tradable

* Regression algorithms updates and addresses review

  * Misc. style fixes and refactoring + a few bug fixes
  * Updates regression algorithms to run without runtime errors
  * Adds data for regression algos

* Sets DefaultOptionStyle on Canonical and support index options

* Update regression algos statistics

* Removes bad line in regression algorithm causing build to fail

* Minor tweaks

* Address review add comment about quoteBar parse scale

Co-authored-by: Balamurali Pandranki <balamurali@live.com>
Co-authored-by: Jared Broad <jaredbroad@gmail.com>
Co-authored-by: Martin-Molinero <martin@quantconnect.com>
2021-03-12 20:46:23 -03:00

201 lines
8.0 KiB
C#

/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.IO;
using QuantConnect.Securities.Future;
namespace QuantConnect.Util
{
/// <summary>
/// Type representing the various pieces of information emebedded into a lean data file path
/// </summary>
public class LeanDataPathComponents
{
/// <summary>
/// Gets the date component from the file name
/// </summary>
public DateTime Date
{
get; private set;
}
/// <summary>
/// Gets the security type from the path
/// </summary>
public SecurityType SecurityType
{
get; private set;
}
/// <summary>
/// Gets the market from the path
/// </summary>
public string Market
{
get; private set;
}
/// <summary>
/// Gets the resolution from the path
/// </summary>
public Resolution Resolution
{
get; private set;
}
/// <summary>
/// Gets the file name, not inluding directory information
/// </summary>
public string Filename
{
get; private set;
}
/// <summary>
/// Gets the symbol object implied by the path. For options, or any
/// multi-entry zip file, this should be the canonical symbol
/// </summary>
public Symbol Symbol
{
get; private set;
}
/// <summary>
/// Gets the tick type from the file name
/// </summary>
public TickType TickType
{
get; private set;
}
/// <summary>
/// Initializes a new instance of the <see cref="LeanDataPathComponents"/> class
/// </summary>
public LeanDataPathComponents(SecurityType securityType, string market, Resolution resolution, Symbol symbol, string filename, DateTime date, TickType tickType)
{
Date = date;
SecurityType = securityType;
Market = market;
Resolution = resolution;
Filename = filename;
Symbol = symbol;
TickType = tickType;
}
/// <summary>
/// Parses the specified path into a new instance of the <see cref="LeanDataPathComponents"/> class
/// </summary>
/// <param name="path">The path to be parsed</param>
/// <returns>A new instance of the <see cref="LeanDataPathComponents"/> class representing the specified path</returns>
public static LeanDataPathComponents Parse(string path)
{
//"../Data/equity/usa/hour/spy.zip"
//"../Data/equity/usa/hour/spy/20160218_trade.zip"
var fileinfo = new FileInfo(path);
var filename = fileinfo.Name;
var parts = path.Split('/', '\\');
// defines the offsets of the security relative to the end of the path
const int LowResSecurityTypeOffset = 4;
const int HighResSecurityTypeOffset = 5;
// defines other offsets relative to the beginning of the substring produce by the above offsets
const int MarketOffset = 1;
const int ResolutionOffset = 2;
const int TickerOffset = 3;
if (parts.Length < LowResSecurityTypeOffset)
{
throw new FormatException($"Unexpected path format: {path}");
}
var securityTypeOffset = LowResSecurityTypeOffset;
SecurityType securityType;
var rawValue = parts[parts.Length - securityTypeOffset];
if (!Enum.TryParse(rawValue, true, out securityType))
{
securityTypeOffset = HighResSecurityTypeOffset;
rawValue = parts[parts.Length - securityTypeOffset];
if (!Enum.TryParse(rawValue, true, out securityType))
{
throw new FormatException($"Unexpected path format: {path}");
}
}
var market = parts[parts.Length - securityTypeOffset + MarketOffset];
var resolution = (Resolution) Enum.Parse(typeof (Resolution), parts[parts.Length - securityTypeOffset + ResolutionOffset], true);
string ticker;
if (securityTypeOffset == LowResSecurityTypeOffset)
{
ticker = Path.GetFileNameWithoutExtension(path);
if (securityType.IsOption())
{
// ticker_trade_american
var tickerWithoutStyle = ticker.Substring(0, ticker.LastIndexOfInvariant("_"));
ticker = tickerWithoutStyle.Substring(0, tickerWithoutStyle.LastIndexOfInvariant("_"));
}
if (securityType == SecurityType.Future)
{
// ticker_trade
ticker = ticker.Substring(0, ticker.LastIndexOfInvariant("_"));
}
if (securityType == SecurityType.Crypto &&
(resolution == Resolution.Daily || resolution == Resolution.Hour))
{
// ticker_trade or ticker_quote
ticker = ticker.Substring(0, ticker.LastIndexOfInvariant("_"));
}
}
else
{
ticker = parts[parts.Length - securityTypeOffset + TickerOffset];
}
var date = securityTypeOffset == LowResSecurityTypeOffset ? DateTime.MinValue : DateTime.ParseExact(filename.Substring(0, filename.IndexOf("_", StringComparison.Ordinal)), DateFormat.EightCharacter, null);
Symbol symbol;
if (securityType == SecurityType.Option)
{
var withoutExtension = Path.GetFileNameWithoutExtension(filename);
rawValue = withoutExtension.Substring(withoutExtension.LastIndexOf("_", StringComparison.Ordinal) + 1);
var style = (OptionStyle) Enum.Parse(typeof (OptionStyle), rawValue, true);
symbol = Symbol.CreateOption(ticker, market, style, OptionRight.Call | OptionRight.Put, 0, SecurityIdentifier.DefaultDate);
}
else if (securityType == SecurityType.FutureOption)
{
var withoutExtension = Path.GetFileNameWithoutExtension(filename);
rawValue = withoutExtension.Substring(withoutExtension.LastIndexOf("_", StringComparison.Ordinal) + 1);
var style = (OptionStyle) Enum.Parse(typeof (OptionStyle), rawValue, true);
var futureSymbol = QuantConnect.Symbol.Create(FuturesOptionsSymbolMappings.MapFromOption(ticker), SecurityType.Future, market);
symbol = Symbol.CreateOption(futureSymbol, market, style, OptionRight.Call | OptionRight.Put, 0, SecurityIdentifier.DefaultDate);
}
else if (securityType == SecurityType.Future)
{
symbol = Symbol.CreateFuture(ticker, market, SecurityIdentifier.DefaultDate);
}
else
{
symbol = Symbol.Create(ticker, securityType, market);
}
var tickType = filename.Contains("_quote") ? TickType.Quote : (filename.Contains("_openinterest") ? TickType.OpenInterest : TickType.Trade);
return new LeanDataPathComponents(securityType, market, resolution, symbol, filename, date, tickType);
}
}
}