/*
* 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.Linq;
using System.Collections.Generic;
using QuantConnect.Securities.Future;
namespace QuantConnect.Securities.IndexOption
{
///
/// Index Option Symbol
///
public static class IndexOptionSymbol
{
private static readonly Dictionary _nonStandardOptionToIndex = new()
{
{ "RUTW", "RUT" },
{ "SPXW", "SPX" },
{ "VIXW", "VIX" },
{ "NDXP", "NDX" },
{ "NQX", "NDX" },
};
///
/// These are known assets that are weeklies or end-of-month settled contracts.
///
private static readonly HashSet _nonStandardIndexOptionTickers = new()
{
// Weeklies
"RUTW", // PM-Settled. While RUT AM-Settled on 3rd Fridays
"SPXW",
"VIXW",
// PM-Settled
"NDXP",
// reduced value index options, 20%
"NQX"
};
///
/// Supported index option tickers
///
public static readonly HashSet SupportedIndexOptionTickers = new string[] { "SPX", "NDX", "VIX", "RUT" }
.Union(_nonStandardIndexOptionTickers)
.ToHashSet();
///
/// Determines if the Index Option Symbol is for a monthly contract
///
/// Index Option Symbol
/// True if monthly contract, false otherwise
public static bool IsStandard(Symbol symbol)
{
if (symbol.ID.Market != Market.USA)
{
return true;
}
switch (symbol.ID.Symbol)
{
case "NQX":
case "SPXW":
case "RUTW":
// they have weeklies and monthly contracts
// NQX https://www.nasdaq.com/docs/NQXFactSheet.pdf
// SPXW https://www.cboe.com/tradable_products/sp_500/spx_weekly_options/specifications/
// RUTW expires every day
return FuturesExpiryUtilityFunctions.ThirdFriday(symbol.ID.Date) == symbol.ID.Date;
default:
// NDX/SPX/NQX/VIX/VIXW/NDXP/RUT are all normal contracts
return true;
}
}
///
/// Checks if the ticker provided is a supported Index Option
///
/// Ticker of the index option
/// true if the ticker matches an index option's ticker
///
/// This is only used in IB brokerage, since they don't distinguish index options
/// from regular equity options. When we do the conversion from a contract to a SecurityType,
/// the only information we're provided that can reverse it to the
/// enum value is the ticker.
///
public static bool IsIndexOption(string ticker)
{
return SupportedIndexOptionTickers.Contains(ticker.LazyToUpper());
}
///
/// Maps an index option ticker to its underlying index ticker
///
/// Index option ticker to map to the underlying
/// Index ticker
public static string MapToUnderlying(string indexOption)
{
if(_nonStandardOptionToIndex.TryGetValue(indexOption.LazyToUpper(), out var index))
{
return index;
}
return indexOption;
}
///
/// Returns the last trading date for the given index option ticker and expiration date
///
/// This is useful for IB brokerage
public static DateTime GetLastTradingDate(string ticker, DateTime expirationDate)
{
return expirationDate.AddDays(-GetExpirationOffset(ticker));
}
///
/// Returns the expiry date for the given index option ticker and last trading date
///
/// This is useful for IB brokerage
public static DateTime GetExpiryDate(string ticker, DateTime lastTradingDate)
{
return lastTradingDate.AddDays(GetExpirationOffset(ticker));
}
///
/// Some index options last tradable date is the previous day to the expiration
/// https://www.cboe.com/tradable_products/vix/vix_options/specifications/
/// https://www.cboe.com/tradable_products/ftse_russell/russell_2000_index_options/rut_specifications
///
private static int GetExpirationOffset(string ticker)
{
switch (ticker)
{
case "SPX":
case "NDX":
case "VIX":
case "VIXW":
case "RUT":
return 1;
default:
// SPXW, NQX, NDXP, RUTW
return 0;
}
}
}
}