chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,691 @@
|
||||
/*
|
||||
* 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 Python.Runtime;
|
||||
using QuantConnect.Data;
|
||||
using QuantConnect.Data.Market;
|
||||
using QuantConnect.Data.UniverseSelection;
|
||||
using QuantConnect.Interfaces;
|
||||
using QuantConnect.Orders;
|
||||
using QuantConnect.Orders.Fees;
|
||||
using QuantConnect.Orders.Fills;
|
||||
using QuantConnect.Orders.OptionExercise;
|
||||
using QuantConnect.Orders.Slippage;
|
||||
using QuantConnect.Python;
|
||||
using QuantConnect.Securities.Interfaces;
|
||||
using QuantConnect.Util;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Securities.Option
|
||||
{
|
||||
/// <summary>
|
||||
/// Option Security Object Implementation for Option Assets
|
||||
/// </summary>
|
||||
/// <seealso cref="Security"/>
|
||||
public class Option : Security, IDerivativeSecurity, IOptionPrice
|
||||
{
|
||||
/// <summary>
|
||||
/// The default number of days required to settle an equity sale
|
||||
/// </summary>
|
||||
public static int DefaultSettlementDays { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The default time of day for settlement
|
||||
/// </summary>
|
||||
public static readonly TimeSpan DefaultSettlementTime = new(6, 0, 0);
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for the option security
|
||||
/// </summary>
|
||||
/// <param name="exchangeHours">Defines the hours this exchange is open</param>
|
||||
/// <param name="quoteCurrency">The cash object that represent the quote currency</param>
|
||||
/// <param name="config">The subscription configuration for this security</param>
|
||||
/// <param name="symbolProperties">The symbol properties for this security</param>
|
||||
/// <param name="currencyConverter">Currency converter used to convert <see cref="CashAmount"/>
|
||||
/// instances into units of the account currency</param>
|
||||
/// <param name="registeredTypes">Provides all data types registered in the algorithm</param>
|
||||
/// <param name="priceModelProvider">The option price model provider</param>
|
||||
/// <remarks>Used in testing</remarks>
|
||||
public Option(SecurityExchangeHours exchangeHours,
|
||||
SubscriptionDataConfig config,
|
||||
Cash quoteCurrency,
|
||||
OptionSymbolProperties symbolProperties,
|
||||
ICurrencyConverter currencyConverter,
|
||||
IRegisteredSecurityDataTypesProvider registeredTypes,
|
||||
IOptionPriceModelProvider priceModelProvider = null)
|
||||
: this(config.Symbol,
|
||||
quoteCurrency,
|
||||
symbolProperties,
|
||||
new OptionExchange(exchangeHours),
|
||||
new OptionCache(),
|
||||
new OptionPortfolioModel(),
|
||||
new ImmediateFillModel(),
|
||||
new InteractiveBrokersFeeModel(),
|
||||
NullSlippageModel.Instance,
|
||||
new ImmediateSettlementModel(),
|
||||
Securities.VolatilityModel.Null,
|
||||
new OptionMarginModel(),
|
||||
new OptionDataFilter(),
|
||||
new SecurityPriceVariationModel(),
|
||||
currencyConverter,
|
||||
registeredTypes,
|
||||
null,
|
||||
priceModelProvider)
|
||||
{
|
||||
AddData(config);
|
||||
SetDataNormalizationMode(DataNormalizationMode.Raw);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for the option security
|
||||
/// </summary>
|
||||
/// <param name="symbol">The symbol of the security</param>
|
||||
/// <param name="exchangeHours">Defines the hours this exchange is open</param>
|
||||
/// <param name="quoteCurrency">The cash object that represent the quote currency</param>
|
||||
/// <param name="symbolProperties">The symbol properties for this security</param>
|
||||
/// <param name="currencyConverter">Currency converter used to convert <see cref="CashAmount"/>
|
||||
/// instances into units of the account currency</param>
|
||||
/// <param name="registeredTypes">Provides all data types registered in the algorithm</param>
|
||||
/// <param name="securityCache">Cache to store security information</param>
|
||||
/// <param name="underlying">Future underlying security</param>
|
||||
/// <param name="priceModelProvider">The option price model provider</param>
|
||||
public Option(Symbol symbol,
|
||||
SecurityExchangeHours exchangeHours,
|
||||
Cash quoteCurrency,
|
||||
OptionSymbolProperties symbolProperties,
|
||||
ICurrencyConverter currencyConverter,
|
||||
IRegisteredSecurityDataTypesProvider registeredTypes,
|
||||
SecurityCache securityCache,
|
||||
Security underlying,
|
||||
IOptionPriceModelProvider priceModelProvider = null)
|
||||
: this (symbol,
|
||||
quoteCurrency,
|
||||
symbolProperties,
|
||||
new OptionExchange(exchangeHours),
|
||||
securityCache,
|
||||
new OptionPortfolioModel(),
|
||||
new ImmediateFillModel(),
|
||||
new InteractiveBrokersFeeModel(),
|
||||
NullSlippageModel.Instance,
|
||||
new ImmediateSettlementModel(),
|
||||
Securities.VolatilityModel.Null,
|
||||
new OptionMarginModel(),
|
||||
new OptionDataFilter(),
|
||||
new SecurityPriceVariationModel(),
|
||||
currencyConverter,
|
||||
registeredTypes,
|
||||
underlying,
|
||||
priceModelProvider)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates instance of the Option class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Allows for the forwarding of the security configuration to the
|
||||
/// base Security constructor
|
||||
/// </remarks>
|
||||
protected Option(Symbol symbol,
|
||||
Cash quoteCurrency,
|
||||
SymbolProperties symbolProperties,
|
||||
SecurityExchange exchange,
|
||||
SecurityCache cache,
|
||||
ISecurityPortfolioModel portfolioModel,
|
||||
IFillModel fillModel,
|
||||
IFeeModel feeModel,
|
||||
ISlippageModel slippageModel,
|
||||
ISettlementModel settlementModel,
|
||||
IVolatilityModel volatilityModel,
|
||||
IBuyingPowerModel buyingPowerModel,
|
||||
ISecurityDataFilter dataFilter,
|
||||
IPriceVariationModel priceVariationModel,
|
||||
ICurrencyConverter currencyConverter,
|
||||
IRegisteredSecurityDataTypesProvider registeredTypesProvider,
|
||||
Security underlying,
|
||||
IOptionPriceModelProvider priceModelProvider
|
||||
) : base(
|
||||
symbol,
|
||||
quoteCurrency,
|
||||
symbolProperties,
|
||||
exchange,
|
||||
cache,
|
||||
portfolioModel,
|
||||
fillModel,
|
||||
feeModel,
|
||||
slippageModel,
|
||||
settlementModel,
|
||||
volatilityModel,
|
||||
buyingPowerModel,
|
||||
dataFilter,
|
||||
priceVariationModel,
|
||||
currencyConverter,
|
||||
registeredTypesProvider,
|
||||
Securities.MarginInterestRateModel.Null
|
||||
)
|
||||
{
|
||||
ExerciseSettlement = SettlementType.PhysicalDelivery;
|
||||
SetDataNormalizationMode(DataNormalizationMode.Raw);
|
||||
OptionExerciseModel = new DefaultExerciseModel();
|
||||
PriceModel = (priceModelProvider ?? QLOptionPriceModelProvider.Instance).GetOptionPriceModel(symbol);
|
||||
Holdings = new OptionHolding(this, currencyConverter);
|
||||
_symbolProperties = (OptionSymbolProperties)symbolProperties;
|
||||
SetFilter(-1, 1, TimeSpan.Zero, TimeSpan.FromDays(35));
|
||||
Underlying = underlying;
|
||||
OptionAssignmentModel = new DefaultOptionAssignmentModel();
|
||||
ScaledStrikePrice = StrikePrice * SymbolProperties.StrikeMultiplier;
|
||||
}
|
||||
|
||||
// save off a strongly typed version of symbol properties
|
||||
private readonly OptionSymbolProperties _symbolProperties;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this is the option chain security, false if it is a specific option contract
|
||||
/// </summary>
|
||||
public bool IsOptionChain => Symbol.IsCanonical();
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this is a specific option contract security, false if it is the option chain security
|
||||
/// </summary>
|
||||
public bool IsOptionContract => !Symbol.IsCanonical();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the strike price
|
||||
/// </summary>
|
||||
public decimal StrikePrice => Symbol.ID.StrikePrice;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the strike price multiplied by the strike multiplier
|
||||
/// </summary>
|
||||
public decimal ScaledStrikePrice
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the expiration date
|
||||
/// </summary>
|
||||
public DateTime Expiry => Symbol.ID.Date;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the right being purchased (call [right to buy] or put [right to sell])
|
||||
/// </summary>
|
||||
public OptionRight Right => Symbol.ID.OptionRight;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the option style
|
||||
/// </summary>
|
||||
public OptionStyle Style => Symbol.ID.OptionStyle;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the most recent bid price if available
|
||||
/// </summary>
|
||||
public override decimal BidPrice => Cache.BidPrice;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the most recent ask price if available
|
||||
/// </summary>
|
||||
public override decimal AskPrice => Cache.AskPrice;
|
||||
|
||||
/// <summary>
|
||||
/// When the holder of an equity option exercises one contract, or when the writer of an equity option is assigned
|
||||
/// an exercise notice on one contract, this unit of trade, usually 100 shares of the underlying security, changes hands.
|
||||
/// </summary>
|
||||
public int ContractUnitOfTrade
|
||||
{
|
||||
get
|
||||
{
|
||||
return _symbolProperties.ContractUnitOfTrade;
|
||||
}
|
||||
set
|
||||
{
|
||||
_symbolProperties.SetContractUnitOfTrade(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The contract multiplier for the option security
|
||||
/// </summary>
|
||||
public int ContractMultiplier
|
||||
{
|
||||
get
|
||||
{
|
||||
return (int)_symbolProperties.ContractMultiplier;
|
||||
}
|
||||
set
|
||||
{
|
||||
_symbolProperties.SetContractMultiplier(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aggregate exercise amount or aggregate contract value. It is the total amount of cash one will pay (or receive) for the shares of the
|
||||
/// underlying stock if he/she decides to exercise (or is assigned an exercise notice). This amount is not the premium paid or received for an equity option.
|
||||
/// </summary>
|
||||
public decimal GetAggregateExerciseAmount()
|
||||
{
|
||||
return StrikePrice * ContractMultiplier;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the directional quantity of underlying shares that are going to change hands on exercise/assignment of all
|
||||
/// contracts held by this account, taking into account the contract's <see cref="Right"/> as well as the contract's current
|
||||
/// <see cref="ContractUnitOfTrade"/>, which may have recently changed due to a split/reverse split in the underlying security.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Long option positions result in exercise while short option positions result in assignment. This function uses the term
|
||||
/// exercise loosely to refer to both situations.
|
||||
/// </remarks>
|
||||
public decimal GetExerciseQuantity()
|
||||
{
|
||||
// negate Holdings.Quantity to match an equivalent order
|
||||
return GetExerciseQuantity(-Holdings.Quantity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the directional quantity of underlying shares that are going to change hands on exercise/assignment of the
|
||||
/// specified <paramref name="exerciseOrderQuantity"/>, taking into account the contract's <see cref="Right"/> as well
|
||||
/// as the contract's current <see cref="ContractUnitOfTrade"/>, which may have recently changed due to a split/reverse
|
||||
/// split in the underlying security.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Long option positions result in exercise while short option positions result in assignment. This function uses the term
|
||||
/// exercise loosely to refer to both situations.
|
||||
/// </remarks>
|
||||
/// <paramref name="exerciseOrderQuantity">The quantity of contracts being exercised as provided by the <see cref="OptionExerciseOrder"/>.
|
||||
/// A negative value indicates exercise (we are long and the order quantity is negative to bring us (closer) to zero.
|
||||
/// A positive value indicates assignment (we are short and the order quantity is positive to bring us (closer) to zero.</paramref>
|
||||
public decimal GetExerciseQuantity(decimal exerciseOrderQuantity)
|
||||
{
|
||||
// when exerciseOrderQuantity > 0 [ we are short ]
|
||||
// && right == call => we sell to contract holder => negative
|
||||
// && right == put => we buy from contract holder => positive
|
||||
|
||||
// when exerciseOrderQuantity < 0 [ we are long ]
|
||||
// && right == call => we buy from contract holder => positive
|
||||
// && right == put => we sell to contract holder => negative
|
||||
|
||||
var sign = Right == OptionRight.Call ? -1 : 1;
|
||||
return sign * exerciseOrderQuantity * ContractUnitOfTrade;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if option is eligible for automatic exercise on expiration
|
||||
/// </summary>
|
||||
public bool IsAutoExercised(decimal underlyingPrice)
|
||||
{
|
||||
return GetIntrinsicValue(underlyingPrice) >= 0.01m;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Intrinsic value function of the option
|
||||
/// </summary>
|
||||
public decimal GetIntrinsicValue(decimal underlyingPrice)
|
||||
{
|
||||
return OptionPayoff.GetIntrinsicValue(underlyingPrice, ScaledStrikePrice, Right);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Option payoff function at expiration time
|
||||
/// </summary>
|
||||
/// <param name="underlyingPrice">The price of the underlying</param>
|
||||
/// <returns></returns>
|
||||
public decimal GetPayOff(decimal underlyingPrice)
|
||||
{
|
||||
return OptionPayoff.GetPayOff(underlyingPrice, ScaledStrikePrice, Right);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Option out of the money function
|
||||
/// </summary>
|
||||
/// <param name="underlyingPrice">The price of the underlying</param>
|
||||
/// <returns></returns>
|
||||
public decimal OutOfTheMoneyAmount(decimal underlyingPrice)
|
||||
{
|
||||
return Math.Max(0, Right == OptionRight.Call ? ScaledStrikePrice - underlyingPrice : underlyingPrice - ScaledStrikePrice);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies if option contract has physical or cash settlement on exercise
|
||||
/// </summary>
|
||||
public SettlementType ExerciseSettlement
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the underlying security object.
|
||||
/// </summary>
|
||||
public Security Underlying
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a reduced interface of the underlying security object.
|
||||
/// </summary>
|
||||
ISecurityPrice IOptionPrice.Underlying => Underlying;
|
||||
|
||||
/// <summary>
|
||||
/// For this option security object, evaluates the specified option
|
||||
/// contract to compute a theoretical price, IV and greeks
|
||||
/// </summary>
|
||||
/// <param name="slice">The current data slice. This can be used to access other information
|
||||
/// available to the algorithm</param>
|
||||
/// <param name="contract">The option contract to evaluate</param>
|
||||
/// <returns>An instance of <see cref="OptionPriceModelResult"/> containing the theoretical
|
||||
/// price of the specified option contract</returns>
|
||||
public OptionPriceModelResult EvaluatePriceModel(Slice slice, OptionContract contract)
|
||||
{
|
||||
return PriceModel.Evaluate(new OptionPriceModelParameters(this, slice, contract));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the price model for this option security
|
||||
/// </summary>
|
||||
public IOptionPriceModel PriceModel
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fill model used to produce fill events for this security
|
||||
/// </summary>
|
||||
public IOptionExerciseModel OptionExerciseModel
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The automatic option assignment model
|
||||
/// </summary>
|
||||
public IOptionAssignmentModel OptionAssignmentModel
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When enabled, approximates Greeks if corresponding pricing model didn't calculate exact numbers
|
||||
/// </summary>
|
||||
[Obsolete("This property has been deprecated. Please use QLOptionPriceModel.EnableGreekApproximation instead.")]
|
||||
public bool EnableGreekApproximation
|
||||
{
|
||||
get
|
||||
{
|
||||
var model = PriceModel as QLOptionPriceModel;
|
||||
if (model != null)
|
||||
{
|
||||
return model.EnableGreekApproximation;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
var model = PriceModel as QLOptionPriceModel;
|
||||
if (model != null)
|
||||
{
|
||||
model.EnableGreekApproximation = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the contract filter
|
||||
/// </summary>
|
||||
public IDerivativeSecurityFilter<OptionUniverse> ContractFilter
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the automatic option assignment model
|
||||
/// </summary>
|
||||
/// <param name="pyObject">The option assignment model to use</param>
|
||||
public void SetOptionAssignmentModel(PyObject pyObject)
|
||||
{
|
||||
OptionAssignmentModel = PythonUtil.CreateInstanceOrWrapper<IOptionAssignmentModel>(
|
||||
pyObject,
|
||||
py => new OptionAssignmentModelPythonWrapper(py)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the automatic option assignment model
|
||||
/// </summary>
|
||||
/// <param name="optionAssignmentModel">The option assignment model to use</param>
|
||||
public void SetOptionAssignmentModel(IOptionAssignmentModel optionAssignmentModel)
|
||||
{
|
||||
OptionAssignmentModel = optionAssignmentModel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the option exercise model
|
||||
/// </summary>
|
||||
/// <param name="pyObject">The option exercise model to use</param>
|
||||
public void SetOptionExerciseModel(PyObject pyObject)
|
||||
{
|
||||
OptionExerciseModel = PythonUtil.CreateInstanceOrWrapper<IOptionExerciseModel>(
|
||||
pyObject,
|
||||
py => new OptionExerciseModelPythonWrapper(py)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the option exercise model
|
||||
/// </summary>
|
||||
/// <param name="optionExerciseModel">The option exercise model to use</param>
|
||||
public void SetOptionExerciseModel(IOptionExerciseModel optionExerciseModel)
|
||||
{
|
||||
OptionExerciseModel = optionExerciseModel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ContractFilter"/> to a new instance of the filter
|
||||
/// using the specified min and max strike values. Contracts with expirations further than 35
|
||||
/// days out will also be filtered.
|
||||
/// </summary>
|
||||
/// <param name="minStrike">The min strike rank relative to market price, for example, -1 would put
|
||||
/// a lower bound of one strike under market price, where a +1 would put a lower bound of one strike
|
||||
/// over market price</param>
|
||||
/// <param name="maxStrike">The max strike rank relative to market place, for example, -1 would put
|
||||
/// an upper bound of on strike under market price, where a +1 would be an upper bound of one strike
|
||||
/// over market price</param>
|
||||
public void SetFilter(int minStrike, int maxStrike)
|
||||
{
|
||||
SetFilterImp(universe => universe.Strikes(minStrike, maxStrike));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ContractFilter"/> to a new instance of the filter
|
||||
/// using the specified min and max strike and expiration range values
|
||||
/// </summary>
|
||||
/// <param name="minExpiry">The minimum time until expiry to include, for example, TimeSpan.FromDays(10)
|
||||
/// would exclude contracts expiring in less than 10 days</param>
|
||||
/// <param name="maxExpiry">The maximum time until expiry to include, for example, TimeSpan.FromDays(10)
|
||||
/// would exclude contracts expiring in more than 10 days</param>
|
||||
public void SetFilter(TimeSpan minExpiry, TimeSpan maxExpiry)
|
||||
{
|
||||
SetFilterImp(universe => universe.Expiration(minExpiry, maxExpiry));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ContractFilter"/> to a new instance of the filter
|
||||
/// using the specified min and max strike and expiration range values
|
||||
/// </summary>
|
||||
/// <param name="minStrike">The min strike rank relative to market price, for example, -1 would put
|
||||
/// a lower bound of one strike under market price, where a +1 would put a lower bound of one strike
|
||||
/// over market price</param>
|
||||
/// <param name="maxStrike">The max strike rank relative to market place, for example, -1 would put
|
||||
/// an upper bound of on strike under market price, where a +1 would be an upper bound of one strike
|
||||
/// over market price</param>
|
||||
/// <param name="minExpiry">The minimum time until expiry to include, for example, TimeSpan.FromDays(10)
|
||||
/// would exclude contracts expiring in less than 10 days</param>
|
||||
/// <param name="maxExpiry">The maximum time until expiry to include, for example, TimeSpan.FromDays(10)
|
||||
/// would exclude contracts expiring in more than 10 days</param>
|
||||
public void SetFilter(int minStrike, int maxStrike, TimeSpan minExpiry, TimeSpan maxExpiry)
|
||||
{
|
||||
SetFilterImp(universe => universe
|
||||
.Strikes(minStrike, maxStrike)
|
||||
.Expiration(minExpiry, maxExpiry));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ContractFilter"/> to a new instance of the filter
|
||||
/// using the specified min and max strike and expiration range values
|
||||
/// </summary>
|
||||
/// <param name="minStrike">The min strike rank relative to market price, for example, -1 would put
|
||||
/// a lower bound of one strike under market price, where a +1 would put a lower bound of one strike
|
||||
/// over market price</param>
|
||||
/// <param name="maxStrike">The max strike rank relative to market place, for example, -1 would put
|
||||
/// an upper bound of on strike under market price, where a +1 would be an upper bound of one strike
|
||||
/// over market price</param>
|
||||
/// <param name="minExpiryDays">The minimum time, expressed in days, until expiry to include, for example, 10
|
||||
/// would exclude contracts expiring in less than 10 days</param>
|
||||
/// <param name="maxExpiryDays">The maximum time, expressed in days, until expiry to include, for example, 10
|
||||
/// would exclude contracts expiring in more than 10 days</param>
|
||||
public void SetFilter(int minStrike, int maxStrike, int minExpiryDays, int maxExpiryDays)
|
||||
{
|
||||
SetFilterImp(universe => universe
|
||||
.Strikes(minStrike, maxStrike)
|
||||
.Expiration(minExpiryDays, maxExpiryDays));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ContractFilter"/> to a new universe selection function
|
||||
/// </summary>
|
||||
/// <param name="universeFunc">new universe selection function</param>
|
||||
public void SetFilter(Func<OptionFilterUniverse, OptionFilterUniverse> universeFunc)
|
||||
{
|
||||
ContractFilter = new FuncSecurityDerivativeFilter<OptionUniverse>(universe =>
|
||||
{
|
||||
var optionUniverse = universe as OptionFilterUniverse;
|
||||
//A null result is allowed: filter methods modify the universe in place,
|
||||
//returning it is only necessary for chaining
|
||||
var result = universeFunc(optionUniverse) ?? optionUniverse;
|
||||
return result.ApplyTypesFilter();
|
||||
});
|
||||
ContractFilter.Asynchronous = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ContractFilter"/> to a new universe selection function
|
||||
/// </summary>
|
||||
/// <param name="universeFunc">new universe selection function</param>
|
||||
public void SetFilter(PyObject universeFunc)
|
||||
{
|
||||
ContractFilter = new FuncSecurityDerivativeFilter<OptionUniverse>(universe =>
|
||||
{
|
||||
var optionUniverse = universe as OptionFilterUniverse;
|
||||
using (Py.GIL())
|
||||
{
|
||||
PyObject result = (universeFunc as dynamic)(optionUniverse);
|
||||
|
||||
//Try to convert it to the possible outcomes and process it
|
||||
//Must try filter first, if it is a filter and you try and convert it to
|
||||
//list, TryConvert() with catch an exception. Later Python algo will break on
|
||||
//this exception because we are using Py.GIL() and it will see the error set
|
||||
OptionFilterUniverse filter;
|
||||
List<Symbol> list;
|
||||
|
||||
//A None result is allowed: filter methods modify the universe in place,
|
||||
//returning it is only necessary for chaining
|
||||
if (result == null || result.IsNone())
|
||||
{
|
||||
return optionUniverse.ApplyTypesFilter();
|
||||
}
|
||||
|
||||
if ((result).TryConvert(out filter))
|
||||
{
|
||||
optionUniverse = filter;
|
||||
}
|
||||
else if ((result).TryConvert(out list))
|
||||
{
|
||||
optionUniverse = optionUniverse.WhereContains(list);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"QCAlgorithm.SetFilter: result type {result.GetPythonType()} from " +
|
||||
$"filter function is not a valid argument, please return either a OptionFilterUniverse or a list of symbols");
|
||||
}
|
||||
}
|
||||
return optionUniverse.ApplyTypesFilter();
|
||||
});
|
||||
ContractFilter.Asynchronous = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the data normalization mode to be used by this security
|
||||
/// </summary>
|
||||
public override void SetDataNormalizationMode(DataNormalizationMode mode)
|
||||
{
|
||||
if (mode != DataNormalizationMode.Raw)
|
||||
{
|
||||
throw new ArgumentException("DataNormalizationMode.Raw must be used with options");
|
||||
}
|
||||
|
||||
base.SetDataNormalizationMode(mode);
|
||||
}
|
||||
|
||||
private void SetFilterImp(Func<OptionFilterUniverse, OptionFilterUniverse> universeFunc)
|
||||
{
|
||||
ContractFilter = new FuncSecurityDerivativeFilter<OptionUniverse>(universe =>
|
||||
{
|
||||
var optionUniverse = universe as OptionFilterUniverse;
|
||||
var result = universeFunc(optionUniverse);
|
||||
return result.ApplyTypesFilter();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the option price model
|
||||
/// </summary>
|
||||
/// <param name="pyObject">The option price model to use</param>
|
||||
public void SetPriceModel(PyObject pyObject)
|
||||
{
|
||||
PriceModel = PythonUtil.CreateInstanceOrWrapper<IOptionPriceModel>(
|
||||
pyObject,
|
||||
py => new OptionPriceModelPythonWrapper(py)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the option price model
|
||||
/// </summary>
|
||||
/// <param name="priceModel">The option price model to use</param>
|
||||
public void SetPriceModel(IOptionPriceModel priceModel)
|
||||
{
|
||||
PriceModel = priceModel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the symbol properties of this security
|
||||
/// </summary>
|
||||
internal override void UpdateSymbolProperties(SymbolProperties symbolProperties)
|
||||
{
|
||||
if (symbolProperties != null)
|
||||
{
|
||||
SymbolProperties = new OptionSymbolProperties(symbolProperties);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the securities symbol
|
||||
/// </summary>
|
||||
public static implicit operator Symbol(Option security) => security.Symbol;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user