diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cbfbbe..4e86e66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## 1.5.1 (2025-12-24) + +- Added the calculation of the probability of an option ever getting ITM before expiration (see function `get_probability_of_touch` in black_scholes.py and the corresponding fields in models.py). +- Updated documentation. + ## 1.5.0 (2025-12-14) - Changed `get_pop` to compute the expected profit and expected loss of a strategy with the Black-Scholes model by calling a new function, `_compute_expected_returns_bs`. diff --git a/README.md b/README.md index 498de44..129a1ba 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,37 @@ -![OptionLab](optionlab.png) +![OptionLab](https://raw.githubusercontent.com/rgaveiga/optionlab/refs/heads/main/optionlab.png) # OptionLab -This package is a lightweight library written entirely in Python, designed to provide -quick evaluation of option strategy ideas. +This package is a lightweight library designed to provide quick evaluation of options trading +strategies. It produces various outputs: -The code produces various outputs, including the profit/loss profile of the strategy on -a user-defined target date, the range of stock prices for which the strategy is -profitable (i.e., generating a return greater than \$0.01), the Greeks associated with -each leg of the strategy using the Black-Sholes model, the resulting debit or credit on the -trading account, the maximum and minimum returns within a specified lower and higher price -range of the underlying asset, and an estimate of the strategy's probability of profit. +- the profit/loss profile of the strategy on a user-defined target date + +- the range of stock prices for which the strategy is profitable (i.e., generating a return of +at least \$0.01) + +- the Greeks (delta, theta, rho, vega and gamma) associated with each leg of the strategy + +- the resulting debit or credit on the trading account + +- the maximum and minimum returns within a specified lower and higher price +range of the underlying asset + +- The expected profit when the strategy is profitable and the expected loss if it proves unprofitable + +- the strategy's probability of profit. + +## Contact If you have any questions, corrections, comments or suggestions, just [drop a message](mailto:roberto.veiga@ufabc.edu.br). You can also reach me on [Linkedin](https://www.linkedin.com/in/roberto-gomes-phd-8a718317b/) or -follow me on [X](https://x.com/rgaveiga). When I have some free time, which is rare, I publish articles -on [Medium](https://medium.com/@rgaveiga). +follow me on [X](https://x.com/rgaveiga). -If you want to support this and other open source projects that I maintain, become a -[sponsor on Github](https://github.com/sponsors/rgaveiga). +> [!NOTE] +> If you want to support this and other open source projects that I maintain, become a +>[sponsor on Github](https://github.com/sponsors/rgaveiga). ## Installation @@ -48,8 +59,9 @@ This is free software and is provided as is. The author makes no guarantee that results are accurate and is not responsible for any losses caused by the use of the code. -Options are very risky derivatives and, like any other type of financial vehicle, -trading options requires due diligence. This code is provided for educational and -research purposes only. - Bugs can be reported as issues. + +> [!CAUTION] +> Options are very risky derivatives and, like any other type of financial vehicle, +> trading options requires due diligence. This code is provided for educational and +> research purposes only. diff --git a/docs/optionlab.html b/docs/optionlab.html index c8d756e..de5a36a 100644 --- a/docs/optionlab.html +++ b/docs/optionlab.html @@ -369,7 +369,7 @@

Examples

155from .utils import get_pl, pl_to_csv 156 157__docformat__ = "markdown" -158__version__ = "1.5.0" +158__version__ = "1.5.1" diff --git a/docs/optionlab/black_scholes.html b/docs/optionlab/black_scholes.html index 1f72576..7af4859 100644 --- a/docs/optionlab/black_scholes.html +++ b/docs/optionlab/black_scholes.html @@ -64,6 +64,9 @@

