Options Models
Assignment
Introduction
If you sell an Option in a backtest, an assignment model can simulate an Option exercise order on behalf of the buyer and assign you to complete the requirements of the contract.
Set Models
To set the assignment model of an Option, call the SetOptionAssignmentModel
set_option_assignment_model
method of the Option
object inside a security initializer.
public class BrokerageModelExampleAlgorithm : QCAlgorithm { public override void Initialize() { // In the Initialize method, set the security initializer to seed initial the prices and models of assets. SetSecurityInitializer(new MySecurityInitializer(BrokerageModel, new FuncSecuritySeeder(GetLastKnownPrices))); } } public class MySecurityInitializer : BrokerageModelSecurityInitializer { public MySecurityInitializer(IBrokerageModel brokerageModel, ISecuritySeeder securitySeeder) : base(brokerageModel, securitySeeder) {} public override void Initialize(Security security) { // First, call the superclass definition. // This method sets the reality models of each security using the default reality models of the brokerage model. base.Initialize(security); // Next, overwrite the assignment model if (security.Type == SecurityType.Option) // Option type { (security as Option).SetOptionAssignmentModel(new DefaultOptionAssignmentModel()); } } }
class BrokerageModelExampleAlgorithm(QCAlgorithm): def initialize(self) -> None: # In the Initialize method, set the security initializer to seed initial the prices and models of assets. self.set_security_initializer(MySecurityInitializer(self.brokerage_model, FuncSecuritySeeder(self.get_last_known_prices))) # Outside of the algorithm class class MySecurityInitializer(BrokerageModelSecurityInitializer): def __init__(self, brokerage_model: IBrokerageModel, security_seeder: ISecuritySeeder) -> None: super().__init__(brokerage_model, security_seeder) def initialize(self, security: Security) -> None: # First, call the superclass definition. # This method sets the reality models of each security using the default reality models of the brokerage model. super().initialize(security) # Next, overwrite the assignment model if security.Type == SecurityType.OPTION: # Option type security.set_option_assignment_model(DefaultOptionAssignmentModel())
Default Behavior
The default Option assignment model is the DefaultOptionAssignmentModel
. The DefaultOptionAssignmentModel
scans your portfolio every hour. It considers exercising American-style Options if they are within 4 days of their expiration and it considers exercising European-style Options on their day of expiration. If you have sold an Option that's 5% in-the-money and the Option exercise order is profitable after the cost of fees, this model exercises the Option.
To view the implementation of this model, see the LEAN GitHub repository.
Model Structure
Option assignment models should implement the IOptionAssignmentModel
interface. Extensions of the IOptionAssignmentModel
interface must implement the GetAssignment
get_assignment
method, which automatically fires at the top of each hour and returns the Option assignments to generate.
Option assignment models should extend the NullOptionAssignmentModel
class. Extensions of the NullOptionAssignmentModel
class must implement the GetAssignment
get_assignment
method, which automatically fires at the top of each hour and returns the Option assignments to generate.
public class CustomOptionAssignmentModelExampleAlgorithm : QCAlgorithm { public override void Initialize() { var security = AddOption("SPY"); // Set custom option assignment model for mimicking specific Brokerage most realistic actions (security as Option).SetOptionAssignmentModel(new MyOptionAssignmentModel()); } } // Define the custom Option assignment model outside of the algorithm public class MyOptionAssignmentModel : IOptionAssignmentModel { public OptionAssignmentResult GetAssignment(OptionAssignmentParameters parameters) { var option = parameters.Option; // Check if the contract is ITM if ((option.Right == OptionRight.Call && option.Underlying.Price > option.StrikePrice) || (option.Right == OptionRight.Put && option.Underlying.Price < option.StrikePrice)) { return new OptionAssignmentResult(option.Holdings.AbsoluteQuantity, "MyTag"); } return OptionAssignmentResult.Null; } }
class CustomOptionAssignmentModelExampleAlgorithm(QCAlgorithm): def initialize(self) -> None: security = self.add_option("SPY") # Set custom option assignment model for mimicking specific Brokerage most realistic actions security.set_option_assignment_model(MyOptionAssignmentModel()) # Define the custom Option assignment model outside of the algorithm class MyOptionAssignmentModel(NullOptionAssignmentModel): def get_assignment(self, parameters: OptionAssignmentParameters) -> OptionAssignmentResult: option = parameters.option # Check if the contract is ITM if option.right == OptionRight.CALL and option.underlying.price > option.strike_price or option.right == OptionRight.PUT and option.underlying.price < option.strike_price: return OptionAssignmentResult(option.holdings.absolute_quantity, "MyTag") return OptionAssignmentResult.NULL
For a full example algorithm, see this backtestthis backtest.
The OptionAssignmentParameters
object has the following members:
To exercise the Option, return an OptionAssignmentResult
with a positive quantity. Otherwise, return OptionAssignmentResult.Null
. The OptionAssignmentResult
constructor accepts the following arguments:
Argument | Data Type | Description | Default Value |
---|---|---|---|
quantity | decimal float | The quantity to assign | |
tag | string str | The order tag to use |