Lean  $LEAN_TAG$
OptionStrategies.cs
1 /*
2  * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3  * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 */
15 
16 using System;
17 using System.Collections.Generic;
18 using System.Linq;
20 
22 {
23  /// <summary>
24  /// Provides methods for creating popular <see cref="OptionStrategy"/> instances.
25  /// These strategies can be directly bought and sold via:
26  /// QCAlgorithm.Buy(OptionStrategy strategy, int quantity)
27  /// QCAlgorithm.Sell(OptionStrategy strategy, int quantity)
28  ///
29  /// See also <see cref="OptionStrategyDefinitions"/>
30  /// </summary>
31  public static class OptionStrategies
32  {
33  /// <summary>
34  /// Symbol properties database to use to get contract multipliers
35  /// </summary>
36  private static SymbolPropertiesDatabase _symbolPropertiesDatabase = SymbolPropertiesDatabase.FromDataFolder();
37 
38  /// <summary>
39  /// Creates a Covered Call strategy that consists of selling one call contract and buying 1 lot of the underlying.
40  /// </summary>
41  /// <param name="canonicalOption">Option symbol</param>
42  /// <param name="strike">The strike price for the call option contract</param>
43  /// <param name="expiration">The expiration date for the call option contract</param>
44  /// <returns>Option strategy specification</returns>
45  public static OptionStrategy CoveredCall(Symbol canonicalOption, decimal strike, DateTime expiration)
46  {
47  CheckCanonicalOptionSymbol(canonicalOption, "CoveredCall");
48  CheckExpirationDate(expiration, "CoveredCall", nameof(expiration));
49 
50  var underlyingQuantity = (int)_symbolPropertiesDatabase.GetSymbolProperties(canonicalOption.ID.Market, canonicalOption,
51  canonicalOption.SecurityType, "").ContractMultiplier;
52 
53  return new OptionStrategy
54  {
56  Underlying = canonicalOption.Underlying,
57  CanonicalOption = canonicalOption,
58  OptionLegs = new List<OptionStrategy.OptionLegData>
59  {
61  {
62  Right = OptionRight.Call, Strike = strike, Quantity = -1, Expiration = expiration
63  }
64  },
65  UnderlyingLegs = new List<OptionStrategy.UnderlyingLegData>
66  {
68  {
69  Quantity = underlyingQuantity, Symbol = canonicalOption.Underlying
70  }
71  }
72  };
73  }
74 
75  /// <summary>
76  /// Creates a Protective Call strategy that consists of buying one call contract and selling 1 lot of the underlying.
77  /// </summary>
78  /// <param name="canonicalOption">Option symbol</param>
79  /// <param name="strike">The strike price for the call option contract</param>
80  /// <param name="expiration">The expiration date for the call option contract</param>
81  /// <returns>Option strategy specification</returns>
82  public static OptionStrategy ProtectiveCall(Symbol canonicalOption, decimal strike, DateTime expiration)
83  {
84  // Since a protective call is an inverted covered call, we can just use the CoveredCall method and invert the legs
85  return InvertStrategy(CoveredCall(canonicalOption, strike, expiration), OptionStrategyDefinitions.ProtectiveCall.Name);
86  }
87 
88  /// <summary>
89  /// Creates a Covered Put strategy that consists of selling 1 put contract and 1 lot of the underlying.
90  /// </summary>
91  /// <param name="canonicalOption">Option symbol</param>
92  /// <param name="strike">The strike price for the put option contract</param>
93  /// <param name="expiration">The expiration date for the put option contract</param>
94  /// <returns>Option strategy specification</returns>
95  public static OptionStrategy CoveredPut(Symbol canonicalOption, decimal strike, DateTime expiration)
96  {
97  CheckCanonicalOptionSymbol(canonicalOption, "CoveredPut");
98  CheckExpirationDate(expiration, "CoveredPut", nameof(expiration));
99 
100  var underlyingQuantity = -(int)_symbolPropertiesDatabase.GetSymbolProperties(canonicalOption.ID.Market, canonicalOption,
101  canonicalOption.SecurityType, "").ContractMultiplier;
102 
103  return new OptionStrategy
104  {
106  Underlying = canonicalOption.Underlying,
107  CanonicalOption = canonicalOption,
108  OptionLegs = new List<OptionStrategy.OptionLegData>
109  {
111  {
112  Right = OptionRight.Put, Strike = strike, Quantity = -1, Expiration = expiration
113  }
114  },
115  UnderlyingLegs = new List<OptionStrategy.UnderlyingLegData>
116  {
118  {
119  Quantity = underlyingQuantity, Symbol = canonicalOption.Underlying
120  }
121  }
122  };
123  }
124 
125  /// <summary>
126  /// Creates a Protective Put strategy that consists of buying 1 put contract and 1 lot of the underlying.
127  /// </summary>
128  /// <param name="canonicalOption">Option symbol</param>
129  /// <param name="strike">The strike price for the put option contract</param>
130  /// <param name="expiration">The expiration date for the put option contract</param>
131  /// <returns>Option strategy specification</returns>
132  public static OptionStrategy ProtectivePut(Symbol canonicalOption, decimal strike, DateTime expiration)
133  {
134  // Since a protective put is an inverted covered put, we can just use the CoveredPut method and invert the legs
135  return InvertStrategy(CoveredPut(canonicalOption, strike, expiration), OptionStrategyDefinitions.ProtectivePut.Name);
136  }
137 
138  /// <summary>
139  /// Creates a Protective Collar strategy that consists of buying 1 put contract and 1 lot of the underlying.
140  /// </summary>
141  /// <param name="canonicalOption">Option symbol</param>
142  /// <param name="callStrike">The strike price for the call option contract</param>
143  /// <param name="putStrike">The strike price for the put option contract</param>
144  /// <param name="expiration">Option expiration date</param>
145  /// <returns>Option strategy specification</returns>
146  public static OptionStrategy ProtectiveCollar(Symbol canonicalOption, decimal callStrike, decimal putStrike, DateTime expiration)
147  {
148  if (callStrike < putStrike)
149  {
150  throw new ArgumentException("ProtectiveCollar: callStrike must be greater than putStrike", $"{nameof(callStrike)}, {nameof(putStrike)}");
151  }
152 
153  // Since a protective collar is a combination of protective put and covered call
154  var coveredCall = CoveredCall(canonicalOption, callStrike, expiration);
155  var protectivePut = ProtectivePut(canonicalOption, putStrike, expiration);
156 
157  return new OptionStrategy
158  {
160  Underlying = canonicalOption.Underlying,
161  CanonicalOption = canonicalOption,
162  OptionLegs = coveredCall.OptionLegs.Concat(protectivePut.OptionLegs).ToList(),
163  UnderlyingLegs = coveredCall.UnderlyingLegs // only 1 lot of long stock position
164  };
165  }
166 
167  /// <summary>
168  /// Creates a Conversion strategy that consists of buying 1 put contract, 1 lot of the underlying and selling 1 call contract.
169  /// Put and call must have the same expiration date, underlying (multiplier), and strike price.
170  /// </summary>
171  /// <param name="canonicalOption">Option symbol</param>
172  /// <param name="strike">The strike price for the call and put option contract</param>
173  /// <param name="expiration">Option expiration date</param>
174  /// <returns>Option strategy specification</returns>
175  public static OptionStrategy Conversion(Symbol canonicalOption, decimal strike, DateTime expiration)
176  {
177  var strategy = ProtectiveCollar(canonicalOption, strike, strike, expiration);
178  strategy.Name = OptionStrategyDefinitions.Conversion.Name;
179  return strategy;
180  }
181 
182  /// <summary>
183  /// Creates a Reverse Conversion strategy that consists of buying 1 put contract and 1 lot of the underlying.
184  /// </summary>
185  /// <param name="canonicalOption">Option symbol</param>
186  /// <param name="strike">The strike price for the put option contract</param>
187  /// <param name="expiration">Option expiration date</param>
188  /// <returns>Option strategy specification</returns>
189  public static OptionStrategy ReverseConversion(Symbol canonicalOption, decimal strike, DateTime expiration)
190  {
191  // Since a reverse conversion is an inverted conversion, we can just use the Conversion method and invert the legs
192  return InvertStrategy(Conversion(canonicalOption, strike, expiration), OptionStrategyDefinitions.ReverseConversion.Name);
193  }
194 
195  /// <summary>
196  /// Creates a Naked Call strategy that consists of selling 1 call contract.
197  /// </summary>
198  /// <param name="canonicalOption">Option symbol</param>
199  /// <param name="strike">The strike price for the call option contract</param>
200  /// <param name="expiration">The expiration date for the call option contract</param>
201  /// <returns>Option strategy specification</returns>
202  public static OptionStrategy NakedCall(Symbol canonicalOption, decimal strike, DateTime expiration)
203  {
204  CheckCanonicalOptionSymbol(canonicalOption, "NakedCall");
205  CheckExpirationDate(expiration, "NakedCall", nameof(expiration));
206 
207  return new OptionStrategy
208  {
210  Underlying = canonicalOption.Underlying,
211  CanonicalOption = canonicalOption,
212  OptionLegs = new List<OptionStrategy.OptionLegData>
213  {
215  {
216  Right = OptionRight.Call, Strike = strike, Quantity = -1, Expiration = expiration
217  }
218  }
219  };
220  }
221 
222  /// <summary>
223  /// Creates a Naked Put strategy that consists of selling 1 put contract.
224  /// </summary>
225  /// <param name="canonicalOption">Option symbol</param>
226  /// <param name="strike">The strike price for the put option contract</param>
227  /// <param name="expiration">The expiration date for the put option contract</param>
228  /// <returns>Option strategy specification</returns>
229  public static OptionStrategy NakedPut(Symbol canonicalOption, decimal strike, DateTime expiration)
230  {
231  CheckCanonicalOptionSymbol(canonicalOption, "NakedPut");
232  CheckExpirationDate(expiration, "NakedPut", nameof(expiration));
233 
234  return new OptionStrategy
235  {
237  Underlying = canonicalOption.Underlying,
238  CanonicalOption = canonicalOption,
239  OptionLegs = new List<OptionStrategy.OptionLegData>
240  {
242  {
243  Right = OptionRight.Put, Strike = strike, Quantity = -1, Expiration = expiration
244  }
245  }
246  };
247  }
248 
249  /// <summary>
250  /// Method creates new Bear Call Spread strategy, that consists of two calls with the same expiration but different strikes.
251  /// The strike price of the short call is below the strike of the long call. This is a credit spread.
252  /// </summary>
253  /// <param name="canonicalOption">Option symbol</param>
254  /// <param name="leg1Strike">The strike price of the short call</param>
255  /// <param name="leg2Strike">The strike price of the long call</param>
256  /// <param name="expiration">Option expiration date</param>
257  /// <returns>Option strategy specification</returns>
259  Symbol canonicalOption,
260  decimal leg1Strike,
261  decimal leg2Strike,
262  DateTime expiration
263  )
264  {
265  CheckCanonicalOptionSymbol(canonicalOption, "BearCallSpread");
266  CheckExpirationDate(expiration, "BearCallSpread", nameof(expiration));
267 
268  if (leg1Strike >= leg2Strike)
269  {
270  throw new ArgumentException("BearCallSpread: leg1Strike must be less than leg2Strike", $"{nameof(leg1Strike)}, {nameof(leg2Strike)}");
271  }
272 
273  return new OptionStrategy
274  {
276  Underlying = canonicalOption.Underlying,
277  CanonicalOption = canonicalOption,
278  OptionLegs = new List<OptionStrategy.OptionLegData>
279  {
281  {
282  Right = OptionRight.Call, Strike = leg1Strike, Quantity = -1, Expiration = expiration
283  },
285  {
286  Right = OptionRight.Call, Strike = leg2Strike, Quantity = 1, Expiration = expiration
287  }
288  }
289  };
290  }
291 
292  /// <summary>
293  /// Method creates new Bear Put Spread strategy, that consists of two puts with the same expiration but different strikes.
294  /// The strike price of the short put is below the strike of the long put. This is a debit spread.
295  /// </summary>
296  /// <param name="canonicalOption">Option symbol</param>
297  /// <param name="leg1Strike">The strike price of the long put</param>
298  /// <param name="leg2Strike">The strike price of the short put</param>
299  /// <param name="expiration">Option expiration date</param>
300  /// <returns>Option strategy specification</returns>
302  Symbol canonicalOption,
303  decimal leg1Strike,
304  decimal leg2Strike,
305  DateTime expiration
306  )
307  {
308  CheckCanonicalOptionSymbol(canonicalOption, "BearPutSpread");
309  CheckExpirationDate(expiration, "BearPutSpread", nameof(expiration));
310 
311  if (leg1Strike <= leg2Strike)
312  {
313  throw new ArgumentException("BearPutSpread: leg1Strike must be greater than leg2Strike", $"{nameof(leg1Strike)}, {nameof(leg2Strike)}");
314  }
315 
316  return new OptionStrategy
317  {
319  Underlying = canonicalOption.Underlying,
320  CanonicalOption = canonicalOption,
321  OptionLegs = new List<OptionStrategy.OptionLegData>
322  {
324  {
325  Right = OptionRight.Put, Strike = leg1Strike, Quantity = 1,
326  Expiration = expiration
327  },
329  {
330  Right = OptionRight.Put, Strike = leg2Strike, Quantity = -1, Expiration = expiration
331  }
332  }
333  };
334  }
335 
336  /// <summary>
337  /// Method creates new Bull Call Spread strategy, that consists of two calls with the same expiration but different strikes.
338  /// The strike price of the short call is higher than the strike of the long call. This is a debit spread.
339  /// </summary>
340  /// <param name="canonicalOption">Option symbol</param>
341  /// <param name="leg1Strike">The strike price of the long call</param>
342  /// <param name="leg2Strike">The strike price of the short call</param>
343  /// <param name="expiration">Option expiration date</param>
344  /// <returns>Option strategy specification</returns>
346  Symbol canonicalOption,
347  decimal leg1Strike,
348  decimal leg2Strike,
349  DateTime expiration
350  )
351  {
352  CheckCanonicalOptionSymbol(canonicalOption, "BullCallSpread");
353  CheckExpirationDate(expiration, "BullCallSpread", nameof(expiration));
354 
355  if (leg1Strike >= leg2Strike)
356  {
357  throw new ArgumentException("BullCallSpread: leg1Strike must be less than leg2Strike", $"{nameof(leg1Strike)}, {nameof(leg2Strike)}");
358  }
359 
360  return new OptionStrategy
361  {
363  Underlying = canonicalOption.Underlying,
364  CanonicalOption = canonicalOption,
365  OptionLegs = new List<OptionStrategy.OptionLegData>
366  {
368  {
369  Right = OptionRight.Call, Strike = leg1Strike, Quantity = 1, Expiration = expiration
370  },
372  {
373  Right = OptionRight.Call, Strike = leg2Strike, Quantity = -1, Expiration = expiration
374  }
375  }
376  };
377  }
378 
379  /// <summary>
380  /// Method creates new Bull Put Spread strategy, that consists of two puts with the same expiration but different strikes.
381  /// The strike price of the short put is above the strike of the long put. This is a credit spread.
382  /// </summary>
383  /// <param name="canonicalOption">Option symbol</param>
384  /// <param name="leg1Strike">The strike price of the short put</param>
385  /// <param name="leg2Strike">The strike price of the long put</param>
386  /// <param name="expiration">Option expiration date</param>
387  /// <returns>Option strategy specification</returns>
389  Symbol canonicalOption,
390  decimal leg1Strike,
391  decimal leg2Strike,
392  DateTime expiration
393  )
394  {
395  CheckCanonicalOptionSymbol(canonicalOption, "BullPutSpread");
396  CheckExpirationDate(expiration, "BullPutSpread", nameof(expiration));
397 
398  if (leg1Strike <= leg2Strike)
399  {
400  throw new ArgumentException("BullPutSpread: leg1Strike must be greater than leg2Strike", $"{nameof(leg1Strike)}, {nameof(leg2Strike)}");
401  }
402 
403  return new OptionStrategy
404  {
406  Underlying = canonicalOption.Underlying,
407  CanonicalOption = canonicalOption,
408  OptionLegs = new List<OptionStrategy.OptionLegData>
409  {
411  {
412  Right = OptionRight.Put, Strike = leg1Strike, Quantity = -1, Expiration = expiration
413  },
415  {
416  Right = OptionRight.Put, Strike = leg2Strike, Quantity = 1,
417  Expiration = expiration
418  }
419  }
420  };
421  }
422 
423  /// <summary>
424  /// Method creates new Straddle strategy, that is a combination of buying a call and buying a put, both with the same strike price and expiration.
425  /// </summary>
426  /// <param name="canonicalOption">Option symbol</param>
427  /// <param name="strike">The strike price of the both legs</param>
428  /// <param name="expiration">Option expiration date</param>
429  /// <returns>Option strategy specification</returns>
430  public static OptionStrategy Straddle(Symbol canonicalOption, decimal strike, DateTime expiration)
431  {
432  CheckCanonicalOptionSymbol(canonicalOption, "Straddle");
433  CheckExpirationDate(expiration, "Straddle", nameof(expiration));
434 
435  return new OptionStrategy
436  {
438  Underlying = canonicalOption.Underlying,
439  CanonicalOption = canonicalOption,
440  OptionLegs = new List<OptionStrategy.OptionLegData>
441  {
443  {
444  Right = OptionRight.Call, Strike = strike, Quantity = 1,
445  Expiration = expiration
446  },
448  {
449  Right = OptionRight.Put, Strike = strike, Quantity = 1,
450  Expiration = expiration
451  }
452  }
453  };
454  }
455 
456  /// <summary>
457  /// Creates a Short Straddle strategy that consists of selling a call and a put, both with the same strike price and expiration.
458  /// </summary>
459  /// <param name="canonicalOption">Option symbol</param>
460  /// <param name="strike">The strike price for the option contracts</param>
461  /// <param name="expiration">The expiration date for the option contracts</param>
462  /// <returns>Option strategy specification</returns>
463  public static OptionStrategy ShortStraddle(Symbol canonicalOption, decimal strike, DateTime expiration)
464  {
465  // Since a short straddle is an inverted straddle, we can just use the Straddle method and invert the legs
466  return InvertStrategy(Straddle(canonicalOption, strike, expiration), OptionStrategyDefinitions.ShortStraddle.Name);
467  }
468 
469  /// <summary>
470  /// Method creates new Strangle strategy, that buying a call option and a put option with the same expiration date
471  /// The strike price of the call is above the strike of the put.
472  /// </summary>
473  /// <param name="canonicalOption">Option symbol</param>
474  /// <param name="callLegStrike">The strike price of the long call</param>
475  /// <param name="putLegStrike">The strike price of the long put</param>
476  /// <param name="expiration">Option expiration date</param>
477  /// <returns>Option strategy specification</returns>
478  public static OptionStrategy Strangle(
479  Symbol canonicalOption,
480  decimal callLegStrike,
481  decimal putLegStrike,
482  DateTime expiration
483  )
484  {
485  CheckCanonicalOptionSymbol(canonicalOption, "Strangle");
486  CheckExpirationDate(expiration, "Strangle", nameof(expiration));
487 
488  if (callLegStrike <= putLegStrike)
489  {
490  throw new ArgumentException($"Strangle: {nameof(callLegStrike)} must be greater than {nameof(putLegStrike)}",
491  $"{nameof(callLegStrike)}, {nameof(putLegStrike)}");
492  }
493 
494  return new OptionStrategy
495  {
497  Underlying = canonicalOption.Underlying,
498  CanonicalOption = canonicalOption,
499  OptionLegs = new List<OptionStrategy.OptionLegData>
500  {
502  {
503  Right = OptionRight.Call, Strike = callLegStrike, Quantity = 1, Expiration = expiration
504  },
506  {
507  Right = OptionRight.Put, Strike = putLegStrike, Quantity = 1, Expiration = expiration
508  }
509  }
510  };
511  }
512 
513  /// <summary>
514  /// Creates a Short Strangle strategy that consists of selling a call and a put, with the same expiration date and
515  /// the call strike being above the put strike.
516  /// </summary>
517  /// <param name="canonicalOption">Option symbol</param>
518  /// <param name="callLegStrike">The strike price of the short call</param>
519  /// <param name="putLegStrike">The strike price of the short put</param>
520  /// <param name="expiration">Option expiration date</param>
521  /// <returns>Option strategy specification</returns>
522  public static OptionStrategy ShortStrangle(Symbol canonicalOption, decimal callLegStrike, decimal putLegStrike, DateTime expiration)
523  {
524  // Since a short strangle is an inverted strangle, we can just use the Strangle method and invert the legs
525  return InvertStrategy(Strangle(canonicalOption, callLegStrike, putLegStrike, expiration), OptionStrategyDefinitions.ShortStrangle.Name);
526  }
527 
528  /// <summary>
529  /// Method creates new Call Butterfly strategy, that consists of two short calls at a middle strike, and one long call each at a lower and upper strike.
530  /// The upper and lower strikes must both be equidistant from the middle strike.
531  /// </summary>
532  /// <param name="canonicalOption">Option symbol</param>
533  /// <param name="higherStrike">The upper strike price of the long call</param>
534  /// <param name="middleStrike">The middle strike price of the two short calls</param>
535  /// <param name="lowerStrike">The lower strike price of the long call</param>
536  /// <param name="expiration">Option expiration date</param>
537  /// <returns>Option strategy specification</returns>
539  Symbol canonicalOption,
540  decimal higherStrike,
541  decimal middleStrike,
542  decimal lowerStrike,
543  DateTime expiration
544  )
545  {
546  CheckCanonicalOptionSymbol(canonicalOption, "CallButterfly");
547  CheckExpirationDate(expiration, "CallButterfly", nameof(expiration));
548 
549  if (higherStrike <= middleStrike ||
550  lowerStrike >= middleStrike ||
551  higherStrike - middleStrike != middleStrike - lowerStrike)
552  {
553  throw new ArgumentException("ButterflyCall: upper and lower strikes must both be equidistant from the middle strike",
554  $"{nameof(higherStrike)}, {nameof(middleStrike)}, {nameof(lowerStrike)}");
555  }
556 
557  return new OptionStrategy
558  {
560  Underlying = canonicalOption.Underlying,
561  CanonicalOption = canonicalOption,
562  OptionLegs = new List<OptionStrategy.OptionLegData>
563  {
565  {
566  Right = OptionRight.Call, Strike = higherStrike, Quantity = 1, Expiration = expiration
567  },
569  {
570  Right = OptionRight.Call, Strike = middleStrike, Quantity = -2, Expiration = expiration
571  },
573  {
574  Right = OptionRight.Call, Strike = lowerStrike, Quantity = 1, Expiration = expiration
575  }
576  }
577  };
578  }
579 
580  /// <summary>
581  /// Creates a new Butterfly Call strategy that consists of two short calls at a middle strike,
582  /// and one long call each at a lower and upper strike.
583  /// The upper and lower strikes must both be equidistant from the middle strike.
584  /// </summary>
585  /// <param name="canonicalOption">Option symbol</param>
586  /// <param name="higherStrike">The upper strike price of the long call</param>
587  /// <param name="middleStrike">The middle strike price of the two short calls</param>
588  /// <param name="lowerStrike">The lower strike price of the long call</param>
589  /// <param name="expiration">Option expiration date</param>
590  /// <returns>Option strategy specification</returns>
591  /// <remarks>Alias for <see cref="CallButterfly" /></remarks>
592  public static OptionStrategy ButterflyCall(Symbol canonicalOption, decimal higherStrike, decimal middleStrike, decimal lowerStrike,
593  DateTime expiration)
594  {
595  return CallButterfly(canonicalOption, higherStrike, middleStrike, lowerStrike, expiration);
596  }
597 
598  /// <summary>
599  /// Creates a new Butterfly Call strategy that consists of two long calls at a middle strike,
600  /// and one short call each at a lower and upper strike.
601  /// The upper and lower strikes must both be equidistant from the middle strike.
602  /// </summary>
603  /// <param name="canonicalOption">Option symbol</param>
604  /// <param name="higherStrike">The upper strike price of the short call</param>
605  /// <param name="middleStrike">The middle strike price of the two long calls</param>
606  /// <param name="lowerStrike">The lower strike price of the short call</param>
607  /// <param name="expiration">Option expiration date</param>
608  /// <returns>Option strategy specification</returns>
609  public static OptionStrategy ShortButterflyCall(Symbol canonicalOption, decimal higherStrike, decimal middleStrike, decimal lowerStrike,
610  DateTime expiration)
611  {
612  // Since a short butterfly call is an inverted butterfly call, we can just use the ButterflyCall method and invert the legs
613  return InvertStrategy(ButterflyCall(canonicalOption, higherStrike, middleStrike, lowerStrike, expiration),
615  }
616 
617  /// <summary>
618  /// Method creates new Put Butterfly strategy, that consists of two short puts at a middle strike, and one long put each at a lower and upper strike.
619  /// The upper and lower strikes must both be equidistant from the middle strike.
620  /// </summary>
621  /// <param name="canonicalOption">Option symbol</param>
622  /// <param name="higherStrike">The upper strike price of the long put</param>
623  /// <param name="middleStrike">The middle strike price of the two short puts</param>
624  /// <param name="lowerStrike">The lower strike price of the long put</param>
625  /// <param name="expiration">Option expiration date</param>
626  /// <returns>Option strategy specification</returns>
628  Symbol canonicalOption,
629  decimal higherStrike,
630  decimal middleStrike,
631  decimal lowerStrike,
632  DateTime expiration
633  )
634  {
635  CheckCanonicalOptionSymbol(canonicalOption, "PutButterfly");
636  CheckExpirationDate(expiration, "PutButterfly", nameof(expiration));
637 
638  if (higherStrike <= middleStrike ||
639  lowerStrike >= middleStrike ||
640  higherStrike - middleStrike != middleStrike - lowerStrike)
641  {
642  throw new ArgumentException("ButterflyPut: upper and lower strikes must both be equidistant from the middle strike",
643  $"{nameof(higherStrike)}, {nameof(middleStrike)}, {nameof(lowerStrike)}");
644  }
645 
646  return new OptionStrategy
647  {
649  Underlying = canonicalOption.Underlying,
650  CanonicalOption = canonicalOption,
651  OptionLegs = new List<OptionStrategy.OptionLegData>
652  {
654  {
655  Right = OptionRight.Put, Strike = higherStrike, Quantity = 1,
656  Expiration = expiration
657  },
659  {
660  Right = OptionRight.Put, Strike = middleStrike, Quantity = -2,
661  Expiration = expiration
662  },
664  {
665  Right = OptionRight.Put, Strike = lowerStrike, Quantity = 1,
666  Expiration = expiration
667  }
668  }
669  };
670  }
671 
672  /// <summary>
673  /// Creates a new Butterfly Put strategy that consists of two short puts at a middle strike,
674  /// and one long put each at a lower and upper strike.
675  /// The upper and lower strikes must both be equidistant from the middle strike.
676  /// </summary>
677  /// <param name="canonicalOption">Option symbol</param>
678  /// <param name="higherStrike">The upper strike price of the long put</param>
679  /// <param name="middleStrike">The middle strike price of the two short puts</param>
680  /// <param name="lowerStrike">The lower strike price of the long put</param>
681  /// <param name="expiration">Option expiration date</param>
682  /// <returns>Option strategy specification</returns>
683  /// <remarks>Alias for <see cref="PutButterfly" /></remarks>
684  public static OptionStrategy ButterflyPut(Symbol canonicalOption, decimal higherStrike, decimal middleStrike, decimal lowerStrike,
685  DateTime expiration)
686  {
687  return PutButterfly(canonicalOption, higherStrike, middleStrike, lowerStrike, expiration);
688  }
689 
690  /// <summary>
691  /// Creates a new Butterfly Put strategy that consists of two long puts at a middle strike,
692  /// and one short put each at a lower and upper strike.
693  /// The upper and lower strikes must both be equidistant from the middle strike.
694  /// </summary>
695  /// <param name="canonicalOption">Option symbol</param>
696  /// <param name="higherStrike">The upper strike price of the short put</param>
697  /// <param name="middleStrike">The middle strike price of the two long puts</param>
698  /// <param name="lowerStrike">The lower strike price of the short put</param>
699  /// <param name="expiration">Option expiration date</param>
700  /// <returns>Option strategy specification</returns>
701  public static OptionStrategy ShortButterflyPut(Symbol canonicalOption, decimal higherStrike, decimal middleStrike, decimal lowerStrike,
702  DateTime expiration)
703  {
704  // Since a short butterfly put is an inverted butterfly put, we can just use the ButterflyPut method and invert the legs
705  return InvertStrategy(ButterflyPut(canonicalOption, higherStrike, middleStrike, lowerStrike, expiration),
707  }
708 
709  /// <summary>
710  /// Creates new Call Calendar Spread strategy which consists of a short and a long call
711  /// with the same strikes but with the long call having a further expiration date.
712  /// </summary>
713  /// <param name="canonicalOption">Option symbol</param>
714  /// <param name="strike">The strike price of the both legs</param>
715  /// <param name="nearExpiration">Near expiration date for the short option</param>
716  /// <param name="farExpiration">Far expiration date for the long option</param>
717  /// <returns>Option strategy specification</returns>
718  public static OptionStrategy CallCalendarSpread(Symbol canonicalOption, decimal strike, DateTime nearExpiration, DateTime farExpiration)
719  {
720  CheckCanonicalOptionSymbol(canonicalOption, "CallCalendarSpread");
721  CheckExpirationDate(nearExpiration, "CallCalendarSpread", nameof(nearExpiration));
722  CheckExpirationDate(farExpiration, "CallCalendarSpread", nameof(farExpiration));
723 
724  if (nearExpiration >= farExpiration)
725  {
726  throw new ArgumentException("CallCalendarSpread: near expiration must be less than far expiration",
727  $"{nameof(nearExpiration)}, {nameof(farExpiration)}");
728  }
729 
730  return new OptionStrategy
731  {
733  Underlying = canonicalOption.Underlying,
734  CanonicalOption = canonicalOption,
735  OptionLegs = new List<OptionStrategy.OptionLegData>
736  {
738  {
739  Right = OptionRight.Call, Strike = strike, Quantity = -1, Expiration = nearExpiration
740  },
742  {
743  Right = OptionRight.Call, Strike = strike, Quantity = 1, Expiration = farExpiration
744  }
745  }
746  };
747  }
748 
749  /// <summary>
750  /// Creates new Short Call Calendar Spread strategy which consists of a short and a long call
751  /// with the same strikes but with the short call having a further expiration date.
752  /// </summary>
753  /// <param name="canonicalOption">Option symbol</param>
754  /// <param name="strike">The strike price of the both legs</param>
755  /// <param name="nearExpiration">Near expiration date for the long option</param>
756  /// <param name="farExpiration">Far expiration date for the short option</param>
757  /// <returns>Option strategy specification</returns>
758  public static OptionStrategy ShortCallCalendarSpread(Symbol canonicalOption, decimal strike, DateTime nearExpiration, DateTime farExpiration)
759  {
760  // Since a short call calendar spread is an inverted call calendar, we can just use the CallCalendarSpread method and invert the legs
761  return InvertStrategy(CallCalendarSpread(canonicalOption, strike, nearExpiration, farExpiration),
763  }
764 
765  /// <summary>
766  /// Creates new Put Calendar Spread strategy which consists of a short and a long put
767  /// with the same strikes but with the long put having a further expiration date.
768  /// </summary>
769  /// <param name="canonicalOption">Option symbol</param>
770  /// <param name="strike">The strike price of the both legs</param>
771  /// <param name="nearExpiration">Near expiration date for the short option</param>
772  /// <param name="farExpiration">Far expiration date for the long option</param>
773  /// <returns>Option strategy specification</returns>
774  public static OptionStrategy PutCalendarSpread(Symbol canonicalOption, decimal strike, DateTime nearExpiration, DateTime farExpiration)
775  {
776  CheckCanonicalOptionSymbol(canonicalOption, "PutCalendarSpread");
777  CheckExpirationDate(nearExpiration, "PutCalendarSpread", nameof(nearExpiration));
778  CheckExpirationDate(farExpiration, "PutCalendarSpread", nameof(farExpiration));
779 
780  if (nearExpiration >= farExpiration)
781  {
782  throw new ArgumentException("PutCalendarSpread: near expiration must be less than far expiration",
783  $"{nameof(nearExpiration)}, {nameof(farExpiration)}");
784  }
785 
786  return new OptionStrategy
787  {
789  Underlying = canonicalOption.Underlying,
790  CanonicalOption = canonicalOption,
791  OptionLegs = new List<OptionStrategy.OptionLegData>
792  {
794  {
795  Right = OptionRight.Put, Strike = strike, Quantity = -1, Expiration = nearExpiration
796  },
798  {
799  Right = OptionRight.Put, Strike = strike, Quantity = 1, Expiration = farExpiration
800  }
801  }
802  };
803  }
804 
805  /// <summary>
806  /// Creates new Short Put Calendar Spread strategy which consists of a short and a long put
807  /// with the same strikes but with the short put having a further expiration date.
808  /// </summary>
809  /// <param name="canonicalOption">Option symbol</param>
810  /// <param name="strike">The strike price of the both legs</param>
811  /// <param name="nearExpiration">Near expiration date for the long option</param>
812  /// <param name="farExpiration">Far expiration date for the short option</param>
813  /// <returns>Option strategy specification</returns>
814  public static OptionStrategy ShortPutCalendarSpread(Symbol canonicalOption, decimal strike, DateTime nearExpiration, DateTime farExpiration)
815  {
816  // Since a short put calendar spread is an inverted put calendar, we can just use the PutCalendarSpread method and invert the legs
817  return InvertStrategy(PutCalendarSpread(canonicalOption, strike, nearExpiration, farExpiration),
819  }
820 
821  /// <summary>
822  /// Creates a new Iron Butterfly strategy which consists of a short ATM call, a short ATM put, a long OTM call, and a long OTM put.
823  /// all with the same expiration date and with increasing strikes prices in the mentioned order.
824  /// </summary>
825  /// <param name="canonicalOption">Option symbol</param>
826  /// <param name="otmCallStrike">OTM call option strike price</param>
827  /// <param name="atmStrike">2 ATM options strike price</param>
828  /// <param name="otmPutStrike">OTM put option strike price</param>
829  /// <param name="expiration">Expiration date for all the options</param>
830  /// <returns>Option strategy specification</returns>
831  public static OptionStrategy IronButterfly(Symbol canonicalOption, decimal otmPutStrike, decimal atmStrike, decimal otmCallStrike,
832  DateTime expiration)
833  {
834  if (atmStrike - otmPutStrike != otmCallStrike - atmStrike)
835  {
836  throw new ArgumentException("IronButterfly: intervals between exercise prices must be equal");
837  }
838 
839  var strategy = IronCondor(canonicalOption, otmPutStrike, atmStrike, atmStrike, otmCallStrike, expiration);
841  return strategy;
842  }
843 
844  /// <summary>
845  /// Creates a new Short Iron Butterfly strategy which consists of a long ATM call, a long ATM put, a short OTM call, and a short OTM put,
846  /// all with the same expiration date and with increasing strikes prices in the mentioned order.
847  /// <remarks>It is the inverse of an <see cref="IronButterfly" />.</remarks>
848  /// </summary>
849  /// <param name="canonicalOption">Option symbol</param>
850  /// <param name="otmCallStrike">OTM call option strike price</param>
851  /// <param name="atmStrike">2 ATM options strike price</param>
852  /// <param name="otmPutStrike">OTM put option strike price</param>
853  /// <param name="expiration">Expiration date for all the options</param>
854  /// <returns>Option strategy specification</returns>
855  public static OptionStrategy ShortIronButterfly(Symbol canonicalOption, decimal otmPutStrike, decimal atmStrike, decimal otmCallStrike,
856  DateTime expiration)
857  {
858  return InvertStrategy(IronButterfly(canonicalOption, otmPutStrike, atmStrike, otmCallStrike, expiration),
860  }
861 
862  /// <summary>
863  /// Creates a new Iron Condor strategy which consists of a long put, a short put, a short call and a long option,
864  /// all with the same expiration date and with increasing strikes prices in the mentioned order.
865  /// </summary>
866  /// <param name="canonicalOption">Option symbol</param>
867  /// <param name="longPutStrike">Long put option strike price</param>
868  /// <param name="shortPutStrike">Short put option strike price</param>
869  /// <param name="shortCallStrike">Short call option strike price</param>
870  /// <param name="longCallStrike">Long call option strike price</param>
871  /// <param name="expiration">Expiration date for all the options</param>
872  /// <returns>Option strategy specification</returns>
873  public static OptionStrategy IronCondor(Symbol canonicalOption, decimal longPutStrike, decimal shortPutStrike, decimal shortCallStrike,
874  decimal longCallStrike, DateTime expiration)
875  {
876  CheckCanonicalOptionSymbol(canonicalOption, "IronCondor");
877  CheckExpirationDate(expiration, "IronCondor", nameof(expiration));
878 
879  if (longPutStrike >= shortPutStrike || shortPutStrike > shortCallStrike || shortCallStrike >= longCallStrike)
880  {
881  throw new ArgumentException("IronCondor: strike prices must be in ascending order",
882  $"{nameof(longPutStrike)}, {nameof(shortPutStrike)}, {nameof(shortCallStrike)}, {nameof(longCallStrike)}");
883  }
884 
885  return new OptionStrategy
886  {
888  Underlying = canonicalOption.Underlying,
889  CanonicalOption = canonicalOption,
890  OptionLegs = new List<OptionStrategy.OptionLegData>
891  {
893  {
894  Right = OptionRight.Put, Strike = longPutStrike, Quantity = 1, Expiration = expiration
895  },
897  {
898  Right = OptionRight.Put, Strike = shortPutStrike, Quantity = -1, Expiration = expiration
899  },
901  {
902  Right = OptionRight.Call, Strike = shortCallStrike, Quantity = -1, Expiration = expiration
903  },
905  {
906  Right = OptionRight.Call, Strike = longCallStrike, Quantity = 1, Expiration = expiration
907  }
908  }
909  };
910  }
911 
912  /// <summary>
913  /// Creates a new Short Iron Condor strategy which consists of a short put, a long put, a long call and a short call,
914  /// all with the same expiration date and with increasing strikes prices in the mentioned order.
915  /// </summary>
916  /// <param name="canonicalOption">Option symbol</param>
917  /// <param name="shortPutStrike">Short put option strike price</param>
918  /// <param name="longPutStrike">Long put option strike price</param>
919  /// <param name="longCallStrike">Long call option strike price</param>
920  /// <param name="shortCallStrike">Short call option strike price</param>
921  /// <param name="expiration">Expiration date for all the options</param>
922  /// <returns>Option strategy specification</returns>
923  public static OptionStrategy ShortIronCondor(Symbol canonicalOption, decimal shortPutStrike, decimal longPutStrike, decimal longCallStrike,
924  decimal shortCallStrike, DateTime expiration)
925  {
926  return InvertStrategy(IronCondor(canonicalOption, shortPutStrike, longPutStrike, longCallStrike, shortCallStrike, expiration),
928  }
929 
930  /// <summary>
931  /// Creates a Box Spread strategy which consists of a long call and a short put (buy side) of the same strikes,
932  /// coupled with a short call and a long put (sell side) of higher but same strikes. All options have the same expiry.
933  /// </summary>
934  /// <param name="canonicalOption">Option symbol</param>
935  /// <param name="higherStrike">The strike price of the sell side legs</param>
936  /// <param name="lowerStrike">The strike price of the buy side legs</param>
937  /// <param name="expiration">Option expiration date</param>
938  /// <returns>Option strategy specification</returns>
939  public static OptionStrategy BoxSpread(Symbol canonicalOption, decimal higherStrike, decimal lowerStrike, DateTime expiration)
940  {
941  if (higherStrike <= lowerStrike)
942  {
943  throw new ArgumentException($"BoxSpread: strike prices must be in descending order, {nameof(higherStrike)}, {nameof(lowerStrike)}");
944  }
945 
946  // It is a combination of a BearPutSpread and a BullCallSpread with the same expiry and strikes
947  var bearPutSpread = BearPutSpread(canonicalOption, higherStrike, lowerStrike, expiration);
948  var bullCallSpread = BullCallSpread(canonicalOption, lowerStrike, higherStrike, expiration);
949 
950  return new OptionStrategy
951  {
953  Underlying = canonicalOption.Underlying,
954  CanonicalOption = canonicalOption,
955  OptionLegs = bearPutSpread.OptionLegs.Concat(bullCallSpread.OptionLegs).ToList()
956  };
957  }
958 
959  /// <summary>
960  /// Creates a Short Box Spread strategy which consists of a long call and a short put (buy side) of the same strikes,
961  /// coupled with a short call and a long put (sell side) of lower but same strikes. All options have the same expiry.
962  /// </summary>
963  /// <param name="canonicalOption">Option symbol</param>
964  /// <param name="higherStrike">The strike price of the buy side</param>
965  /// <param name="lowerStrike">The strike price of the sell side</param>
966  /// <param name="expiration">Option expiration date</param>
967  /// <returns>Option strategy specification</returns>
968  public static OptionStrategy ShortBoxSpread(Symbol canonicalOption, decimal higherStrike, decimal lowerStrike, DateTime expiration)
969  {
970  // Since a short box spread is an inverted box spread, we can just use the BoxSpread method and invert the legs
971  return InvertStrategy(BoxSpread(canonicalOption, higherStrike, lowerStrike, expiration), OptionStrategyDefinitions.ShortBoxSpread.Name);
972  }
973 
974  /// <summary>
975  /// Creates new Jelly Roll strategy which combines a long call calendar spread and a short put calendar spread
976  /// with the same strikes and the same pair of expiration dates.
977  /// </summary>
978  /// <param name="canonicalOption">Option symbol</param>
979  /// <param name="strike">The strike price of the all legs</param>
980  /// <param name="nearExpiration">Near expiration date for the short call and the long put</param>
981  /// <param name="farExpiration">Far expiration date for the long call and the short put</param>
982  /// <returns>Option strategy specification</returns>
983  public static OptionStrategy JellyRoll(Symbol canonicalOption, decimal strike, DateTime nearExpiration, DateTime farExpiration)
984  {
985  var callCalendarSpread = CallCalendarSpread(canonicalOption, strike, nearExpiration, farExpiration);
986  var shortPutCalendarSpread = ShortPutCalendarSpread(canonicalOption, strike, nearExpiration, farExpiration);
987 
988  return new OptionStrategy
989  {
991  Underlying = canonicalOption.Underlying,
992  CanonicalOption = canonicalOption,
993  OptionLegs = callCalendarSpread.OptionLegs.Concat(shortPutCalendarSpread.OptionLegs).ToList()
994  };
995  }
996 
997  /// <summary>
998  /// Creates new Short Jelly Roll strategy which combines a long call calendar spread and a short put calendar spread
999  /// with the same strikes and the same pair of expiration dates.
1000  /// </summary>
1001  /// <param name="canonicalOption">Option symbol</param>
1002  /// <param name="strike">The strike price of the all legs</param>
1003  /// <param name="nearExpiration">Near expiration date for the short call and the long put</param>
1004  /// <param name="farExpiration">Far expiration date for the long call and the short put</param>
1005  /// <returns>Option strategy specification</returns>
1006  public static OptionStrategy ShortJellyRoll(Symbol canonicalOption, decimal strike, DateTime nearExpiration, DateTime farExpiration)
1007  {
1008  return InvertStrategy(JellyRoll(canonicalOption, strike, nearExpiration, farExpiration), OptionStrategyDefinitions.ShortJellyRoll.Name);
1009  }
1010 
1011  /// <summary>
1012  /// Method creates new Bear Call Ladder strategy, that consists of three calls with the same expiration but different strikes.
1013  /// The strike price of the short call is below the strikes of the two long calls.
1014  /// </summary>
1015  /// <param name="canonicalOption">Option symbol</param>
1016  /// <param name="lowerStrike">The strike price of the short call</param>
1017  /// <param name="middleStrike">The middle strike price of one long call</param>
1018  /// <param name="higherStrike">The strike price of one long call with higher strike price</param>
1019  /// <param name="expiration">Option expiration date</param>
1020  /// <returns>Option strategy specification</returns>
1022  Symbol canonicalOption,
1023  decimal lowerStrike,
1024  decimal middleStrike,
1025  decimal higherStrike,
1026  DateTime expiration
1027  )
1028  {
1029  CheckCanonicalOptionSymbol(canonicalOption, "BearCallLadder");
1030  CheckExpirationDate(expiration, "BearCallLadder", nameof(expiration));
1031 
1032  if (lowerStrike >= middleStrike || lowerStrike >= higherStrike || middleStrike >= higherStrike)
1033  {
1034  throw new ArgumentException("BearCallLadder: strike prices must be in ascending order",
1035  $"{nameof(lowerStrike)}, {nameof(middleStrike)}, {nameof(higherStrike)}");
1036  }
1037 
1038  return new OptionStrategy
1039  {
1041  Underlying = canonicalOption.Underlying,
1042  CanonicalOption = canonicalOption,
1043  OptionLegs = new List<OptionStrategy.OptionLegData>
1044  {
1046  {
1047  Right = OptionRight.Call, Strike = lowerStrike, Quantity = -1, Expiration = expiration
1048  },
1050  {
1051  Right = OptionRight.Call, Strike = middleStrike, Quantity = 1, Expiration = expiration
1052  },
1054  {
1055  Right = OptionRight.Call, Strike = higherStrike, Quantity = 1, Expiration = expiration
1056  }
1057  }
1058  };
1059  }
1060 
1061  /// <summary>
1062  /// Method creates new Bear Put Ladder strategy, that consists of three puts with the same expiration but different strikes.
1063  /// The strike price of the long put is above the strikes of the two short puts.
1064  /// </summary>
1065  /// <param name="canonicalOption">Option symbol</param>
1066  /// <param name="higherStrike">The strike price of the long put</param>
1067  /// <param name="middleStrike">The middle strike price of one short put</param>
1068  /// <param name="lowerStrike">The strike price of one short put with lower strike price</param>
1069  /// <param name="expiration">Option expiration date</param>
1070  /// <returns>Option strategy specification</returns>
1072  Symbol canonicalOption,
1073  decimal higherStrike,
1074  decimal middleStrike,
1075  decimal lowerStrike,
1076  DateTime expiration
1077  )
1078  {
1079  CheckCanonicalOptionSymbol(canonicalOption, "BearPutLadder");
1080  CheckExpirationDate(expiration, "BearPutLadder", nameof(expiration));
1081 
1082  if (higherStrike <= middleStrike || higherStrike <= lowerStrike || middleStrike <= lowerStrike)
1083  {
1084  throw new ArgumentException("BearPutLadder: strike prices must be in descending order",
1085  $"{nameof(higherStrike)}, {nameof(middleStrike)}, {nameof(lowerStrike)}");
1086  }
1087 
1088  return new OptionStrategy
1089  {
1091  Underlying = canonicalOption.Underlying,
1092  CanonicalOption = canonicalOption,
1093  OptionLegs = new List<OptionStrategy.OptionLegData>
1094  {
1096  {
1097  Right = OptionRight.Put, Strike = higherStrike, Quantity = 1,
1098  Expiration = expiration
1099  },
1101  {
1102  Right = OptionRight.Put, Strike = middleStrike, Quantity = -1, Expiration = expiration
1103  },
1105  {
1106  Right = OptionRight.Put, Strike = lowerStrike, Quantity = -1, Expiration = expiration
1107  }
1108  }
1109  };
1110  }
1111 
1112  /// <summary>
1113  /// Method creates new Bull Call Ladder strategy, that consists of three calls with the same expiration but different strikes.
1114  /// The strike price of the long call is below the strikes of the two short calls.
1115  /// </summary>
1116  /// <param name="canonicalOption">Option symbol</param>
1117  /// <param name="lowerStrike">The strike price of the long call</param>
1118  /// <param name="middleStrike">The middle strike price of one short call</param>
1119  /// <param name="higherStrike">The strike price of one short call with higher strike price</param>
1120  /// <param name="expiration">Option expiration date</param>
1121  /// <returns>Option strategy specification</returns>
1123  Symbol canonicalOption,
1124  decimal lowerStrike,
1125  decimal middleStrike,
1126  decimal higherStrike,
1127  DateTime expiration
1128  )
1129  {
1130  return InvertStrategy(BearCallLadder(canonicalOption, lowerStrike, middleStrike, higherStrike, expiration), OptionStrategyDefinitions.BullCallLadder.Name);
1131  }
1132 
1133  /// <summary>
1134  /// Method creates new Bull Put Ladder strategy, that consists of three puts with the same expiration but different strikes.
1135  /// The strike price of the short put is above the strikes of the two long puts.
1136  /// </summary>
1137  /// <param name="canonicalOption">Option symbol</param>
1138  /// <param name="higherStrike">The strike price of the short put</param>
1139  /// <param name="middleStrike">The middle strike price of one long put</param>
1140  /// <param name="lowerStrike">The strike price of one long put with lower strike price</param>
1141  /// <param name="expiration">Option expiration date</param>
1142  /// <returns>Option strategy specification</returns>
1144  Symbol canonicalOption,
1145  decimal higherStrike,
1146  decimal middleStrike,
1147  decimal lowerStrike,
1148  DateTime expiration
1149  )
1150  {
1151  return InvertStrategy(BearPutLadder(canonicalOption, higherStrike, middleStrike, lowerStrike, expiration), OptionStrategyDefinitions.BullPutLadder.Name);
1152  }
1153 
1154  /// <summary>
1155  /// Method creates new Long Call Backspread strategy, that consists of two calls with the same expiration but different strikes.
1156  /// It involves selling the lower strike call, while buying twice the number of the higher strike call.
1157  /// </summary>
1158  /// <param name="canonicalOption">Option symbol</param>
1159  /// <param name="lowerStrike">The strike price of the short call</param>
1160  /// <param name="higherStrike">The strike price of the long call</param>
1161  /// <param name="expiration">Option expiration date</param>
1162  /// <returns>Option strategy specification</returns>
1164  Symbol canonicalOption,
1165  decimal lowerStrike,
1166  decimal higherStrike,
1167  DateTime expiration
1168  )
1169  {
1170  CheckCanonicalOptionSymbol(canonicalOption, "CallBackspread");
1171  CheckExpirationDate(expiration, "CallBackspread", nameof(expiration));
1172 
1173  if (lowerStrike >= higherStrike)
1174  {
1175  throw new ArgumentException($"CallBackspread: strike prices must be in ascending order, {nameof(lowerStrike)}, {nameof(higherStrike)}");
1176  }
1177 
1178  return new OptionStrategy
1179  {
1180  Name = "Call Backspread",
1181  Underlying = canonicalOption.Underlying,
1182  CanonicalOption = canonicalOption,
1183  OptionLegs = new List<OptionStrategy.OptionLegData>
1184  {
1186  {
1187  Right = OptionRight.Call, Strike = lowerStrike, Quantity = -1, Expiration = expiration
1188  },
1190  {
1191  Right = OptionRight.Call, Strike = higherStrike, Quantity = 2, Expiration = expiration
1192  }
1193  }
1194  };
1195  }
1196 
1197  /// <summary>
1198  /// Method creates new Long Put Backspread strategy, that consists of two puts with the same expiration but different strikes.
1199  /// It involves selling the higher strike put, while buying twice the number of the lower strike put.
1200  /// </summary>
1201  /// <param name="canonicalOption">Option symbol</param>
1202  /// <param name="higherStrike">The strike price of the short put</param>
1203  /// <param name="lowerStrike">The strike price of the long put</param>
1204  /// <param name="expiration">Option expiration date</param>
1205  /// <returns>Option strategy specification</returns>
1207  Symbol canonicalOption,
1208  decimal higherStrike,
1209  decimal lowerStrike,
1210  DateTime expiration
1211  )
1212  {
1213  CheckCanonicalOptionSymbol(canonicalOption, "PutBackspread");
1214  CheckExpirationDate(expiration, "PutBackspread", nameof(expiration));
1215 
1216  if (higherStrike <= lowerStrike)
1217  {
1218  throw new ArgumentException($"PutBackspread: strike prices must be in descending order, {nameof(higherStrike)}, {nameof(lowerStrike)}");
1219  }
1220 
1221  return new OptionStrategy
1222  {
1223  Name = "Put Backspread",
1224  Underlying = canonicalOption.Underlying,
1225  CanonicalOption = canonicalOption,
1226  OptionLegs = new List<OptionStrategy.OptionLegData>
1227  {
1229  {
1230  Right = OptionRight.Put, Strike = higherStrike, Quantity = -1, Expiration = expiration
1231  },
1233  {
1234  Right = OptionRight.Put, Strike = lowerStrike, Quantity = 2, Expiration = expiration
1235  }
1236  }
1237  };
1238  }
1239 
1240  /// <summary>
1241  /// Method creates new Short Call Backspread strategy, that consists of two calls with the same expiration but different strikes.
1242  /// It involves buying the lower strike call, while shorting twice the number of the higher strike call.
1243  /// </summary>
1244  /// <param name="canonicalOption">Option symbol</param>
1245  /// <param name="lowerStrike">The strike price of the long call</param>
1246  /// <param name="higherStrike">The strike price of the short call</param>
1247  /// <param name="expiration">Option expiration date</param>
1249  Symbol canonicalOption,
1250  decimal lowerStrike,
1251  decimal higherStrike,
1252  DateTime expiration
1253  )
1254  {
1255  return InvertStrategy(CallBackspread(canonicalOption, lowerStrike, higherStrike, expiration), "Short Call Backspread");
1256  }
1257 
1258  /// <summary>
1259  /// Method creates new Short Put Backspread strategy, that consists of two puts with the same expiration but different strikes.
1260  /// It involves buying the higher strike put, while selling twice the number of the lower strike put.
1261  /// </summary>
1262  /// <param name="canonicalOption">Option symbol</param>
1263  /// <param name="higherStrike">The strike price of the long put</param>
1264  /// <param name="lowerStrike">The strike price of the short put</param>
1265  /// <param name="expiration">Option expiration date</param>
1266  /// <returns>Option strategy specification</returns>
1268  Symbol canonicalOption,
1269  decimal higherStrike,
1270  decimal lowerStrike,
1271  DateTime expiration
1272  )
1273  {
1274  return InvertStrategy(PutBackspread(canonicalOption, higherStrike, lowerStrike, expiration), "Short Put Backspread");
1275  }
1276 
1277  /// <summary>
1278  /// Checks that canonical option symbol is valid
1279  /// </summary>
1280  private static void CheckCanonicalOptionSymbol(Symbol canonicalOption, string strategyName)
1281  {
1282  if (!canonicalOption.HasUnderlying || canonicalOption.ID.StrikePrice != 0.0m)
1283  {
1284  throw new ArgumentException($"{strategyName}: canonicalOption must contain canonical option symbol", nameof(canonicalOption));
1285  }
1286  }
1287 
1288  /// <summary>
1289  /// Checks that expiration date is valid
1290  /// </summary>
1291  private static void CheckExpirationDate(DateTime expiration, string strategyName, string parameterName)
1292  {
1293  if (expiration == DateTime.MaxValue || expiration == DateTime.MinValue)
1294  {
1295  throw new ArgumentException($"{strategyName}: expiration must contain expiration date", parameterName);
1296  }
1297  }
1298 
1299  /// <summary>
1300  /// Inverts the given strategy by multiplying all legs' quantities by -1 and changing the strategy name.
1301  /// </summary>
1302  private static OptionStrategy InvertStrategy(OptionStrategy strategy, string invertedStrategyName)
1303  {
1304  strategy.Name = invertedStrategyName;
1305  foreach (var leg in strategy.OptionLegs.Cast<OptionStrategy.LegData>().Concat(strategy.UnderlyingLegs))
1306  {
1307  leg.Quantity *= -1;
1308  }
1309 
1310  return strategy;
1311  }
1312  }
1313 }