Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# 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 docstrings.

## 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`.
- Updated docstrings.
- Removed price_array.py (a better Monte Carlo implementation is coming soon).
- The `expected_return_above_target` and `expected_return_below_target` fields in `PoPOutputs`, in models.py, are no longer optional but floats with default value of 0.0.
- The same for the `expected_profit` and `expected_loss` fields in `EngineData` and `Outputs`, both also in models.py.
- Removed test_misc.py.

## 1.4.3 (2025-04-14)

- Updated docstrings.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
![OptionLab](optionlab.png)
![OptionLab](https://raw.githubusercontent.com/rgaveiga/optionlab/refs/heads/main/optionlab.png)

# OptionLab

Expand Down
181 changes: 33 additions & 148 deletions docs/optionlab.html

Large diffs are not rendered by default.

1,725 changes: 960 additions & 765 deletions docs/optionlab/black_scholes.html

Large diffs are not rendered by default.

478 changes: 242 additions & 236 deletions docs/optionlab/engine.html

Large diffs are not rendered by default.

2,497 changes: 1,286 additions & 1,211 deletions docs/optionlab/models.html

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions docs/optionlab/plot.html

Large diffs are not rendered by default.

584 changes: 322 additions & 262 deletions docs/optionlab/support.html

Large diffs are not rendered by default.

64 changes: 32 additions & 32 deletions docs/optionlab/utils.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/search.js

Large diffs are not rendered by default.

13 changes: 9 additions & 4 deletions examples/black_scholes_calculator.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"source": [
"from __future__ import print_function\n",
"from __future__ import division\n",
"from optionlab import VERSION, get_bs_info\n",
"from optionlab import __version__\n",
"from optionlab.black_scholes import get_bs_info\n",
"import sys"
]
},
Expand All @@ -43,13 +44,13 @@
"output_type": "stream",
"text": [
"Python version: 3.11.9 | packaged by Anaconda, Inc. | (main, Apr 19 2024, 16:40:41) [MSC v.1916 64 bit (AMD64)]\n",
"OptionLab version: 1.4.3\n"
"OptionLab version: 1.5.1\n"
]
}
],
"source": [
"print(f\"Python version: {sys.version}\")\n",
"print(f\"OptionLab version: {VERSION}\")"
"print(f\"OptionLab version: {__version__}\")"
]
},
{
Expand Down Expand Up @@ -106,7 +107,7 @@
"output_type": "stream",
"text": [
"CPU times: total: 0 ns\n",
"Wall time: 4 ms\n"
"Wall time: 0 ns\n"
]
}
],
Expand Down Expand Up @@ -151,6 +152,7 @@
" Theta: -8.78\n",
" Rho: 0.05\n",
" ITM probability: 26.70\n",
" Probability of touch: 54.04\n",
"\n",
"\n",
"PUT\n",
Expand All @@ -160,6 +162,7 @@
" Theta: -7.73\n",
" Rho: -0.13\n",
" ITM probability: 73.30\n",
" Probability of touch: 100.00\n",
"\n",
"\n",
"Gamma and Vega: 0.0425 \n",
Expand All @@ -175,6 +178,7 @@
"print(f\" Theta: {bs.call_theta:.2f}\")\n",
"print(f\" Rho: {bs.call_rho: .2f}\")\n",
"print(f\" ITM probability: {bs.call_itm_prob * 100.0:.2f}\")\n",
"print(f\" Probability of touch: {bs.call_prob_of_touch * 100.0:.2f}\")\n",
"print(\"\\n\")\n",
"print(\"PUT\")\n",
"print(\"===\")\n",
Expand All @@ -183,6 +187,7 @@
"print(f\" Theta: {bs.put_theta:.2f}\")\n",
"print(f\" Rho: {bs.put_rho: .2f}\")\n",
"print(f\" ITM probability: {bs.put_itm_prob * 100.0:.2f}\")\n",
"print(f\" Probability of touch: {bs.put_prob_of_touch * 100.0:.2f}\")\n",
"print(\"\\n\")\n",
"print(f\"Gamma and Vega: {bs.gamma:.4f} \\n {bs.vega:.2f}\")"
]
Expand Down
13 changes: 8 additions & 5 deletions examples/calendar_spread.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"import datetime as dt\n",
"import sys\n",
"\n",
"from optionlab import VERSION, run_strategy, plot_pl\n",
"from optionlab import __version__, run_strategy, plot_pl\n",
"\n",
"%matplotlib inline"
]
Expand All @@ -47,13 +47,13 @@
"output_type": "stream",
"text": [
"Python version: 3.11.9 | packaged by Anaconda, Inc. | (main, Apr 19 2024, 16:40:41) [MSC v.1916 64 bit (AMD64)]\n",
"OptionLab version: 1.4.3\n"
"OptionLab version: 1.5.1\n"
]
}
],
"source": [
"print(f\"Python version: {sys.version}\")\n",
"print(f\"OptionLab version: {VERSION}\")"
"print(f\"OptionLab version: {__version__}\")"
]
},
{
Expand Down Expand Up @@ -119,8 +119,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: total: 375 ms\n",
"Wall time: 485 ms\n"
"CPU times: total: 297 ms\n",
"Wall time: 450 ms\n"
]
}
],
Expand Down Expand Up @@ -179,12 +179,15 @@
"text": [
"Probability of profit: 0.599111819020198\n",
"Profit ranges: [(118.87, 136.15)]\n",
"Expected profit if profitable: 1383.2\n",
"Expected loss if unprofitable: -691.09\n",
"Per leg cost: [4600.0, -5900.0]\n",
"Strategy cost: -1300.0\n",
"Minimum return in the domain: -1300.0000000000146\n",
"Maximum return in the domain: 3009.999999999999\n",
"Implied volatility: [0.47300000000000003, 0.419]\n",
"In the money probability: [0.4895105709759477, 0.4805997906939539]\n",
"Probability of touch: [1.0, 1.0]\n",
"Delta: [-0.5216914758915705, 0.5273457614638198]\n",
"Gamma: [0.03882722919950356, 0.02669940508461828]\n",
"Theta: [0.22727438444823292, -0.15634971608107964]\n",
Expand Down
86 changes: 50 additions & 36 deletions examples/call_spread.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,20 @@
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"C:\\Users\\rgave\\AppData\\Local\\pypoetry\\Cache\\virtualenvs\\optionlab-M7OP2qJc-py3.11\\Lib\\site-packages\\numpy\\lib\\_scimath_impl.py:289: RuntimeWarning: divide by zero encountered in log\n",
" return nx.log(x)\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: total: 39.8 s\n",
"Wall time: 42.4 s\n"
"CPU times: total: 2min 41s\n",
"Wall time: 2min 51s\n"
]
}
],
Expand Down Expand Up @@ -235,25 +243,28 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Strategy cost: -15995.00\n",
"Maximum loss: 15995.00\n",
"Maximum profit: 5.00\n",
"Profitable stock price range:\n",
" 304.96 ---> inf\n",
"Probability of Profit (PoP): 99.1\n"
"Probability of profit: 0.9906981384518034\n",
"Profit ranges: [(304.96, inf)]\n",
"Expected profit if profitable: 5.0\n",
"Expected loss if unprofitable: -499.07\n",
"Per leg cost: [-19805.0, 3810.0]\n",
"Strategy cost: -15995.0\n",
"Minimum return in the domain: -15995.0\n",
"Maximum return in the domain: 5.0\n",
"Implied volatility: [0.999, 0.2]\n",
"In the money probability: [1.0, 0.9906315405574139]\n",
"Probability of touch: [1.0, 1.0]\n",
"Delta: [1.0, -0.9918058094935618]\n",
"Gamma: [1.951791997745016e-68, 0.00132062967266379]\n",
"Theta: [-0.0005753534439382797, 0.011185261446659761]\n",
"Vega: [3.1158128584143207e-67, 0.02108234340566703]\n",
"Rho: [0.10931715434827315, -0.22778876835532164]\n",
"\n"
]
}
],
"source": [
"print(f\"Strategy cost: {out.strategy_cost:.2f}\")\n",
"print(f\"Maximum loss: {abs(out.minimum_return_in_the_domain):.2f}\")\n",
"print(f\"Maximum profit: {out.maximum_return_in_the_domain:.2f}\")\n",
"print(\"Profitable stock price range:\")\n",
"\n",
"for low, high in out.profit_ranges:\n",
" print(f\" {low:.2f} ---> {high:.2f}\")\n",
"\n",
"print(f\"Probability of Profit (PoP): {out.probability_of_profit * 100.0:.1f}\")"
"print(out)"
]
},
{
Expand All @@ -269,7 +280,7 @@
{
"data": {
"text/plain": [
"[<matplotlib.lines.Line2D at 0x1d7a0247250>]"
"[<matplotlib.lines.Line2D at 0x222784d3890>]"
]
},
"execution_count": 9,
Expand Down Expand Up @@ -383,8 +394,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: total: 39.5 s\n",
"Wall time: 42.3 s\n"
"CPU times: total: 2min 34s\n",
"Wall time: 2min 46s\n"
]
}
],
Expand Down Expand Up @@ -454,25 +465,28 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Strategy cost: -8293.00\n",
"Maximum loss: 8293.00\n",
"Maximum profit: 8707.00\n",
"Profitable stock price range:\n",
" 342.94 ---> inf\n",
"Probability of Profit (PoP): 49.1\n"
"Probability of profit: 0.4914563792806722\n",
"Profit ranges: [(342.94, inf)]\n",
"Expected profit if profitable: 1381.92\n",
"Expected loss if unprofitable: -1323.79\n",
"Per leg cost: [-8300.0, 7.000000000000001]\n",
"Strategy cost: -8293.0\n",
"Minimum return in the domain: -8293.0\n",
"Maximum return in the domain: 8707.000000000002\n",
"Implied volatility: [0.319, 0.327]\n",
"In the money probability: [0.9999999880052545, 2.126445370979977e-06]\n",
"Probability of touch: [1.0, 4.272550589235243e-06]\n",
"Delta: [0.9999999909830838, -2.6925191836574867e-06]\n",
"Gamma: [3.083980302091833e-09, 7.547374646336367e-07]\n",
"Theta: [-0.0010316915524542186, 5.710822366452319e-06]\n",
"Vega: [4.923222091009698e-08, 1.2048521050139721e-05]\n",
"Rho: [0.1960169640664196, -6.893551133656091e-07]\n",
"\n"
]
}
],
"source": [
"print(f\"Strategy cost: {out.strategy_cost:.2f}\")\n",
"print(f\"Maximum loss: {abs(out.minimum_return_in_the_domain):.2f}\")\n",
"print(f\"Maximum profit: {out.maximum_return_in_the_domain:.2f}\")\n",
"print(\"Profitable stock price range:\")\n",
"\n",
"for low, high in out.profit_ranges:\n",
" print(f\" {low:.2f} ---> {high:.2f}\")\n",
"\n",
"print(f\"Probability of Profit (PoP): {out.probability_of_profit * 100.0:.1f}\")"
"print(out)"
]
},
{
Expand All @@ -488,7 +502,7 @@
{
"data": {
"text/plain": [
"[<matplotlib.lines.Line2D at 0x1d7a2447bd0>]"
"[<matplotlib.lines.Line2D at 0x2227fa87a10>]"
]
},
"execution_count": 15,
Expand Down
15 changes: 9 additions & 6 deletions examples/covered_call.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"import matplotlib.pyplot as plt\n",
"from numpy import zeros\n",
"\n",
"from optionlab import VERSION, run_strategy\n",
"from optionlab import __version__, run_strategy\n",
"\n",
"%matplotlib inline"
]
Expand All @@ -54,13 +54,13 @@
"output_type": "stream",
"text": [
"Python version: 3.11.9 | packaged by Anaconda, Inc. | (main, Apr 19 2024, 16:40:41) [MSC v.1916 64 bit (AMD64)]\n",
"OptionLab version: 1.4.3\n"
"OptionLab version: 1.5.1\n"
]
}
],
"source": [
"print(\"Python version: %s\" % sys.version)\n",
"print(\"OptionLab version: %s\" % VERSION)"
"print(\"OptionLab version: %s\" % __version__)"
]
},
{
Expand Down Expand Up @@ -119,8 +119,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: total: 281 ms\n",
"Wall time: 258 ms\n"
"CPU times: total: 297 ms\n",
"Wall time: 341 ms\n"
]
}
],
Expand All @@ -142,7 +142,7 @@
{
"data": {
"text/plain": [
"<matplotlib.legend.Legend at 0x1e0346f7f90>"
"<matplotlib.legend.Legend at 0x21d8b7fc910>"
]
},
"execution_count": 5,
Expand Down Expand Up @@ -195,12 +195,15 @@
"text": [
"Probability of profit: 0.522421406650333\n",
"Profit ranges: [(162.9, inf)]\n",
"Expected profit if profitable: 787.24\n",
"Expected loss if unprofitable: -904.12\n",
"Per leg cost: [-16404.0, 114.99999999999999]\n",
"Strategy cost: -16289.0\n",
"Minimum return in the domain: -8087.0\n",
"Maximum return in the domain: 1211.0000000000018\n",
"Implied volatility: [0.0, 0.256]\n",
"In the money probability: [1.0, 0.1832371984432129]\n",
"Probability of touch: [1.0, 0.3741546603689868]\n",
"Delta: [1.0, -0.20371918274704337]\n",
"Gamma: [0.0, 0.023104402361599465]\n",
"Theta: [0.0, 0.091289876347897]\n",
Expand Down
Loading
Loading