API Documentation

  • get_itm_probability
  • +
  • + get_probability_of_touch +
  • @@ -147,427 +150,500 @@

    57 put_rho = get_rho("put", x, r, years_to_maturity, d2) 58 call_itm_prob = get_itm_probability("call", d2, years_to_maturity, y) 59 put_itm_prob = get_itm_probability("put", d2, years_to_maturity, y) - 60 - 61 return BlackScholesInfo( - 62 call_price=call_price, - 63 put_price=put_price, - 64 call_delta=call_delta, - 65 put_delta=put_delta, - 66 call_theta=call_theta, - 67 put_theta=put_theta, - 68 gamma=gamma, - 69 vega=vega, - 70 call_rho=call_rho, - 71 put_rho=put_rho, - 72 call_itm_prob=call_itm_prob, - 73 put_itm_prob=put_itm_prob, - 74 ) - 75 - 76 - 77def get_option_price( - 78 option_type: OptionType, - 79 s0: FloatOrNdarray, - 80 x: FloatOrNdarray, - 81 r: float, - 82 years_to_maturity: float, - 83 d1: FloatOrNdarray, - 84 d2: FloatOrNdarray, - 85 y: float = 0.0, - 86) -> FloatOrNdarray: - 87 """ - 88 Returns the price of an option. - 89 - 90 ### Parameters - 91 - 92 `option_type`: either *'call'* or *'put'*. - 93 - 94 `s0`: spot price(s) of the underlying asset. - 95 - 96 `x`: strike price(s). + 60 call_prob_of_touch = get_probability_of_touch( + 61 "call", s, x, r, vol, years_to_maturity, y + 62 ) + 63 put_prob_of_touch = get_probability_of_touch( + 64 "put", s, x, r, vol, years_to_maturity, y + 65 ) + 66 + 67 return BlackScholesInfo( + 68 call_price=call_price, + 69 put_price=put_price, + 70 call_delta=call_delta, + 71 put_delta=put_delta, + 72 call_theta=call_theta, + 73 put_theta=put_theta, + 74 gamma=gamma, + 75 vega=vega, + 76 call_rho=call_rho, + 77 put_rho=put_rho, + 78 call_itm_prob=call_itm_prob, + 79 put_itm_prob=put_itm_prob, + 80 call_prob_of_touch=call_prob_of_touch, + 81 put_prob_of_touch=put_prob_of_touch, + 82 ) + 83 + 84 + 85def get_option_price( + 86 option_type: OptionType, + 87 s0: FloatOrNdarray, + 88 x: FloatOrNdarray, + 89 r: float, + 90 years_to_maturity: float, + 91 d1: FloatOrNdarray, + 92 d2: FloatOrNdarray, + 93 y: float = 0.0, + 94) -> FloatOrNdarray: + 95 """ + 96 Returns the price of an option. 97 - 98 `r`: annualize risk-free interest rate. + 98 ### Parameters 99 -100 `years_to_maturity`: time remaining to maturity, in years. +100 `option_type`: either *'call'* or *'put'*. 101 -102 `d1`: `d1` in Black-Scholes formula. +102 `s0`: spot price(s) of the underlying asset. 103 -104 `d2`: `d2` in Black-Scholes formula. +104 `x`: strike price(s). 105 -106 `y`: annualized dividend yield. +106 `r`: annualize risk-free interest rate. 107 -108 ### Returns +108 `years_to_maturity`: time remaining to maturity, in years. 109 -110 Option price(s). -111 """ -112 -113 s = s0 * exp(-y * years_to_maturity) -114 -115 if option_type == "call": -116 return round( -117 s * stats.norm.cdf(d1) -118 - x * exp(-r * years_to_maturity) * stats.norm.cdf(d2), -119 2, -120 ) -121 elif option_type == "put": -122 return round( -123 x * exp(-r * years_to_maturity) * stats.norm.cdf(-d2) -124 - s * stats.norm.cdf(-d1), -125 2, -126 ) -127 else: -128 raise ValueError("Option type must be either 'call' or 'put'!") -129 -130 -131def get_delta( -132 option_type: OptionType, -133 d1: FloatOrNdarray, -134 years_to_maturity: float, -135 y: float = 0.0, -136) -> FloatOrNdarray: -137 """ -138 Returns the option's Greek Delta. -139 -140 ### Parameters -141 -142 `option_type`: either *'call'* or *'put'*. -143 -144 `d1`: `d1` in Black-Scholes formula. -145 -146 `years_to_maturity`: time remaining to maturity, in years. +110 `d1`: `d1` in Black-Scholes formula. +111 +112 `d2`: `d2` in Black-Scholes formula. +113 +114 `y`: annualized dividend yield. +115 +116 ### Returns +117 +118 Option price(s). +119 """ +120 +121 s = s0 * exp(-y * years_to_maturity) +122 +123 if option_type == "call": +124 return round( +125 s * stats.norm.cdf(d1) +126 - x * exp(-r * years_to_maturity) * stats.norm.cdf(d2), +127 2, +128 ) +129 elif option_type == "put": +130 return round( +131 x * exp(-r * years_to_maturity) * stats.norm.cdf(-d2) +132 - s * stats.norm.cdf(-d1), +133 2, +134 ) +135 else: +136 raise ValueError("Option type must be either 'call' or 'put'!") +137 +138 +139def get_delta( +140 option_type: OptionType, +141 d1: FloatOrNdarray, +142 years_to_maturity: float, +143 y: float = 0.0, +144) -> FloatOrNdarray: +145 """ +146 Returns the option's Greek Delta. 147 -148 `y`: annualized dividend yield. +148 ### Parameters 149 -150 ### Returns +150 `option_type`: either *'call'* or *'put'*. 151 -152 Option's Greek Delta. -153 """ -154 -155 yfac = exp(-y * years_to_maturity) -156 -157 if option_type == "call": -158 return yfac * stats.norm.cdf(d1) -159 elif option_type == "put": -160 return yfac * (stats.norm.cdf(d1) - 1.0) -161 else: -162 raise ValueError("Option must be either 'call' or 'put'!") -163 +152 `d1`: `d1` in Black-Scholes formula. +153 +154 `years_to_maturity`: time remaining to maturity, in years. +155 +156 `y`: annualized dividend yield. +157 +158 ### Returns +159 +160 Option's Greek Delta. +161 """ +162 +163 yfac = exp(-y * years_to_maturity) 164 -165def get_gamma( -166 s0: float, -167 vol: float, -168 years_to_maturity: float, -169 d1: FloatOrNdarray, -170 y: float = 0.0, -171) -> FloatOrNdarray: -172 """ -173 Returns the option's Greek Gamma. -174 -175 ### Parameters -176 -177 `s0`: spot price of the underlying asset. -178 -179 `vol`: annualized volatitily. -180 -181 `years_to_maturity`: time remaining to maturity, in years. +165 if option_type == "call": +166 return yfac * stats.norm.cdf(d1) +167 elif option_type == "put": +168 return yfac * (stats.norm.cdf(d1) - 1.0) +169 else: +170 raise ValueError("Option must be either 'call' or 'put'!") +171 +172 +173def get_gamma( +174 s0: float, +175 vol: float, +176 years_to_maturity: float, +177 d1: FloatOrNdarray, +178 y: float = 0.0, +179) -> FloatOrNdarray: +180 """ +181 Returns the option's Greek Gamma. 182 -183 `d1`: `d1` in Black-Scholes formula. +183 ### Parameters 184 -185 `y`: annualized divident yield. +185 `s0`: spot price of the underlying asset. 186 -187 ### Returns +187 `vol`: annualized volatitily. 188 -189 Option's Greek Gamma. -190 """ -191 -192 yfac = exp(-y * years_to_maturity) -193 -194 cdf_d1_prime = exp(-0.5 * d1 * d1) / sqrt(2.0 * pi) -195 -196 return yfac * cdf_d1_prime / (s0 * vol * sqrt(years_to_maturity)) -197 -198 -199def get_theta( -200 option_type: OptionType, -201 s0: float, -202 x: FloatOrNdarray, -203 r: float, -204 vol: float, -205 years_to_maturity: float, -206 d1: FloatOrNdarray, -207 d2: FloatOrNdarray, -208 y: float = 0.0, -209) -> FloatOrNdarray: -210 """ -211 Returns the option's Greek Theta. -212 -213 ### Parameters -214 -215 `option_type`: either *'call'* or *'put'*. -216 -217 `s0`: spot price of the underlying asset. -218 -219 `x`: strike price(s). +189 `years_to_maturity`: time remaining to maturity, in years. +190 +191 `d1`: `d1` in Black-Scholes formula. +192 +193 `y`: annualized divident yield. +194 +195 ### Returns +196 +197 Option's Greek Gamma. +198 """ +199 +200 yfac = exp(-y * years_to_maturity) +201 +202 cdf_d1_prime = exp(-0.5 * d1 * d1) / sqrt(2.0 * pi) +203 +204 return yfac * cdf_d1_prime / (s0 * vol * sqrt(years_to_maturity)) +205 +206 +207def get_theta( +208 option_type: OptionType, +209 s0: float, +210 x: FloatOrNdarray, +211 r: float, +212 vol: float, +213 years_to_maturity: float, +214 d1: FloatOrNdarray, +215 d2: FloatOrNdarray, +216 y: float = 0.0, +217) -> FloatOrNdarray: +218 """ +219 Returns the option's Greek Theta. 220 -221 `r`: annualized risk-free interest rate. +221 ### Parameters 222 -223 `vol`: annualized volatility. +223 `option_type`: either *'call'* or *'put'*. 224 -225 `years_to_maturity`: time remaining to maturity, in years. +225 `s0`: spot price of the underlying asset. 226 -227 `d1`: `d1` in Black-Scholes formula. +227 `x`: strike price(s). 228 -229 `d2`: `d2` in Black-Scholes formula. +229 `r`: annualized risk-free interest rate. 230 -231 `y`: annualized dividend yield. +231 `vol`: annualized volatility. 232 -233 ### Returns +233 `years_to_maturity`: time remaining to maturity, in years. 234 -235 Option's Greek Theta. -236 """ -237 -238 s = s0 * exp(-y * years_to_maturity) -239 -240 cdf_d1_prime = exp(-0.5 * d1 * d1) / sqrt(2.0 * pi) -241 -242 if option_type == "call": -243 return -( -244 s * vol * cdf_d1_prime / (2.0 * sqrt(years_to_maturity)) -245 + r * x * exp(-r * years_to_maturity) * stats.norm.cdf(d2) -246 - y * s * stats.norm.cdf(d1) -247 ) -248 elif option_type == "put": -249 return -( -250 s * vol * cdf_d1_prime / (2.0 * sqrt(years_to_maturity)) -251 - r * x * exp(-r * years_to_maturity) * stats.norm.cdf(-d2) -252 + y * s * stats.norm.cdf(-d1) -253 ) -254 else: -255 raise ValueError("Option type must be either 'call' or 'put'!") -256 -257 -258def get_vega( -259 s0: float, -260 years_to_maturity: float, -261 d1: FloatOrNdarray, -262 y: float = 0.0, -263) -> FloatOrNdarray: -264 """ -265 Returns the option's Greek Vega. -266 -267 ### Parameters -268 -269 `s0`: spot price of the underlying asset. -270 -271 `years_to_maturity`: time remaining to maturity, in years. -272 -273 `d1`: `d1` in Black-Scholes formula. +235 `d1`: `d1` in Black-Scholes formula. +236 +237 `d2`: `d2` in Black-Scholes formula. +238 +239 `y`: annualized dividend yield. +240 +241 ### Returns +242 +243 Option's Greek Theta. +244 """ +245 +246 s = s0 * exp(-y * years_to_maturity) +247 +248 cdf_d1_prime = exp(-0.5 * d1 * d1) / sqrt(2.0 * pi) +249 +250 if option_type == "call": +251 return -( +252 s * vol * cdf_d1_prime / (2.0 * sqrt(years_to_maturity)) +253 + r * x * exp(-r * years_to_maturity) * stats.norm.cdf(d2) +254 - y * s * stats.norm.cdf(d1) +255 ) +256 elif option_type == "put": +257 return -( +258 s * vol * cdf_d1_prime / (2.0 * sqrt(years_to_maturity)) +259 - r * x * exp(-r * years_to_maturity) * stats.norm.cdf(-d2) +260 + y * s * stats.norm.cdf(-d1) +261 ) +262 else: +263 raise ValueError("Option type must be either 'call' or 'put'!") +264 +265 +266def get_vega( +267 s0: float, +268 years_to_maturity: float, +269 d1: FloatOrNdarray, +270 y: float = 0.0, +271) -> FloatOrNdarray: +272 """ +273 Returns the option's Greek Vega. 274 -275 `y`: annualized dividend yield. +275 ### Parameters 276 -277 ### Returns +277 `s0`: spot price of the underlying asset. 278 -279 Option's Greek Vega. -280 """ -281 -282 s = s0 * exp(-y * years_to_maturity) -283 -284 cdf_d1_prime = exp(-0.5 * d1 * d1) / sqrt(2.0 * pi) -285 -286 return s * cdf_d1_prime * sqrt(years_to_maturity) / 100 -287 -288 -289def get_rho( -290 option_type: OptionType, -291 x: FloatOrNdarray, -292 r: float, -293 years_to_maturity: float, -294 d2: FloatOrNdarray, -295) -> FloatOrNdarray: -296 """ -297 Returns the option's Greek Rho. -298 -299 ### Parameters -300 -301 `option_type`: either *'call'* or *'put'*. -302 -303 `x`: strike price(s). -304 -305 `r`: annualized risk-free interest rate. +279 `years_to_maturity`: time remaining to maturity, in years. +280 +281 `d1`: `d1` in Black-Scholes formula. +282 +283 `y`: annualized dividend yield. +284 +285 ### Returns +286 +287 Option's Greek Vega. +288 """ +289 +290 s = s0 * exp(-y * years_to_maturity) +291 +292 cdf_d1_prime = exp(-0.5 * d1 * d1) / sqrt(2.0 * pi) +293 +294 return s * cdf_d1_prime * sqrt(years_to_maturity) / 100 +295 +296 +297def get_rho( +298 option_type: OptionType, +299 x: FloatOrNdarray, +300 r: float, +301 years_to_maturity: float, +302 d2: FloatOrNdarray, +303) -> FloatOrNdarray: +304 """ +305 Returns the option's Greek Rho. 306 -307 `years_to_maturity`: time remaining to maturity, in years. +307 ### Parameters 308 -309 `d2`: `d2` in Black-Scholes formula. +309 `option_type`: either *'call'* or *'put'*. 310 -311 ### Returns +311 `x`: strike price(s). 312 -313 Option's Greek Rho. -314 """ -315 -316 if option_type == "call": -317 return ( -318 x -319 * years_to_maturity -320 * exp(-r * years_to_maturity) -321 * stats.norm.cdf(d2) -322 / 100 -323 ) -324 elif option_type == "put": +313 `r`: annualized risk-free interest rate. +314 +315 `years_to_maturity`: time remaining to maturity, in years. +316 +317 `d2`: `d2` in Black-Scholes formula. +318 +319 ### Returns +320 +321 Option's Greek Rho. +322 """ +323 +324 if option_type == "call": 325 return ( -326 -x +326 x 327 * years_to_maturity 328 * exp(-r * years_to_maturity) -329 * stats.norm.cdf(-d2) +329 * stats.norm.cdf(d2) 330 / 100 331 ) -332 else: -333 raise ValueError("Option must be either 'call' or 'put'!") -334 -335 -336def get_d1( -337 s0: FloatOrNdarray, -338 x: FloatOrNdarray, -339 r: float, -340 vol: FloatOrNdarray, -341 years_to_maturity: float, -342 y: float = 0.0, -343) -> FloatOrNdarray: -344 """ -345 Returns `d1` used in Black-Scholes formula. -346 -347 ### Parameters -348 -349 `s0`: spot price(s) of the underlying asset. -350 -351 `x`: strike price(s). -352 -353 `r`: annualized risk-free interest rate. +332 elif option_type == "put": +333 return ( +334 -x +335 * years_to_maturity +336 * exp(-r * years_to_maturity) +337 * stats.norm.cdf(-d2) +338 / 100 +339 ) +340 else: +341 raise ValueError("Option must be either 'call' or 'put'!") +342 +343 +344def get_d1( +345 s0: FloatOrNdarray, +346 x: FloatOrNdarray, +347 r: float, +348 vol: FloatOrNdarray, +349 years_to_maturity: float, +350 y: float = 0.0, +351) -> FloatOrNdarray: +352 """ +353 Returns `d1` used in Black-Scholes formula. 354 -355 `vol`: annualized volatility(ies). +355 ### Parameters 356 -357 `years_to_maturity`: time remaining to maturity, in years. +357 `s0`: spot price(s) of the underlying asset. 358 -359 `y`: annualized divident yield. +359 `x`: strike price(s). 360 -361 ### Returns +361 `r`: annualized risk-free interest rate. 362 -363 `d1` in Black-Scholes formula. -364 """ -365 -366 return (log(s0 / x) + (r - y + vol * vol / 2.0) * years_to_maturity) / ( -367 vol * sqrt(years_to_maturity) -368 ) -369 +363 `vol`: annualized volatility(ies). +364 +365 `years_to_maturity`: time remaining to maturity, in years. +366 +367 `y`: annualized divident yield. +368 +369 ### Returns 370 -371def get_d2( -372 s0: FloatOrNdarray, -373 x: FloatOrNdarray, -374 r: float, -375 vol: FloatOrNdarray, -376 years_to_maturity: float, -377 y: float = 0.0, -378) -> FloatOrNdarray: -379 """ -380 Returns `d2` used in Black-Scholes formula. -381 -382 ### Parameters -383 -384 `s0`: spot price(s) of the underlying asset. -385 -386 `x`: strike price(s). -387 -388 `r`: annualized risk-free interest rate. +371 `d1` in Black-Scholes formula. +372 """ +373 +374 return (log(s0 / x) + (r - y + vol * vol / 2.0) * years_to_maturity) / ( +375 vol * sqrt(years_to_maturity) +376 ) +377 +378 +379def get_d2( +380 s0: FloatOrNdarray, +381 x: FloatOrNdarray, +382 r: float, +383 vol: FloatOrNdarray, +384 years_to_maturity: float, +385 y: float = 0.0, +386) -> FloatOrNdarray: +387 """ +388 Returns `d2` used in Black-Scholes formula. 389 -390 `vol`: annualized volatility(ies). +390 ### Parameters 391 -392 `years_to_maturity`: time remaining to maturity, in years. +392 `s0`: spot price(s) of the underlying asset. 393 -394 `y`: annualized divident yield. +394 `x`: strike price(s). 395 -396 ### Returns +396 `r`: annualized risk-free interest rate. 397 -398 `d2` in Black-Scholes formula. -399 """ -400 -401 return (log(s0 / x) + (r - y - vol * vol / 2.0) * years_to_maturity) / ( -402 vol * sqrt(years_to_maturity) -403 ) -404 +398 `vol`: annualized volatility(ies). +399 +400 `years_to_maturity`: time remaining to maturity, in years. +401 +402 `y`: annualized divident yield. +403 +404 ### Returns 405 -406def get_implied_vol( -407 option_type: OptionType, -408 oprice: float, -409 s0: float, -410 x: float, -411 r: float, -412 years_to_maturity: float, -413 y: float = 0.0, -414) -> float: -415 """ -416 Returns the implied volatility of an option. -417 -418 ### Parameters -419 -420 `option_type`: either *'call'* or *'put'*. -421 -422 `oprice`: market price of an option. -423 -424 `s0`: spot price of the underlying asset. +406 `d2` in Black-Scholes formula. +407 """ +408 +409 return (log(s0 / x) + (r - y - vol * vol / 2.0) * years_to_maturity) / ( +410 vol * sqrt(years_to_maturity) +411 ) +412 +413 +414def get_implied_vol( +415 option_type: OptionType, +416 oprice: float, +417 s0: float, +418 x: float, +419 r: float, +420 years_to_maturity: float, +421 y: float = 0.0, +422) -> float: +423 """ +424 Returns the implied volatility of an option. 425 -426 `x`: strike price. +426 ### Parameters 427 -428 `r`: annualized risk-free interest rate. +428 `option_type`: either *'call'* or *'put'*. 429 -430 `years_to_maturity`: time remaining to maturity, in years. +430 `oprice`: market price of an option. 431 -432 `y`: annualized dividend yield. +432 `s0`: spot price of the underlying asset. 433 -434 ### Returns +434 `x`: strike price. 435 -436 Option's implied volatility. -437 """ -438 -439 vol = 0.001 * arange(1, 1001) -440 d1 = get_d1(s0, x, r, vol, years_to_maturity, y) -441 d2 = get_d2(s0, x, r, vol, years_to_maturity, y) -442 dopt = abs( -443 get_option_price(option_type, s0, x, r, years_to_maturity, d1, d2, y) - oprice -444 ) -445 -446 return vol[argmin(dopt)] -447 -448 -449def get_itm_probability( -450 option_type: OptionType, -451 d2: FloatOrNdarray, -452 years_to_maturity: float, -453 y: float = 0.0, -454) -> FloatOrNdarray: -455 """ -456 Returns the probability(ies) that the option(s) will expire in-the-money (ITM). -457 -458 ### Parameters -459 -460 `option_type`: either *'call'* or *'put'*. -461 -462 `d2`: `d2` in Black-Scholes formula. -463 -464 `years_to_maturity`: time remaining to maturity, in years. +436 `r`: annualized risk-free interest rate. +437 +438 `years_to_maturity`: time remaining to maturity, in years. +439 +440 `y`: annualized dividend yield. +441 +442 ### Returns +443 +444 Option's implied volatility. +445 """ +446 +447 vol = 0.001 * arange(1, 1001) +448 d1 = get_d1(s0, x, r, vol, years_to_maturity, y) +449 d2 = get_d2(s0, x, r, vol, years_to_maturity, y) +450 dopt = abs( +451 get_option_price(option_type, s0, x, r, years_to_maturity, d1, d2, y) - oprice +452 ) +453 +454 return vol[argmin(dopt)] +455 +456 +457def get_itm_probability( +458 option_type: OptionType, +459 d2: FloatOrNdarray, +460 years_to_maturity: float, +461 y: float = 0.0, +462) -> FloatOrNdarray: +463 """ +464 Returns the probability(ies) that the option(s) will expire in-the-money (ITM). 465 -466 `y`: annualized dividend yield. +466 ### Parameters 467 -468 ### Returns +468 `option_type`: either *'call'* or *'put'*. 469 -470 Probability(ies) that the option(s) will expire in-the-money (ITM). -471 """ -472 -473 yfac = exp(-y * years_to_maturity) -474 -475 if option_type == "call": -476 return yfac * stats.norm.cdf(d2) -477 elif option_type == "put": -478 return yfac * stats.norm.cdf(-d2) -479 else: -480 raise ValueError("Option type must be either 'call' or 'put'!") +470 `d2`: `d2` in Black-Scholes formula. +471 +472 `years_to_maturity`: time remaining to maturity, in years. +473 +474 `y`: annualized dividend yield. +475 +476 ### Returns +477 +478 Probability(ies) that the option(s) will expire in-the-money (ITM). +479 """ +480 +481 yfac = exp(-y * years_to_maturity) +482 +483 if option_type == "call": +484 return yfac * stats.norm.cdf(d2) +485 elif option_type == "put": +486 return yfac * stats.norm.cdf(-d2) +487 else: +488 raise ValueError("Option type must be either 'call' or 'put'!") +489 +490 +491def get_probability_of_touch( +492 option_type: OptionType, +493 s: float, +494 x: FloatOrNdarray, +495 r: float, +496 vol: float, +497 years_to_maturity: float, +498 y: float = 0.0, +499) -> FloatOrNdarray: +500 """ +501 Returns the probability(ies) that the option(s) will ever get in-the-money (ITM) +502 before expiration. +503 +504 > [!NOTE] +505 > This function implements equations 2.66 and 2.67 (see pages 80 and 81) in +506 > *The complete guide to option pricing formulas*, 2nd edition, authored by +507 > Espen Gaarder Haug, PhD, and published by McGraw-Hill. +508 +509 ### Parameters +510 +511 `option_type`: either *'call'* or *'put'*. +512 +513 `s`: stock price. +514 +515 `x`: strike price(s). +516 +517 `r`: annualized risk-free interest rate. +518 +519 `vol`: annualized volatility. +520 +521 `years_to_maturity`: time remaining to maturity, in years. +522 +523 `y`: annualized dividend yield. +524 +525 ### Returns +526 +527 Probability(ies) that the option(s) will ever get in-the-money (ITM) before +528 expiration. +529 """ +530 +531 mu = (r - y - 0.5 * vol * vol) / (vol * vol) +532 lam = sqrt((mu * mu) + 2.0 * r / (vol * vol)) +533 sigma = vol * sqrt(years_to_maturity) +534 z = log(x / s) / sigma + lam * sigma +535 exp1 = mu + lam +536 exp2 = mu - lam +537 +538 if option_type == "call": +539 if s >= x: +540 return 1.0 +541 else: +542 return ((x / s) ** exp1) * stats.norm.cdf(-z) + ( +543 (x / s) ** exp2 +544 ) * stats.norm.cdf(2.0 * lam * sigma - z) +545 elif option_type == "put": +546 if s <= x: +547 return 1.0 +548 else: +549 return ((x / s) ** exp1) * stats.norm.cdf(z) + ( +550 (x / s) ** exp2 +551 ) * stats.norm.cdf(z - 2.0 * lam * sigma) +552 else: +553 raise ValueError("Option type must be either 'call' or 'put'!") @@ -628,21 +704,29 @@

    58 put_rho = get_rho("put", x, r, years_to_maturity, d2) 59 call_itm_prob = get_itm_probability("call", d2, years_to_maturity, y) 60 put_itm_prob = get_itm_probability("put", d2, years_to_maturity, y) -61 -62 return BlackScholesInfo( -63 call_price=call_price, -64 put_price=put_price, -65 call_delta=call_delta, -66 put_delta=put_delta, -67 call_theta=call_theta, -68 put_theta=put_theta, -69 gamma=gamma, -70 vega=vega, -71 call_rho=call_rho, -72 put_rho=put_rho, -73 call_itm_prob=call_itm_prob, -74 put_itm_prob=put_itm_prob, -75 ) +61 call_prob_of_touch = get_probability_of_touch( +62 "call", s, x, r, vol, years_to_maturity, y +63 ) +64 put_prob_of_touch = get_probability_of_touch( +65 "put", s, x, r, vol, years_to_maturity, y +66 ) +67 +68 return BlackScholesInfo( +69 call_price=call_price, +70 put_price=put_price, +71 call_delta=call_delta, +72 put_delta=put_delta, +73 call_theta=call_theta, +74 put_theta=put_theta, +75 gamma=gamma, +76 vega=vega, +77 call_rho=call_rho, +78 put_rho=put_rho, +79 call_itm_prob=call_itm_prob, +80 put_itm_prob=put_itm_prob, +81 call_prob_of_touch=call_prob_of_touch, +82 put_prob_of_touch=put_prob_of_touch, +83 ) @@ -681,58 +765,58 @@

    Returns

    -
     78def get_option_price(
    - 79    option_type: OptionType,
    - 80    s0: FloatOrNdarray,
    - 81    x: FloatOrNdarray,
    - 82    r: float,
    - 83    years_to_maturity: float,
    - 84    d1: FloatOrNdarray,
    - 85    d2: FloatOrNdarray,
    - 86    y: float = 0.0,
    - 87) -> FloatOrNdarray:
    - 88    """
    - 89    Returns the price of an option.
    - 90
    - 91    ### Parameters
    - 92
    - 93    `option_type`: either *'call'* or *'put'*.
    - 94
    - 95    `s0`: spot price(s) of the underlying asset.
    - 96
    - 97    `x`: strike price(s).
    +            
     86def get_option_price(
    + 87    option_type: OptionType,
    + 88    s0: FloatOrNdarray,
    + 89    x: FloatOrNdarray,
    + 90    r: float,
    + 91    years_to_maturity: float,
    + 92    d1: FloatOrNdarray,
    + 93    d2: FloatOrNdarray,
    + 94    y: float = 0.0,
    + 95) -> FloatOrNdarray:
    + 96    """
    + 97    Returns the price of an option.
      98
    - 99    `r`: annualize risk-free interest rate.
    + 99    ### Parameters
     100
    -101    `years_to_maturity`: time remaining to maturity, in years.
    +101    `option_type`: either *'call'* or *'put'*.
     102
    -103    `d1`: `d1` in Black-Scholes formula.
    +103    `s0`: spot price(s) of the underlying asset.
     104
    -105    `d2`: `d2` in Black-Scholes formula.
    +105    `x`: strike price(s).
     106
    -107    `y`: annualized dividend yield.
    +107    `r`: annualize risk-free interest rate.
     108
    -109    ### Returns
    +109    `years_to_maturity`: time remaining to maturity, in years.
     110
    -111    Option price(s).
    -112    """
    -113
    -114    s = s0 * exp(-y * years_to_maturity)
    -115
    -116    if option_type == "call":
    -117        return round(
    -118            s * stats.norm.cdf(d1)
    -119            - x * exp(-r * years_to_maturity) * stats.norm.cdf(d2),
    -120            2,
    -121        )
    -122    elif option_type == "put":
    -123        return round(
    -124            x * exp(-r * years_to_maturity) * stats.norm.cdf(-d2)
    -125            - s * stats.norm.cdf(-d1),
    -126            2,
    -127        )
    -128    else:
    -129        raise ValueError("Option type must be either 'call' or 'put'!")
    +111    `d1`: `d1` in Black-Scholes formula.
    +112
    +113    `d2`: `d2` in Black-Scholes formula.
    +114
    +115    `y`: annualized dividend yield.
    +116
    +117    ### Returns
    +118
    +119    Option price(s).
    +120    """
    +121
    +122    s = s0 * exp(-y * years_to_maturity)
    +123
    +124    if option_type == "call":
    +125        return round(
    +126            s * stats.norm.cdf(d1)
    +127            - x * exp(-r * years_to_maturity) * stats.norm.cdf(d2),
    +128            2,
    +129        )
    +130    elif option_type == "put":
    +131        return round(
    +132            x * exp(-r * years_to_maturity) * stats.norm.cdf(-d2)
    +133            - s * stats.norm.cdf(-d1),
    +134            2,
    +135        )
    +136    else:
    +137        raise ValueError("Option type must be either 'call' or 'put'!")
     
    @@ -774,38 +858,38 @@

    Returns

    -
    132def get_delta(
    -133    option_type: OptionType,
    -134    d1: FloatOrNdarray,
    -135    years_to_maturity: float,
    -136    y: float = 0.0,
    -137) -> FloatOrNdarray:
    -138    """
    -139    Returns the option's Greek Delta.
    -140
    -141    ### Parameters
    -142
    -143    `option_type`: either *'call'* or *'put'*.
    -144
    -145    `d1`: `d1` in Black-Scholes formula.
    -146
    -147    `years_to_maturity`: time remaining to maturity, in years.
    +            
    140def get_delta(
    +141    option_type: OptionType,
    +142    d1: FloatOrNdarray,
    +143    years_to_maturity: float,
    +144    y: float = 0.0,
    +145) -> FloatOrNdarray:
    +146    """
    +147    Returns the option's Greek Delta.
     148
    -149    `y`: annualized dividend yield.
    +149    ### Parameters
     150
    -151    ### Returns
    +151    `option_type`: either *'call'* or *'put'*.
     152
    -153    Option's Greek Delta.
    -154    """
    -155
    -156    yfac = exp(-y * years_to_maturity)
    -157
    -158    if option_type == "call":
    -159        return yfac * stats.norm.cdf(d1)
    -160    elif option_type == "put":
    -161        return yfac * (stats.norm.cdf(d1) - 1.0)
    -162    else:
    -163        raise ValueError("Option must be either 'call' or 'put'!")
    +153    `d1`: `d1` in Black-Scholes formula.
    +154
    +155    `years_to_maturity`: time remaining to maturity, in years.
    +156
    +157    `y`: annualized dividend yield.
    +158
    +159    ### Returns
    +160
    +161    Option's Greek Delta.
    +162    """
    +163
    +164    yfac = exp(-y * years_to_maturity)
    +165
    +166    if option_type == "call":
    +167        return yfac * stats.norm.cdf(d1)
    +168    elif option_type == "put":
    +169        return yfac * (stats.norm.cdf(d1) - 1.0)
    +170    else:
    +171        raise ValueError("Option must be either 'call' or 'put'!")
     
    @@ -839,38 +923,38 @@

    Returns

    -
    166def get_gamma(
    -167    s0: float,
    -168    vol: float,
    -169    years_to_maturity: float,
    -170    d1: FloatOrNdarray,
    -171    y: float = 0.0,
    -172) -> FloatOrNdarray:
    -173    """
    -174    Returns the option's Greek Gamma.
    -175
    -176    ### Parameters
    -177
    -178    `s0`: spot price of the underlying asset.
    -179
    -180    `vol`: annualized volatitily.
    -181
    -182    `years_to_maturity`: time remaining to maturity, in years.
    +            
    174def get_gamma(
    +175    s0: float,
    +176    vol: float,
    +177    years_to_maturity: float,
    +178    d1: FloatOrNdarray,
    +179    y: float = 0.0,
    +180) -> FloatOrNdarray:
    +181    """
    +182    Returns the option's Greek Gamma.
     183
    -184    `d1`: `d1` in Black-Scholes formula.
    +184    ### Parameters
     185
    -186    `y`: annualized divident yield.
    +186    `s0`: spot price of the underlying asset.
     187
    -188    ### Returns
    +188    `vol`: annualized volatitily.
     189
    -190    Option's Greek Gamma.
    -191    """
    -192
    -193    yfac = exp(-y * years_to_maturity)
    -194
    -195    cdf_d1_prime = exp(-0.5 * d1 * d1) / sqrt(2.0 * pi)
    -196
    -197    return yfac * cdf_d1_prime / (s0 * vol * sqrt(years_to_maturity))
    +190    `years_to_maturity`: time remaining to maturity, in years.
    +191
    +192    `d1`: `d1` in Black-Scholes formula.
    +193
    +194    `y`: annualized divident yield.
    +195
    +196    ### Returns
    +197
    +198    Option's Greek Gamma.
    +199    """
    +200
    +201    yfac = exp(-y * years_to_maturity)
    +202
    +203    cdf_d1_prime = exp(-0.5 * d1 * d1) / sqrt(2.0 * pi)
    +204
    +205    return yfac * cdf_d1_prime / (s0 * vol * sqrt(years_to_maturity))
     
    @@ -906,63 +990,63 @@

    Returns

    -
    200def get_theta(
    -201    option_type: OptionType,
    -202    s0: float,
    -203    x: FloatOrNdarray,
    -204    r: float,
    -205    vol: float,
    -206    years_to_maturity: float,
    -207    d1: FloatOrNdarray,
    -208    d2: FloatOrNdarray,
    -209    y: float = 0.0,
    -210) -> FloatOrNdarray:
    -211    """
    -212    Returns the option's Greek Theta.
    -213
    -214    ### Parameters
    -215
    -216    `option_type`: either *'call'* or *'put'*.
    -217
    -218    `s0`: spot price of the underlying asset.
    -219
    -220    `x`: strike price(s).
    +            
    208def get_theta(
    +209    option_type: OptionType,
    +210    s0: float,
    +211    x: FloatOrNdarray,
    +212    r: float,
    +213    vol: float,
    +214    years_to_maturity: float,
    +215    d1: FloatOrNdarray,
    +216    d2: FloatOrNdarray,
    +217    y: float = 0.0,
    +218) -> FloatOrNdarray:
    +219    """
    +220    Returns the option's Greek Theta.
     221
    -222    `r`: annualized risk-free interest rate.
    +222    ### Parameters
     223
    -224    `vol`: annualized volatility.
    +224    `option_type`: either *'call'* or *'put'*.
     225
    -226    `years_to_maturity`: time remaining to maturity, in years.
    +226    `s0`: spot price of the underlying asset.
     227
    -228    `d1`: `d1` in Black-Scholes formula.
    +228    `x`: strike price(s).
     229
    -230    `d2`: `d2` in Black-Scholes formula.
    +230    `r`: annualized risk-free interest rate.
     231
    -232    `y`: annualized dividend yield.
    +232    `vol`: annualized volatility.
     233
    -234    ### Returns
    +234    `years_to_maturity`: time remaining to maturity, in years.
     235
    -236    Option's Greek Theta.
    -237    """
    -238
    -239    s = s0 * exp(-y * years_to_maturity)
    -240
    -241    cdf_d1_prime = exp(-0.5 * d1 * d1) / sqrt(2.0 * pi)
    -242
    -243    if option_type == "call":
    -244        return -(
    -245            s * vol * cdf_d1_prime / (2.0 * sqrt(years_to_maturity))
    -246            + r * x * exp(-r * years_to_maturity) * stats.norm.cdf(d2)
    -247            - y * s * stats.norm.cdf(d1)
    -248        )
    -249    elif option_type == "put":
    -250        return -(
    -251            s * vol * cdf_d1_prime / (2.0 * sqrt(years_to_maturity))
    -252            - r * x * exp(-r * years_to_maturity) * stats.norm.cdf(-d2)
    -253            + y * s * stats.norm.cdf(-d1)
    -254        )
    -255    else:
    -256        raise ValueError("Option type must be either 'call' or 'put'!")
    +236    `d1`: `d1` in Black-Scholes formula.
    +237
    +238    `d2`: `d2` in Black-Scholes formula.
    +239
    +240    `y`: annualized dividend yield.
    +241
    +242    ### Returns
    +243
    +244    Option's Greek Theta.
    +245    """
    +246
    +247    s = s0 * exp(-y * years_to_maturity)
    +248
    +249    cdf_d1_prime = exp(-0.5 * d1 * d1) / sqrt(2.0 * pi)
    +250
    +251    if option_type == "call":
    +252        return -(
    +253            s * vol * cdf_d1_prime / (2.0 * sqrt(years_to_maturity))
    +254            + r * x * exp(-r * years_to_maturity) * stats.norm.cdf(d2)
    +255            - y * s * stats.norm.cdf(d1)
    +256        )
    +257    elif option_type == "put":
    +258        return -(
    +259            s * vol * cdf_d1_prime / (2.0 * sqrt(years_to_maturity))
    +260            - r * x * exp(-r * years_to_maturity) * stats.norm.cdf(-d2)
    +261            + y * s * stats.norm.cdf(-d1)
    +262        )
    +263    else:
    +264        raise ValueError("Option type must be either 'call' or 'put'!")
     
    @@ -1006,35 +1090,35 @@

    Returns

    -
    259def get_vega(
    -260    s0: float,
    -261    years_to_maturity: float,
    -262    d1: FloatOrNdarray,
    -263    y: float = 0.0,
    -264) -> FloatOrNdarray:
    -265    """
    -266    Returns the option's Greek Vega.
    -267
    -268    ### Parameters
    -269
    -270    `s0`: spot price of the underlying asset.
    -271
    -272    `years_to_maturity`: time remaining to maturity, in years.
    -273
    -274    `d1`: `d1` in Black-Scholes formula.
    +            
    267def get_vega(
    +268    s0: float,
    +269    years_to_maturity: float,
    +270    d1: FloatOrNdarray,
    +271    y: float = 0.0,
    +272) -> FloatOrNdarray:
    +273    """
    +274    Returns the option's Greek Vega.
     275
    -276    `y`: annualized dividend yield.
    +276    ### Parameters
     277
    -278    ### Returns
    +278    `s0`: spot price of the underlying asset.
     279
    -280    Option's Greek Vega.
    -281    """
    -282
    -283    s = s0 * exp(-y * years_to_maturity)
    -284
    -285    cdf_d1_prime = exp(-0.5 * d1 * d1) / sqrt(2.0 * pi)
    -286
    -287    return s * cdf_d1_prime * sqrt(years_to_maturity) / 100
    +280    `years_to_maturity`: time remaining to maturity, in years.
    +281
    +282    `d1`: `d1` in Black-Scholes formula.
    +283
    +284    `y`: annualized dividend yield.
    +285
    +286    ### Returns
    +287
    +288    Option's Greek Vega.
    +289    """
    +290
    +291    s = s0 * exp(-y * years_to_maturity)
    +292
    +293    cdf_d1_prime = exp(-0.5 * d1 * d1) / sqrt(2.0 * pi)
    +294
    +295    return s * cdf_d1_prime * sqrt(years_to_maturity) / 100
     
    @@ -1068,51 +1152,51 @@

    Returns

    -
    290def get_rho(
    -291    option_type: OptionType,
    -292    x: FloatOrNdarray,
    -293    r: float,
    -294    years_to_maturity: float,
    -295    d2: FloatOrNdarray,
    -296) -> FloatOrNdarray:
    -297    """
    -298    Returns the option's Greek Rho.
    -299
    -300    ### Parameters
    -301
    -302    `option_type`: either *'call'* or *'put'*.
    -303
    -304    `x`: strike price(s).
    -305
    -306    `r`: annualized risk-free interest rate.
    +            
    298def get_rho(
    +299    option_type: OptionType,
    +300    x: FloatOrNdarray,
    +301    r: float,
    +302    years_to_maturity: float,
    +303    d2: FloatOrNdarray,
    +304) -> FloatOrNdarray:
    +305    """
    +306    Returns the option's Greek Rho.
     307
    -308    `years_to_maturity`: time remaining to maturity, in years.
    +308    ### Parameters
     309
    -310    `d2`: `d2` in Black-Scholes formula.
    +310    `option_type`: either *'call'* or *'put'*.
     311
    -312    ### Returns
    +312    `x`: strike price(s).
     313
    -314    Option's Greek Rho.
    -315    """
    -316
    -317    if option_type == "call":
    -318        return (
    -319            x
    -320            * years_to_maturity
    -321            * exp(-r * years_to_maturity)
    -322            * stats.norm.cdf(d2)
    -323            / 100
    -324        )
    -325    elif option_type == "put":
    +314    `r`: annualized risk-free interest rate.
    +315
    +316    `years_to_maturity`: time remaining to maturity, in years.
    +317
    +318    `d2`: `d2` in Black-Scholes formula.
    +319
    +320    ### Returns
    +321
    +322    Option's Greek Rho.
    +323    """
    +324
    +325    if option_type == "call":
     326        return (
    -327            -x
    +327            x
     328            * years_to_maturity
     329            * exp(-r * years_to_maturity)
    -330            * stats.norm.cdf(-d2)
    +330            * stats.norm.cdf(d2)
     331            / 100
     332        )
    -333    else:
    -334        raise ValueError("Option must be either 'call' or 'put'!")
    +333    elif option_type == "put":
    +334        return (
    +335            -x
    +336            * years_to_maturity
    +337            * exp(-r * years_to_maturity)
    +338            * stats.norm.cdf(-d2)
    +339            / 100
    +340        )
    +341    else:
    +342        raise ValueError("Option must be either 'call' or 'put'!")
     
    @@ -1148,39 +1232,39 @@

    Returns

    -
    337def get_d1(
    -338    s0: FloatOrNdarray,
    -339    x: FloatOrNdarray,
    -340    r: float,
    -341    vol: FloatOrNdarray,
    -342    years_to_maturity: float,
    -343    y: float = 0.0,
    -344) -> FloatOrNdarray:
    -345    """
    -346    Returns `d1` used in Black-Scholes formula.
    -347
    -348    ### Parameters
    -349
    -350    `s0`: spot price(s) of the underlying asset.
    -351
    -352    `x`: strike price(s).
    -353
    -354    `r`: annualized risk-free interest rate.
    +            
    345def get_d1(
    +346    s0: FloatOrNdarray,
    +347    x: FloatOrNdarray,
    +348    r: float,
    +349    vol: FloatOrNdarray,
    +350    years_to_maturity: float,
    +351    y: float = 0.0,
    +352) -> FloatOrNdarray:
    +353    """
    +354    Returns `d1` used in Black-Scholes formula.
     355
    -356    `vol`: annualized volatility(ies).
    +356    ### Parameters
     357
    -358    `years_to_maturity`: time remaining to maturity, in years.
    +358    `s0`: spot price(s) of the underlying asset.
     359
    -360    `y`: annualized divident yield.
    +360    `x`: strike price(s).
     361
    -362    ### Returns
    +362    `r`: annualized risk-free interest rate.
     363
    -364    `d1` in Black-Scholes formula.
    -365    """
    -366
    -367    return (log(s0 / x) + (r - y + vol * vol / 2.0) * years_to_maturity) / (
    -368        vol * sqrt(years_to_maturity)
    -369    )
    +364    `vol`: annualized volatility(ies).
    +365
    +366    `years_to_maturity`: time remaining to maturity, in years.
    +367
    +368    `y`: annualized divident yield.
    +369
    +370    ### Returns
    +371
    +372    `d1` in Black-Scholes formula.
    +373    """
    +374
    +375    return (log(s0 / x) + (r - y + vol * vol / 2.0) * years_to_maturity) / (
    +376        vol * sqrt(years_to_maturity)
    +377    )
     
    @@ -1218,39 +1302,39 @@

    Returns

    -
    372def get_d2(
    -373    s0: FloatOrNdarray,
    -374    x: FloatOrNdarray,
    -375    r: float,
    -376    vol: FloatOrNdarray,
    -377    years_to_maturity: float,
    -378    y: float = 0.0,
    -379) -> FloatOrNdarray:
    -380    """
    -381    Returns `d2` used in Black-Scholes formula.
    -382
    -383    ### Parameters
    -384
    -385    `s0`: spot price(s) of the underlying asset.
    -386
    -387    `x`: strike price(s).
    -388
    -389    `r`: annualized risk-free interest rate.
    +            
    380def get_d2(
    +381    s0: FloatOrNdarray,
    +382    x: FloatOrNdarray,
    +383    r: float,
    +384    vol: FloatOrNdarray,
    +385    years_to_maturity: float,
    +386    y: float = 0.0,
    +387) -> FloatOrNdarray:
    +388    """
    +389    Returns `d2` used in Black-Scholes formula.
     390
    -391    `vol`: annualized volatility(ies).
    +391    ### Parameters
     392
    -393    `years_to_maturity`: time remaining to maturity, in years.
    +393    `s0`: spot price(s) of the underlying asset.
     394
    -395    `y`: annualized divident yield.
    +395    `x`: strike price(s).
     396
    -397    ### Returns
    +397    `r`: annualized risk-free interest rate.
     398
    -399    `d2` in Black-Scholes formula.
    -400    """
    -401
    -402    return (log(s0 / x) + (r - y - vol * vol / 2.0) * years_to_maturity) / (
    -403        vol * sqrt(years_to_maturity)
    -404    )
    +399    `vol`: annualized volatility(ies).
    +400
    +401    `years_to_maturity`: time remaining to maturity, in years.
    +402
    +403    `y`: annualized divident yield.
    +404
    +405    ### Returns
    +406
    +407    `d2` in Black-Scholes formula.
    +408    """
    +409
    +410    return (log(s0 / x) + (r - y - vol * vol / 2.0) * years_to_maturity) / (
    +411        vol * sqrt(years_to_maturity)
    +412    )
     
    @@ -1288,47 +1372,47 @@

    Returns

    -
    407def get_implied_vol(
    -408    option_type: OptionType,
    -409    oprice: float,
    -410    s0: float,
    -411    x: float,
    -412    r: float,
    -413    years_to_maturity: float,
    -414    y: float = 0.0,
    -415) -> float:
    -416    """
    -417    Returns the implied volatility of an option.
    -418
    -419    ### Parameters
    -420
    -421    `option_type`: either *'call'* or *'put'*.
    -422
    -423    `oprice`: market price of an option.
    -424
    -425    `s0`: spot price of the underlying asset.
    +            
    415def get_implied_vol(
    +416    option_type: OptionType,
    +417    oprice: float,
    +418    s0: float,
    +419    x: float,
    +420    r: float,
    +421    years_to_maturity: float,
    +422    y: float = 0.0,
    +423) -> float:
    +424    """
    +425    Returns the implied volatility of an option.
     426
    -427    `x`: strike price.
    +427    ### Parameters
     428
    -429    `r`: annualized risk-free interest rate.
    +429    `option_type`: either *'call'* or *'put'*.
     430
    -431    `years_to_maturity`: time remaining to maturity, in years.
    +431    `oprice`: market price of an option.
     432
    -433    `y`: annualized dividend yield.
    +433    `s0`: spot price of the underlying asset.
     434
    -435    ### Returns
    +435    `x`: strike price.
     436
    -437    Option's implied volatility.
    -438    """
    -439
    -440    vol = 0.001 * arange(1, 1001)
    -441    d1 = get_d1(s0, x, r, vol, years_to_maturity, y)
    -442    d2 = get_d2(s0, x, r, vol, years_to_maturity, y)
    -443    dopt = abs(
    -444        get_option_price(option_type, s0, x, r, years_to_maturity, d1, d2, y) - oprice
    -445    )
    -446
    -447    return vol[argmin(dopt)]
    +437    `r`: annualized risk-free interest rate.
    +438
    +439    `years_to_maturity`: time remaining to maturity, in years.
    +440
    +441    `y`: annualized dividend yield.
    +442
    +443    ### Returns
    +444
    +445    Option's implied volatility.
    +446    """
    +447
    +448    vol = 0.001 * arange(1, 1001)
    +449    d1 = get_d1(s0, x, r, vol, years_to_maturity, y)
    +450    d2 = get_d2(s0, x, r, vol, years_to_maturity, y)
    +451    dopt = abs(
    +452        get_option_price(option_type, s0, x, r, years_to_maturity, d1, d2, y) - oprice
    +453    )
    +454
    +455    return vol[argmin(dopt)]
     
    @@ -1368,38 +1452,38 @@

    Returns

    -
    450def get_itm_probability(
    -451    option_type: OptionType,
    -452    d2: FloatOrNdarray,
    -453    years_to_maturity: float,
    -454    y: float = 0.0,
    -455) -> FloatOrNdarray:
    -456    """
    -457    Returns the probability(ies) that the option(s) will expire in-the-money (ITM).
    -458
    -459    ### Parameters
    -460
    -461    `option_type`: either *'call'* or *'put'*.
    -462
    -463    `d2`: `d2` in Black-Scholes formula.
    -464
    -465    `years_to_maturity`: time remaining to maturity, in years.
    +            
    458def get_itm_probability(
    +459    option_type: OptionType,
    +460    d2: FloatOrNdarray,
    +461    years_to_maturity: float,
    +462    y: float = 0.0,
    +463) -> FloatOrNdarray:
    +464    """
    +465    Returns the probability(ies) that the option(s) will expire in-the-money (ITM).
     466
    -467    `y`: annualized dividend yield.
    +467    ### Parameters
     468
    -469    ### Returns
    +469    `option_type`: either *'call'* or *'put'*.
     470
    -471    Probability(ies) that the option(s) will expire in-the-money (ITM).
    -472    """
    -473
    -474    yfac = exp(-y * years_to_maturity)
    -475
    -476    if option_type == "call":
    -477        return yfac * stats.norm.cdf(d2)
    -478    elif option_type == "put":
    -479        return yfac * stats.norm.cdf(-d2)
    -480    else:
    -481        raise ValueError("Option type must be either 'call' or 'put'!")
    +471    `d2`: `d2` in Black-Scholes formula.
    +472
    +473    `years_to_maturity`: time remaining to maturity, in years.
    +474
    +475    `y`: annualized dividend yield.
    +476
    +477    ### Returns
    +478
    +479    Probability(ies) that the option(s) will expire in-the-money (ITM).
    +480    """
    +481
    +482    yfac = exp(-y * years_to_maturity)
    +483
    +484    if option_type == "call":
    +485        return yfac * stats.norm.cdf(d2)
    +486    elif option_type == "put":
    +487        return yfac * stats.norm.cdf(-d2)
    +488    else:
    +489        raise ValueError("Option type must be either 'call' or 'put'!")
     
    @@ -1421,6 +1505,117 @@

    Returns

    + +
    + +
    + + def + get_probability_of_touch( option_type: Literal['call', 'put'], s: float, x: float | numpy.ndarray, r: float, vol: float, years_to_maturity: float, y: float = 0.0) -> float | numpy.ndarray: + + + +
    + +
    492def get_probability_of_touch(
    +493    option_type: OptionType,
    +494    s: float,
    +495    x: FloatOrNdarray,
    +496    r: float,
    +497    vol: float,
    +498    years_to_maturity: float,
    +499    y: float = 0.0,
    +500) -> FloatOrNdarray:
    +501    """
    +502    Returns the probability(ies) that the option(s) will ever get in-the-money (ITM)
    +503    before expiration.
    +504
    +505    > [!NOTE]
    +506    > This function implements equations 2.66 and 2.67 (see pages 80 and 81) in
    +507    > *The complete guide to option pricing formulas*, 2nd edition, authored by
    +508    > Espen Gaarder Haug, PhD, and published by McGraw-Hill.
    +509
    +510    ### Parameters
    +511
    +512    `option_type`: either *'call'* or *'put'*.
    +513
    +514    `s`: stock price.
    +515
    +516    `x`: strike price(s).
    +517
    +518    `r`: annualized risk-free interest rate.
    +519
    +520    `vol`: annualized volatility.
    +521
    +522    `years_to_maturity`: time remaining to maturity, in years.
    +523
    +524    `y`: annualized dividend yield.
    +525
    +526    ### Returns
    +527
    +528    Probability(ies) that the option(s) will ever get in-the-money (ITM) before
    +529    expiration.
    +530    """
    +531
    +532    mu = (r - y - 0.5 * vol * vol) / (vol * vol)
    +533    lam = sqrt((mu * mu) + 2.0 * r / (vol * vol))
    +534    sigma = vol * sqrt(years_to_maturity)
    +535    z = log(x / s) / sigma + lam * sigma
    +536    exp1 = mu + lam
    +537    exp2 = mu - lam
    +538
    +539    if option_type == "call":
    +540        if s >= x:
    +541            return 1.0
    +542        else:
    +543            return ((x / s) ** exp1) * stats.norm.cdf(-z) + (
    +544                (x / s) ** exp2
    +545            ) * stats.norm.cdf(2.0 * lam * sigma - z)
    +546    elif option_type == "put":
    +547        if s <= x:
    +548            return 1.0
    +549        else:
    +550            return ((x / s) ** exp1) * stats.norm.cdf(z) + (
    +551                (x / s) ** exp2
    +552            ) * stats.norm.cdf(z - 2.0 * lam * sigma)
    +553    else:
    +554        raise ValueError("Option type must be either 'call' or 'put'!")
    +
    + + +

    Returns the probability(ies) that the option(s) will ever get in-the-money (ITM) +before expiration.

    + +
    +Note +

    This function implements equations 2.66 and 2.67 (see pages 80 and 81) in + The complete guide to option pricing formulas, 2nd edition, authored by + Espen Gaarder Haug, PhD, and published by McGraw-Hill.

    +
    + +

    Parameters

    + +

    option_type: either 'call' or 'put'.

    + +

    s: stock price.

    + +

    x: strike price(s).

    + +

    r: annualized risk-free interest rate.

    + +

    vol: annualized volatility.

    + +

    years_to_maturity: time remaining to maturity, in years.

    + +

    y: annualized dividend yield.

    + +

    Returns

    + +

    Probability(ies) that the option(s) will ever get in-the-money (ITM) before +expiration.

    +
    + +