/* * 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.Collections.Immutable; using System.Linq; using System.Reflection; namespace QuantConnect.Securities.Option.StrategyMatcher { /// /// Provides a listing of pre-defined /// These definitions are blueprints for instances. /// Factory functions for those can be found at /// public static class OptionStrategyDefinitions { // lazy since 'AllDefinitions' is at top of file and static members are evaluated in order private static readonly Lazy> All = new Lazy>(() => typeof(OptionStrategyDefinitions) .GetProperties(BindingFlags.Public | BindingFlags.Static) .Where(property => property.PropertyType == typeof(OptionStrategyDefinition)) .Select(property => (OptionStrategyDefinition)property.GetValue(null)) .ToImmutableList() ); /// /// Collection of all OptionStrategyDefinitions /// public static ImmutableList AllDefinitions { get { var strategies = All.Value; return strategies .SelectMany(optionStrategy => { // when selling the strategy can get reverted and it's still valid, we need the definition to match against var inverted = new OptionStrategyDefinition(optionStrategy.Name, optionStrategy.UnderlyingLots * -1, optionStrategy.Legs.Select(leg => new OptionStrategyLegDefinition(leg.Right, leg.Quantity * -1, leg))); if (strategies.Any(strategy => strategy.UnderlyingLots == inverted.UnderlyingLots && strategy.Legs.Count == inverted.Legs.Count && strategy.Legs.All(leg => inverted.Legs. Any(invertedLeg => invertedLeg.Right == leg.Right && leg.Quantity == invertedLeg.Quantity && leg.All(predicate => invertedLeg.Any(invertedPredicate => invertedPredicate.ToString() == predicate.ToString())))))) { // some strategies inverted have a different name we already know, let's skip those return new[] { optionStrategy }; } return new[] { optionStrategy, inverted }; }) .ToImmutableList(); } } /// /// Hold 1 lot of the underlying and sell 1 call contract /// /// Inverse of the public static OptionStrategyDefinition CoveredCall { get; } = OptionStrategyDefinition.Create("Covered Call", 1, OptionStrategyDefinition.CallLeg(-1) ); /// /// Hold -1 lot of the underlying and buy 1 call contract /// /// Inverse of the public static OptionStrategyDefinition ProtectiveCall { get; } = OptionStrategyDefinition.Create("Protective Call", -1, OptionStrategyDefinition.CallLeg(1) ); /// /// Hold -1 lot of the underlying and sell 1 put contract /// /// Inverse of the public static OptionStrategyDefinition CoveredPut { get; } = OptionStrategyDefinition.Create("Covered Put", -1, OptionStrategyDefinition.PutLeg(-1) ); /// /// Hold 1 lot of the underlying and buy 1 put contract /// /// Inverse of the public static OptionStrategyDefinition ProtectivePut { get; } = OptionStrategyDefinition.Create("Protective Put", 1, OptionStrategyDefinition.PutLeg(1) ); /// /// Hold 1 lot of the underlying, sell 1 call contract and buy 1 put contract. /// The strike price of the short call is below the strike of the long put with the same expiration. /// /// Combination of and public static OptionStrategyDefinition ProtectiveCollar { get; } = OptionStrategyDefinition.Create("Protective Collar", 1, OptionStrategyDefinition.CallLeg(-1), OptionStrategyDefinition.PutLeg(1, (legs, p) => p.Strike < legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration) ); /// /// Hold 1 lot of the underlying, sell 1 call contract and buy 1 put contract. /// The strike price of the call and put are the same, with the same expiration. /// /// A special case of public static OptionStrategyDefinition Conversion { get; } = OptionStrategyDefinition.Create("Conversion", 1, OptionStrategyDefinition.CallLeg(-1), OptionStrategyDefinition.PutLeg(1, (legs, p) => p.Strike == legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration) ); /// /// Hold 1 lot of the underlying, sell 1 call contract and buy 1 put contract. /// The strike price of the call and put are the same, with the same expiration. /// /// Inverse of public static OptionStrategyDefinition ReverseConversion { get; } = OptionStrategyDefinition.Create("Reverse Conversion", -1, OptionStrategyDefinition.CallLeg(1), OptionStrategyDefinition.PutLeg(-1, (legs, p) => p.Strike == legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration) ); /// /// Sell 1 call contract without holding the underlying /// public static OptionStrategyDefinition NakedCall { get; } = OptionStrategyDefinition.Create("Naked Call", OptionStrategyDefinition.CallLeg(-1) ); /// /// Sell 1 put contract without holding the underlying /// public static OptionStrategyDefinition NakedPut { get; } = OptionStrategyDefinition.Create("Naked Put", OptionStrategyDefinition.PutLeg(-1) ); /// /// Bear Call Spread strategy consists of two calls with the same expiration but different strikes. /// The strike price of the short call is below the strike of the long call. This is a credit spread. /// public static OptionStrategyDefinition BearCallSpread { get; } = OptionStrategyDefinition.Create("Bear Call Spread", OptionStrategyDefinition.CallLeg(-1), OptionStrategyDefinition.CallLeg(+1, (legs, p) => p.Strike > legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration) ); /// /// Bear Put Spread strategy consists of two puts with the same expiration but different strikes. /// The strike price of the short put is below the strike of the long put. This is a debit spread. /// public static OptionStrategyDefinition BearPutSpread { get; } = OptionStrategyDefinition.Create("Bear Put Spread", OptionStrategyDefinition.PutLeg(1), OptionStrategyDefinition.PutLeg(-1, (legs, p) => p.Strike < legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration) ); /// /// Bull Call Spread strategy consists of two calls with the same expiration but different strikes. /// The strike price of the short call is higher than the strike of the long call. This is a debit spread. /// public static OptionStrategyDefinition BullCallSpread { get; } = OptionStrategyDefinition.Create("Bull Call Spread", OptionStrategyDefinition.CallLeg(+1), OptionStrategyDefinition.CallLeg(-1, (legs, p) => p.Strike > legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration) ); /// /// Method creates new Bull Put Spread strategy, that consists of two puts with the same expiration but /// different strikes. The strike price of the short put is above the strike of the long put. This is a /// credit spread. /// public static OptionStrategyDefinition BullPutSpread { get; } = OptionStrategyDefinition.Create("Bull Put Spread", OptionStrategyDefinition.PutLeg(-1), OptionStrategyDefinition.PutLeg(+1, (legs, p) => p.Strike < legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration) ); /// /// Straddle strategy is a combination of buying a call and buying a put, both with the same strike price /// and expiration. /// public static OptionStrategyDefinition Straddle { get; } = OptionStrategyDefinition.Create("Straddle", OptionStrategyDefinition.CallLeg(+1), OptionStrategyDefinition.PutLeg(+1, (legs, p) => p.Strike == legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration) ); /// /// Short Straddle strategy is a combination of selling a call and selling a put, both with the same strike price /// and expiration. /// /// Inverse of the public static OptionStrategyDefinition ShortStraddle { get; } = OptionStrategyDefinition.Create("Short Straddle", OptionStrategyDefinition.CallLeg(-1), OptionStrategyDefinition.PutLeg(-1, (legs, p) => p.Strike == legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration) ); /// /// Strangle strategy consists of buying a call option and a put option with the same expiration date. /// The strike price of the call is above the strike of the put. /// public static OptionStrategyDefinition Strangle { get; } = OptionStrategyDefinition.Create("Strangle", OptionStrategyDefinition.CallLeg(+1), OptionStrategyDefinition.PutLeg(+1, (legs, p) => p.Strike < legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration) ); /// /// Strangle strategy consists of selling a call option and a put option with the same expiration date. /// The strike price of the call is above the strike of the put. /// /// Inverse of the public static OptionStrategyDefinition ShortStrangle { get; } = OptionStrategyDefinition.Create("Short Strangle", OptionStrategyDefinition.CallLeg(-1), OptionStrategyDefinition.PutLeg(-1, (legs, p) => p.Strike < legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration) ); /// /// Short Butterfly Call strategy consists of two short calls at a middle strike, and one long call each at a lower /// and upper strike. The upper and lower strikes must both be equidistant from the middle strike. /// public static OptionStrategyDefinition ButterflyCall { get; } = OptionStrategyDefinition.Create("Butterfly Call", OptionStrategyDefinition.CallLeg(+1), OptionStrategyDefinition.CallLeg(-2, (legs, p) => p.Strike >= legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration), OptionStrategyDefinition.CallLeg(+1, (legs, p) => p.Strike >= legs[1].Strike, (legs, p) => p.Expiration == legs[0].Expiration, (legs, p) => p.Strike - legs[1].Strike == legs[1].Strike - legs[0].Strike) ); /// /// Butterfly Call strategy consists of two long calls at a middle strike, and one short call each at a lower /// and upper strike. The upper and lower strikes must both be equidistant from the middle strike. /// public static OptionStrategyDefinition ShortButterflyCall { get; } = OptionStrategyDefinition.Create("Short Butterfly Call", OptionStrategyDefinition.CallLeg(-1), OptionStrategyDefinition.CallLeg(+2, (legs, p) => p.Strike >= legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration), OptionStrategyDefinition.CallLeg(-1, (legs, p) => p.Strike >= legs[1].Strike, (legs, p) => p.Expiration == legs[0].Expiration, (legs, p) => p.Strike - legs[1].Strike == legs[1].Strike - legs[0].Strike) ); /// /// Butterfly Put strategy consists of two short puts at a middle strike, and one long put each at a lower and /// upper strike. The upper and lower strikes must both be equidistant from the middle strike. /// public static OptionStrategyDefinition ButterflyPut { get; } = OptionStrategyDefinition.Create("Butterfly Put", OptionStrategyDefinition.PutLeg(+1), OptionStrategyDefinition.PutLeg(-2, (legs, p) => p.Strike >= legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration), OptionStrategyDefinition.PutLeg(+1, (legs, p) => p.Strike >= legs[1].Strike, (legs, p) => p.Expiration == legs[0].Expiration, (legs, p) => p.Strike - legs[1].Strike == legs[1].Strike - legs[0].Strike) ); /// /// Short Butterfly Put strategy consists of two long puts at a middle strike, and one short put each at a lower and /// upper strike. The upper and lower strikes must both be equidistant from the middle strike. /// public static OptionStrategyDefinition ShortButterflyPut { get; } = OptionStrategyDefinition.Create("Short Butterfly Put", OptionStrategyDefinition.PutLeg(-1), OptionStrategyDefinition.PutLeg(+2, (legs, p) => p.Strike >= legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration), OptionStrategyDefinition.PutLeg(-1, (legs, p) => p.Strike >= legs[1].Strike, (legs, p) => p.Expiration == legs[0].Expiration, (legs, p) => p.Strike - legs[1].Strike == legs[1].Strike - legs[0].Strike) ); /// /// Call Calendar Spread strategy is a short one call option and long a second call option with a more distant /// expiration. /// public static OptionStrategyDefinition CallCalendarSpread { get; } = OptionStrategyDefinition.Create("Call Calendar Spread", OptionStrategyDefinition.CallLeg(-1), OptionStrategyDefinition.CallLeg(+1, (legs, p) => p.Strike == legs[0].Strike, (legs, p) => p.Expiration > legs[0].Expiration) ); /// /// Short Call Calendar Spread strategy is long one call option and short a second call option with a more distant /// expiration. /// /// Inverse of the public static OptionStrategyDefinition ShortCallCalendarSpread { get; } = OptionStrategyDefinition.Create("Short Call Calendar Spread", OptionStrategyDefinition.CallLeg(+1), OptionStrategyDefinition.CallLeg(-1, (legs, p) => p.Strike == legs[0].Strike, (legs, p) => p.Expiration > legs[0].Expiration) ); /// /// Put Calendar Spread strategy is a short one put option and long a second put option with a more distant /// expiration. /// public static OptionStrategyDefinition PutCalendarSpread { get; } = OptionStrategyDefinition.Create("Put Calendar Spread", OptionStrategyDefinition.PutLeg(-1), OptionStrategyDefinition.PutLeg(+1, (legs, p) => p.Strike == legs[0].Strike, (legs, p) => p.Expiration > legs[0].Expiration) ); /// /// Short Put Calendar Spread strategy is long one put option and short a second put option with a more distant /// expiration. /// /// Inverse of the public static OptionStrategyDefinition ShortPutCalendarSpread { get; } = OptionStrategyDefinition.Create("Short Put Calendar Spread", OptionStrategyDefinition.PutLeg(+1), OptionStrategyDefinition.PutLeg(-1, (legs, p) => p.Strike == legs[0].Strike, (legs, p) => p.Expiration > legs[0].Expiration) ); /// /// Iron Butterfly strategy consists of a short ATM call, a short ATM put, a long OTM call, and a long OTM put. /// The strike spread between ATM and OTM call and put are the same. All at the same expiration date. /// public static OptionStrategyDefinition IronButterfly { get; } = OptionStrategyDefinition.Create("Iron Butterfly", OptionStrategyDefinition.PutLeg(-1), OptionStrategyDefinition.PutLeg(+1, (legs, p) => p.Strike < legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration), OptionStrategyDefinition.CallLeg(-1, (legs, c) => c.Strike == legs[0].Strike, (legs, c) => c.Expiration == legs[0].Expiration), OptionStrategyDefinition.CallLeg(+1, (legs, c) => c.Strike == legs[0].Strike * 2 - legs[1].Strike, (legs, c) => c.Expiration == legs[0].Expiration) ); /// /// Short Iron Butterfly strategy consists of a long ATM call, a long ATM put, a short OTM call, and a short OTM put. /// The strike spread between ATM and OTM call and put are the same. All at the same expiration date. /// public static OptionStrategyDefinition ShortIronButterfly { get; } = OptionStrategyDefinition.Create("Short Iron Butterfly", OptionStrategyDefinition.PutLeg(+1), OptionStrategyDefinition.PutLeg(-1, (legs, p) => p.Strike < legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration), OptionStrategyDefinition.CallLeg(+1, (legs, c) => c.Strike == legs[0].Strike, (legs, c) => c.Expiration == legs[0].Expiration), OptionStrategyDefinition.CallLeg(-1, (legs, c) => c.Strike == legs[0].Strike * 2 - legs[1].Strike, (legs, c) => c.Expiration == legs[0].Expiration) ); /// /// Iron Condor strategy is buying a put, selling a put with a higher strike price, selling a call and buying a call with a higher strike price. /// All at the same expiration date /// public static OptionStrategyDefinition IronCondor { get; } = OptionStrategyDefinition.Create("Iron Condor", OptionStrategyDefinition.PutLeg(+1), OptionStrategyDefinition.PutLeg(-1, (legs, p) => p.Strike > legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration), OptionStrategyDefinition.CallLeg(-1, (legs, p) => p.Strike > legs[1].Strike, (legs, p) => p.Expiration == legs[0].Expiration), OptionStrategyDefinition.CallLeg(1, (legs, p) => p.Strike > legs[2].Strike, (legs, p) => p.Expiration == legs[0].Expiration) ); /// /// Short Iron Condor strategy is selling a put, buying a put with a higher strike price, buying a call and selling a call with a higher strike price. /// All at the same expiration date /// public static OptionStrategyDefinition ShortIronCondor { get; } = OptionStrategyDefinition.Create("Short Iron Condor", OptionStrategyDefinition.PutLeg(-1), OptionStrategyDefinition.PutLeg(+1, (legs, p) => p.Strike > legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration), OptionStrategyDefinition.CallLeg(+1, (legs, p) => p.Strike > legs[1].Strike, (legs, p) => p.Expiration == legs[0].Expiration), OptionStrategyDefinition.CallLeg(-1, (legs, p) => p.Strike > legs[2].Strike, (legs, p) => p.Expiration == legs[0].Expiration) ); /// /// Long Box Spread strategy is long 1 call and short 1 put with the same strike, /// while short 1 call and long 1 put with a higher, same strike. All options have the same expiry. /// expiration. /// public static OptionStrategyDefinition BoxSpread { get; } = OptionStrategyDefinition.Create("Box Spread", OptionStrategyDefinition.PutLeg(+1), OptionStrategyDefinition.PutLeg(-1, (legs, p) => p.Strike < legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration), OptionStrategyDefinition.CallLeg(+1, (legs, c) => c.Strike == legs[1].Strike, (legs, c) => c.Expiration == legs[0].Expiration), OptionStrategyDefinition.CallLeg(-1, (legs, c) => c.Strike == legs[0].Strike, (legs, c) => c.Expiration == legs[0].Expiration) ); /// /// Short Box Spread strategy is short 1 call and long 1 put with the same strike, /// while long 1 call and short 1 put with a higher, same strike. All options have the same expiry. /// expiration. /// public static OptionStrategyDefinition ShortBoxSpread { get; } = OptionStrategyDefinition.Create("Short Box Spread", OptionStrategyDefinition.PutLeg(-1), OptionStrategyDefinition.PutLeg(+1, (legs, p) => p.Strike < legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration), OptionStrategyDefinition.CallLeg(-1, (legs, c) => c.Strike == legs[1].Strike, (legs, c) => c.Expiration == legs[0].Expiration), OptionStrategyDefinition.CallLeg(+1, (legs, c) => c.Strike == legs[0].Strike, (legs, c) => c.Expiration == legs[0].Expiration) ); /// /// Jelly Roll is short 1 call and long 1 call with the same strike but further expiry, together with /// long 1 put and short 1 put with the same strike and expiries as calls. /// public static OptionStrategyDefinition JellyRoll { get; } = OptionStrategyDefinition.Create("Jelly Roll", OptionStrategyDefinition.CallLeg(-1), OptionStrategyDefinition.CallLeg(+1, (legs, c) => c.Strike == legs[0].Strike, (legs, c) => c.Expiration > legs[0].Expiration), OptionStrategyDefinition.PutLeg(+1, (legs, p) => p.Strike == legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration), OptionStrategyDefinition.PutLeg(-1, (legs, p) => p.Strike == legs[0].Strike, (legs, p) => p.Expiration == legs[1].Expiration) ); /// /// Short Jelly Roll is long 1 call and short 1 call with the same strike but further expiry, together with /// short 1 put and long 1 put with the same strike and expiries as calls. /// public static OptionStrategyDefinition ShortJellyRoll { get; } = OptionStrategyDefinition.Create("Short Jelly Roll", OptionStrategyDefinition.CallLeg(+1), OptionStrategyDefinition.CallLeg(-1, (legs, c) => c.Strike == legs[0].Strike, (legs, c) => c.Expiration > legs[0].Expiration), OptionStrategyDefinition.PutLeg(-1, (legs, p) => p.Strike == legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration), OptionStrategyDefinition.PutLeg(+1, (legs, p) => p.Strike == legs[0].Strike, (legs, p) => p.Expiration == legs[1].Expiration) ); /// /// Bear Call Ladder strategy is short 1 call and long 2 calls, with ascending strike prices in order, /// All options have the same expiry. /// public static OptionStrategyDefinition BearCallLadder { get; } = OptionStrategyDefinition.Create("Bear Call Ladder", OptionStrategyDefinition.CallLeg(-1), OptionStrategyDefinition.CallLeg(+1, (legs, c) => c.Strike > legs[0].Strike, (legs, c) => c.Expiration == legs[0].Expiration), OptionStrategyDefinition.CallLeg(+1, (legs, c) => c.Strike > legs[1].Strike, (legs, c) => c.Expiration == legs[0].Expiration) ); /// /// Bear Put Ladder strategy is long 1 put and short 2 puts, with descending strike prices in order, /// All options have the same expiry. /// public static OptionStrategyDefinition BearPutLadder { get; } = OptionStrategyDefinition.Create("Bear Put Ladder", OptionStrategyDefinition.PutLeg(+1), OptionStrategyDefinition.PutLeg(-1, (legs, p) => p.Strike < legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration), OptionStrategyDefinition.PutLeg(-1, (legs, p) => p.Strike < legs[1].Strike, (legs, p) => p.Expiration == legs[0].Expiration) ); /// /// Bull Call Ladder strategy is long 1 call and short 2 calls, with ascending strike prices in order, /// All options have the same expiry. /// public static OptionStrategyDefinition BullCallLadder { get; } = OptionStrategyDefinition.Create("Bull Call Ladder", OptionStrategyDefinition.CallLeg(+1), OptionStrategyDefinition.CallLeg(-1, (legs, c) => c.Strike > legs[0].Strike, (legs, c) => c.Expiration == legs[0].Expiration), OptionStrategyDefinition.CallLeg(-1, (legs, c) => c.Strike > legs[1].Strike, (legs, c) => c.Expiration == legs[0].Expiration) ); /// /// Bull Put Ladder strategy is short 1 put and long 2 puts, with descending strike prices in order, /// All options have the same expiry. /// public static OptionStrategyDefinition BullPutLadder { get; } = OptionStrategyDefinition.Create("Bull Put Ladder", OptionStrategyDefinition.PutLeg(-1), OptionStrategyDefinition.PutLeg(+1, (legs, p) => p.Strike < legs[0].Strike, (legs, p) => p.Expiration == legs[0].Expiration), OptionStrategyDefinition.PutLeg(+1, (legs, p) => p.Strike < legs[1].Strike, (legs, p) => p.Expiration == legs[0].Expiration) ); } }