|
14 | 14 | */ |
15 | 15 |
|
16 | 16 | using System; |
| 17 | +using QuantConnect.Logging; |
17 | 18 | using QuantConnect.Orders; |
18 | 19 | using QuantConnect.Orders.Fees; |
19 | 20 |
|
@@ -55,34 +56,32 @@ public virtual OptionAssignmentResult GetAssignment(OptionAssignmentParameters p |
55 | 56 | var underlying = parameters.Option.Underlying; |
56 | 57 |
|
57 | 58 | // we take only options that expire soon |
58 | | - try |
| 59 | + if ((option.Symbol.ID.OptionStyle == OptionStyle.American && option.Symbol.ID.Date - option.LocalTime <= _priorExpiration || |
| 60 | + option.Symbol.ID.OptionStyle == OptionStyle.European && option.Symbol.ID.Date.Date == option.LocalTime.Date) |
| 61 | + // we take only deep ITM strikes |
| 62 | + && IsDeepInTheMoney(option)) |
59 | 63 | { |
60 | | - if ((option.Symbol.ID.OptionStyle == OptionStyle.American && option.Symbol.ID.Date - option.LocalTime <= _priorExpiration || |
61 | | - option.Symbol.ID.OptionStyle == OptionStyle.European && option.Symbol.ID.Date.Date == option.LocalTime.Date) |
62 | | - // we take only deep ITM strikes |
63 | | - && IsDeepInTheMoney(option)) |
| 64 | + // we estimate P/L |
| 65 | + var potentialPnL = EstimateArbitragePnL(option, (OptionHolding)option.Holdings, underlying); |
| 66 | + if (potentialPnL > 0) |
64 | 67 | { |
65 | | - // we estimate P/L |
66 | | - var potentialPnL = EstimateArbitragePnL(option, (OptionHolding)option.Holdings, underlying); |
67 | | - if (potentialPnL > 0) |
68 | | - { |
69 | | - return new OptionAssignmentResult(option.Holdings.AbsoluteQuantity, "Simulated option assignment before expiration"); |
70 | | - } |
| 68 | + return new OptionAssignmentResult(option.Holdings.AbsoluteQuantity, "Simulated option assignment before expiration"); |
71 | 69 | } |
72 | | - |
73 | | - return OptionAssignmentResult.Null; |
74 | | - } |
75 | | - catch (DivideByZeroException e) |
76 | | - { |
77 | | - throw new DivideByZeroException($"Error in DefaultOptionAssignmentModel.GetAssignment({option.Symbol.Value} :: {underlying.Symbol.ID} :: {underlying.Symbol.Value}): {e.Message}", e); |
78 | 70 | } |
| 71 | + |
| 72 | + return OptionAssignmentResult.Null; |
79 | 73 | } |
80 | 74 |
|
81 | 75 | private bool IsDeepInTheMoney(Option option) |
82 | 76 | { |
83 | 77 | var symbol = option.Symbol; |
84 | 78 | var underlyingPrice = option.Underlying.Close; |
85 | 79 |
|
| 80 | + if (underlyingPrice == 0) |
| 81 | + { |
| 82 | + Log.Error($"-----------> Underlying price is 0 for {option.Symbol}. Cannot determine if option is deep in the money."); |
| 83 | + } |
| 84 | + |
86 | 85 | // For some options, the price is based on a fraction of the underlying, such as for NQX. |
87 | 86 | // Therefore, for those options we need to scale the price when comparing it with the |
88 | 87 | // underlying. For that reason we use option.ScaledStrikePrice instead of |
|
0 commit comments