17 using System.Collections.Generic;
47 CheckCanonicalOptionSymbol(canonicalOption,
"CoveredCall");
48 CheckExpirationDate(expiration,
"CoveredCall", nameof(expiration));
57 CanonicalOption = canonicalOption,
97 CheckCanonicalOptionSymbol(canonicalOption,
"CoveredPut");
98 CheckExpirationDate(expiration,
"CoveredPut", nameof(expiration));
107 CanonicalOption = canonicalOption,
147 CheckCanonicalOptionSymbol(canonicalOption,
"NakedCall");
148 CheckExpirationDate(expiration,
"NakedCall", nameof(expiration));
154 CanonicalOption = canonicalOption,
174 CheckCanonicalOptionSymbol(canonicalOption,
"NakedPut");
175 CheckExpirationDate(expiration,
"NakedPut", nameof(expiration));
181 CanonicalOption = canonicalOption,
208 CheckCanonicalOptionSymbol(canonicalOption,
"BearCallSpread");
209 CheckExpirationDate(expiration,
"BearCallSpread", nameof(expiration));
211 if (leg1Strike >= leg2Strike)
213 throw new ArgumentException(
"BearCallSpread: leg1Strike must be less than leg2Strike", $
"{nameof(leg1Strike)}, {nameof(leg2Strike)}");
220 CanonicalOption = canonicalOption,
251 CheckCanonicalOptionSymbol(canonicalOption,
"BearPutSpread");
252 CheckExpirationDate(expiration,
"BearPutSpread", nameof(expiration));
254 if (leg1Strike <= leg2Strike)
256 throw new ArgumentException(
"BearPutSpread: leg1Strike must be greater than leg2Strike", $
"{nameof(leg1Strike)}, {nameof(leg2Strike)}");
263 CanonicalOption = canonicalOption,
295 CheckCanonicalOptionSymbol(canonicalOption,
"BullCallSpread");
296 CheckExpirationDate(expiration,
"BullCallSpread", nameof(expiration));
298 if (leg1Strike >= leg2Strike)
300 throw new ArgumentException(
"BullCallSpread: leg1Strike must be less than leg2Strike", $
"{nameof(leg1Strike)}, {nameof(leg2Strike)}");
307 CanonicalOption = canonicalOption,
338 CheckCanonicalOptionSymbol(canonicalOption,
"BullPutSpread");
339 CheckExpirationDate(expiration,
"BullPutSpread", nameof(expiration));
341 if (leg1Strike <= leg2Strike)
343 throw new ArgumentException(
"BullPutSpread: leg1Strike must be greater than leg2Strike", $
"{nameof(leg1Strike)}, {nameof(leg2Strike)}");
350 CanonicalOption = canonicalOption,
375 CheckCanonicalOptionSymbol(canonicalOption,
"Straddle");
376 CheckExpirationDate(expiration,
"Straddle", nameof(expiration));
382 CanonicalOption = canonicalOption,
423 decimal callLegStrike,
424 decimal putLegStrike,
428 CheckCanonicalOptionSymbol(canonicalOption,
"Strangle");
429 CheckExpirationDate(expiration,
"Strangle", nameof(expiration));
431 if (callLegStrike <= putLegStrike)
433 throw new ArgumentException($
"Strangle: {nameof(callLegStrike)} must be greater than {nameof(putLegStrike)}",
434 $
"{nameof(callLegStrike)}, {nameof(putLegStrike)}");
441 CanonicalOption = canonicalOption,
483 decimal higherStrike,
484 decimal middleStrike,
489 CheckCanonicalOptionSymbol(canonicalOption,
"CallButterfly");
490 CheckExpirationDate(expiration,
"CallButterfly", nameof(expiration));
492 if (higherStrike <= middleStrike ||
493 lowerStrike >= middleStrike ||
494 higherStrike - middleStrike != middleStrike - lowerStrike)
496 throw new ArgumentException(
"ButterflyCall: upper and lower strikes must both be equidistant from the middle strike",
497 $
"{nameof(higherStrike)}, {nameof(middleStrike)}, {nameof(lowerStrike)}");
504 CanonicalOption = canonicalOption,
538 return CallButterfly(canonicalOption, higherStrike, middleStrike, lowerStrike, expiration);
556 return InvertStrategy(
ButterflyCall(canonicalOption, higherStrike, middleStrike, lowerStrike, expiration),
572 decimal higherStrike,
573 decimal middleStrike,
578 CheckCanonicalOptionSymbol(canonicalOption,
"PutButterfly");
579 CheckExpirationDate(expiration,
"PutButterfly", nameof(expiration));
581 if (higherStrike <= middleStrike ||
582 lowerStrike >= middleStrike ||
583 higherStrike - middleStrike != middleStrike - lowerStrike)
585 throw new ArgumentException(
"ButterflyPut: upper and lower strikes must both be equidistant from the middle strike",
586 $
"{nameof(higherStrike)}, {nameof(middleStrike)}, {nameof(lowerStrike)}");
593 CanonicalOption = canonicalOption,
630 return PutButterfly(canonicalOption, higherStrike, middleStrike, lowerStrike, expiration);
648 return InvertStrategy(
ButterflyPut(canonicalOption, higherStrike, middleStrike, lowerStrike, expiration),
663 CheckCanonicalOptionSymbol(canonicalOption,
"CallCalendarSpread");
664 CheckExpirationDate(nearExpiration,
"CallCalendarSpread", nameof(nearExpiration));
665 CheckExpirationDate(farExpiration,
"CallCalendarSpread", nameof(farExpiration));
667 if (nearExpiration >= farExpiration)
669 throw new ArgumentException(
"CallCalendarSpread: near expiration must be less than far expiration",
670 $
"{nameof(nearExpiration)}, {nameof(farExpiration)}");
677 CanonicalOption = canonicalOption,
704 return InvertStrategy(
CallCalendarSpread(canonicalOption, strike, nearExpiration, farExpiration),
719 CheckCanonicalOptionSymbol(canonicalOption,
"PutCalendarSpread");
720 CheckExpirationDate(nearExpiration,
"PutCalendarSpread", nameof(nearExpiration));
721 CheckExpirationDate(farExpiration,
"PutCalendarSpread", nameof(farExpiration));
723 if (nearExpiration >= farExpiration)
725 throw new ArgumentException(
"PutCalendarSpread: near expiration must be less than far expiration",
726 $
"{nameof(nearExpiration)}, {nameof(farExpiration)}");
733 CanonicalOption = canonicalOption,
760 return InvertStrategy(
PutCalendarSpread(canonicalOption, strike, nearExpiration, farExpiration),
776 decimal longCallStrike, DateTime expiration)
778 CheckCanonicalOptionSymbol(canonicalOption,
"IronCondor");
779 CheckExpirationDate(expiration,
"IronCondor", nameof(expiration));
781 if (longPutStrike >= shortPutStrike || shortPutStrike >= shortCallStrike || shortCallStrike >= longCallStrike)
783 throw new ArgumentException(
"IronCondor: strike prices must be in ascending order",
784 $
"{nameof(longPutStrike)}, {nameof(shortPutStrike)}, {nameof(shortCallStrike)}, {nameof(longCallStrike)}");
791 CanonicalOption = canonicalOption,
817 private static void CheckCanonicalOptionSymbol(
Symbol canonicalOption,
string strategyName)
821 throw new ArgumentException($
"{strategyName}: canonicalOption must contain canonical option symbol", nameof(canonicalOption));
828 private static void CheckExpirationDate(DateTime expiration,
string strategyName,
string parameterName)
830 if (expiration == DateTime.MaxValue || expiration == DateTime.MinValue)
832 throw new ArgumentException($
"{strategyName}: expiration must contain expiration date", parameterName);
839 private static OptionStrategy InvertStrategy(OptionStrategy strategy,
string invertedStrategyName)
841 strategy.Name = invertedStrategyName;
842 foreach (var leg
in strategy.OptionLegs.Cast<OptionStrategy.LegData>().Concat(strategy.UnderlyingLegs))