Skip to content

Commit

Permalink
[BugFix] Handle Options Skew Error From Zero/Empty IV Value (#6701)
Browse files Browse the repository at this point in the history
* handle options skew error from zero/empty IV value

* docstring touchup

* too many positional arguments

---------

Co-authored-by: Igor Radovanovic <74266147+IgorWounds@users.noreply.github.com>
  • Loading branch information
deeleeramone and IgorWounds authored Sep 27, 2024
1 parent a14e0cf commit 12f1199
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ class OptionsChainsData(OptionsChainsProperties):
Methods
-------
filter_data(
date: Optional[Union[str, int]] = None, column: Optional[str] = None,
date: Optional[Union[str, int]] = None,
column: Optional[str] = None,
option_type: Optional[Literal["call", "put"]] = None,
moneyness: Optional[Literal["otm", "itm"]] = None,
value_min: Optional[float] = None,
Expand All @@ -78,7 +79,7 @@ class OptionsChainsData(OptionsChainsProperties):
) -> DataFrame:
Return statistics by strike or expiration; or, the filtered chains data.
skew(
days: Optional[int] = None, underlying_price: Optional[float] = None)
date: Optional[Union[int, str]] = None, underlying_price: Optional[float] = None)
-> DataFrame:
Return skewness of the options, either vertical or horizontal, by nearest DTE.
straddle(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Options Chains Properties."""

# pylint: disable=too-many-lines, too-many-arguments, too-many-locals, too-many-statements
# pylint: disable=too-many-lines, too-many-arguments, too-many-locals, too-many-statements, too-many-positional-arguments

from datetime import datetime
from typing import TYPE_CHECKING, Dict, List, Literal, Optional, Union
Expand Down Expand Up @@ -1673,6 +1673,9 @@ def skew(
else data.underlying_price.iloc[0]
)

if moneyness is not None and date is None:
date = -1

if moneyness is None and date is None:
date = 30
moneyness = 20
Expand Down Expand Up @@ -1749,6 +1752,12 @@ def skew(
puts = concat([puts, put_iv]) # type: ignore
atm_put_iv = concat([atm_put_iv, atm_put]) # type: ignore

if calls.empty or puts.empty:
raise OpenBBError(
"Error: Not enough information to complete the operation."
" Likely due to zero values in the IV field of the expiration."
)

calls = calls.drop_duplicates(subset=["expiration"]).set_index("expiration") # type: ignore
atm_call_iv = atm_call_iv.drop_duplicates(subset=["expiration"]).set_index( # type: ignore
"expiration"
Expand Down Expand Up @@ -1789,10 +1798,11 @@ def skew(
call = _calls.set_index("expiration").copy() # type: ignore
call_atm_iv = call.query("`strike` == @atm_call_strike")[
"implied_volatility"
].iloc[0]
call["ATM IV"] = call_atm_iv
call["Skew"] = call["implied_volatility"] - call["ATM IV"]
call_skew = concat([call_skew, call])
]
if len(call_atm_iv) > 0:
call["ATM IV"] = call_atm_iv.iloc[0]
call["Skew"] = call["implied_volatility"] - call["ATM IV"]
call_skew = concat([call_skew, call])

atm_put_strike = self._get_nearest_strike(
"put", day, force_otm=False
Expand All @@ -1805,11 +1815,15 @@ def skew(
put = _puts.set_index("expiration").copy() # type: ignore
put_atm_iv = put.query("`strike` == @atm_put_strike")[
"implied_volatility"
].iloc[0]
put["ATM IV"] = put_atm_iv
put["Skew"] = put["implied_volatility"] - put["ATM IV"]
put_skew = concat([put_skew, put])

]
if len(put_atm_iv) > 0:
put["ATM IV"] = put_atm_iv.iloc[0]
put["Skew"] = put["implied_volatility"] - put["ATM IV"]
put_skew = concat([put_skew, put])
if call_skew.empty or put_skew.empty:
raise OpenBBError(
"Error: Not enough information to complete the operation. Likely due to zero values in the IV field."
)
call_skew = call_skew.set_index(["strike", "option_type"], append=True)
put_skew = put_skew.set_index(["strike", "option_type"], append=True)
skew_df = concat([call_skew, put_skew]).sort_index().reset_index()
Expand Down

0 comments on commit 12f1199

Please sign in to comment.