/*
* 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)
);
}
}