Skip to content

Commit 638e677

Browse files
committed
Updated examples and blacked source
1 parent c4bc9b5 commit 638e677

File tree

5 files changed

+110
-40
lines changed

5 files changed

+110
-40
lines changed

examples/naked_call.ipynb

Lines changed: 20 additions & 6 deletions
Large diffs are not rendered by default.

optionlab/black_scholes.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def get_option_price(
8888
Parameters
8989
----------
9090
option_type : str
91-
`OptionType` literal value, which must be either 'call' or 'put'.
91+
`OptionType` literal value, which must be either **call** or **put**.
9292
s0 : float | numpy.ndarray
9393
Spot price(s) of the underlying asset.
9494
x : float | numpy.ndarray
@@ -140,7 +140,7 @@ def get_delta(
140140
Parameters
141141
----------
142142
option_type : str
143-
`OptionType` literal value, which must be either 'call' or 'put'.
143+
`OptionType` literal value, which must be either **call** or **put**.
144144
d1 : float | numpy.ndarray
145145
`d1` in Black-Scholes formula.
146146
years_to_maturity : float
@@ -217,7 +217,7 @@ def get_theta(
217217
Parameters
218218
----------
219219
option_type : str
220-
`OptionType` literal value, which must be either 'call' or 'put'.
220+
`OptionType` literal value, which must be either **call** or **put**.
221221
s0 : float
222222
Spot price of the underlying asset.
223223
x : float | numpy.ndarray
@@ -307,7 +307,7 @@ def get_rho(
307307
Parameters
308308
----------
309309
option_type : OptionType
310-
`OptionType` literal value, which must be either 'call' or 'put'.
310+
`OptionType` literal value, which must be either **call** or **put**.
311311
x : float | numpy.ndarray
312312
Strike price(s).
313313
r : float
@@ -432,7 +432,7 @@ def get_implied_vol(
432432
Parameters
433433
----------
434434
option_type : str
435-
`OptionType` literal value, which must be either 'call' or 'put'.
435+
`OptionType` literal value, which must be either **call** or **put**.
436436
oprice : float
437437
Market price of an option.
438438
s0 : float
@@ -474,7 +474,7 @@ def get_itm_probability(
474474
Parameters
475475
----------
476476
option_type : str
477-
`OptionType` literal value, which must be either 'call' or 'put'.
477+
`OptionType` literal value, which must be either **call** or **put**.
478478
d2 : float | numpy.ndarray
479479
`d2` in Black-Scholes formula.
480480
years_to_maturity : float

optionlab/models.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ class Stock(BaseLeg):
2424
Attributes
2525
----------
2626
type : str
27-
It must be 'stock'. It is mandatory.
27+
It must be **stock**.
2828
n : int
29-
Number of shares. It is mandatory.
29+
Number of shares.
3030
action : str
31-
`Action` literal value, which must be either 'buy' or 'sell'. It is mandatory.
31+
`Action` literal value, which must be either **buy** or **sell**.
3232
prev_pos : float | None, optional
3333
Stock price effectively paid or received in a previously opened position.
3434
If positive, the position remains open and the payoff calculation considers
@@ -48,24 +48,23 @@ class Option(BaseLeg):
4848
Attributes
4949
----------
5050
type : str
51-
`OptionType` literal value, which must be either 'call' or 'put'. It is
52-
mandatory.
51+
`OptionType` literal value, which must be either **call** or **put**.
5352
strike : float
54-
Option strike price. It is mandatory.
53+
Strike price.
5554
premium : float
56-
Option premium. It is mandatory.
55+
Option premium.
5756
n : int
58-
Number of options. It is mandatory
57+
Number of options.
5958
action : str
60-
`Action` literal value, which must be either 'buy' or 'sell'.
59+
`Action` literal value, which must be either **buy** or **sell**.
6160
prev_pos : float | None, optional
6261
Premium effectively paid or received in a previously opened position. If
6362
positive, the position remains open and the payoff calculation considers
6463
this price instead of the current price of the option. If negative, the
6564
position is closed and the difference between this price and the current
6665
price is included in the payoff calculation. The default is None, which
6766
means this option position is not a previously opened position.
68-
expiration : str | int | None, optional.
67+
expiration : str | int | None, optional
6968
Expiration date or number of days remaining to maturity. The default is
7069
None.
7170
"""
@@ -89,10 +88,10 @@ class ClosedPosition(BaseModel):
8988
Attributes
9089
----------
9190
type : str
92-
It must be 'closed'. It is mandatory.
91+
It must be **closed**.
9392
prev_pos : float
9493
The total amount of the closed position. If positive, it resulted in a
95-
profit; if negative, it incurred a loss. It is mandatory.
94+
profit; if negative, it incurred a loss.
9695
"""
9796

9897
type: Literal["closed"] = "closed"
@@ -115,7 +114,7 @@ class BlackScholesModelInputs(TheoreticalModelInputs):
115114
Attributes
116115
----------
117116
model : str
118-
It must be either 'black-scholes' or 'normal'.
117+
It must be either **black-scholes** or **normal**.
119118
stock_price : float
120119
Stock price.
121120
volatility : float
@@ -143,7 +142,7 @@ class LaplaceInputs(TheoreticalModelInputs):
143142
Attributes
144143
----------
145144
model : str
146-
It must be 'laplace'.
145+
It must be **laplace**.
147146
stock_price : float
148147
Stock price.
149148
mu : float
@@ -168,7 +167,7 @@ class ArrayInputs(BaseModel):
168167
Attributes
169168
----------
170169
model : str
171-
It must be 'array'.
170+
It must be **array**.
172171
array : numpy.ndarray
173172
Array of strategy returns.
174173
"""
@@ -223,7 +222,7 @@ class Inputs(BaseModel):
223222
Number of business days in a year. The default is 252.
224223
country : str, optional
225224
Country whose holidays will be counted if `discard_nonbusinessdays` is
226-
set to True. The default is 'US'.
225+
set to True. The default is **US**.
227226
start_date : datetime.date, optional
228227
Start date in the calculations. If not provided, `days_to_target_date`
229228
must be provided.
@@ -234,8 +233,9 @@ class Inputs(BaseModel):
234233
Days remaining to the target date. If not provided, `start_date` and
235234
`target_date` must be provided.
236235
model : str, optional
237-
Theoretical model used in the calculations. It can be 'black-scholes'
238-
(the same as 'normal') or 'array'. The default is 'black-scholes'.
236+
Theoretical model used in the calculations of probability of profit. It
237+
can be **black-scholes** (the same as **normal**) or **array**. The default
238+
is **black-scholes**.
239239
array : numpy.ndarray | None, optional
240240
Array of terminal stock prices. The default is None.
241241
"""
@@ -491,7 +491,7 @@ def __str__(self):
491491

492492
class PoPOutputs(BaseModel):
493493
"""
494-
Defineas the output data from a probability of profit (PoP) calculation.
494+
Defines the output data from a probability of profit (PoP) calculation.
495495
496496
Attributes
497497
----------

optionlab/support.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ def get_pl_profile(
3333
Parameters
3434
----------
3535
option_type : str
36-
`OptionType` literal value, which must be either 'call' or 'put'.
36+
`OptionType` literal value, which must be either **call** or **put**.
3737
action : str
38-
`Action` literal value, which must be either 'buy' or 'sell'.
38+
`Action` literal value, which must be either **buy** or **sell**.
3939
x : float
4040
Strike price.
4141
val : float
@@ -80,7 +80,7 @@ def get_pl_profile_stock(
8080
s0 : float
8181
Initial stock price.
8282
action : str
83-
`Action` literal value, which must be either 'buy' or 'sell'.
83+
`Action` literal value, which must be either **buy** or **sell**.
8484
n : int
8585
Number of shares.
8686
s : numpy.ndarray
@@ -124,9 +124,9 @@ def get_pl_profile_bs(
124124
Parameters
125125
----------
126126
option_type : str
127-
`OptionType` literal value, which must be either 'call' or 'put'.
127+
`OptionType` literal value, which must be either **call** or **put**.
128128
action : str
129-
`Action` literal value, which must be either 'buy' or 'sell'.
129+
`Action` literal value, which must be either **buy** or **sell**.
130130
x : float
131131
Strike price.
132132
val : float
@@ -428,11 +428,11 @@ def _get_pl_option(
428428
Parameters
429429
----------
430430
option_type : str
431-
`OptionType` literal value, which must be either 'call' or 'put'.
431+
`OptionType` literal value, which must be either **call** or **put**.
432432
opvalue : float
433433
Option price.
434434
action : str
435-
`Action` literal value, which must be either 'buy' or 'sell'.
435+
`Action` literal value, which must be either **buy** or **sell**.
436436
s : numpy.ndarray
437437
Array of stock prices.
438438
x : float
@@ -459,7 +459,7 @@ def _get_payoff(option_type: OptionType, s: np.ndarray, x: float) -> np.ndarray:
459459
Parameters
460460
----------
461461
option_type : str
462-
`OptionType` literal value, which must be either 'call' or 'put'.
462+
`OptionType` literal value, which must be either **call** or **put**.
463463
s : numpy.ndarray
464464
Array of stock prices.
465465
x : float
@@ -488,7 +488,7 @@ def _get_pl_stock(s0: float, action: Action, s: np.ndarray) -> np.ndarray:
488488
s0 : float
489489
Spot price of the underlying asset.
490490
action : str
491-
`Action` literal value, which must be either 'buy' or 'sell'.
491+
`Action` literal value, which must be either **buy** or **sell**.
492492
s : numpy.ndarray
493493
Array of stock prices.
494494

tests/test_core.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,28 @@
4141
"rho": [0.08536880237502181, -0.07509774107468528],
4242
}
4343

44+
PROB_NAKED_CALL = {
45+
"probability_of_profit": 0.8389215512144531,
46+
"profit_ranges": [(0.0, 176.14)],
47+
"expected_profit": 115.0,
48+
"expected_loss": -707.0,
49+
"per_leg_cost": [114.99999999999999],
50+
"strategy_cost": 114.99999999999999,
51+
"minimum_return_in_the_domain": -6991.999999999999,
52+
"maximum_return_in_the_domain": 114.99999999999999,
53+
"implied_volatility": [0.256],
54+
"in_the_money_probability": [0.1832371984432129],
55+
"delta": [-0.20371918274704337],
56+
"gamma": [0.023104402361599465],
57+
"theta": [0.091289876347897],
58+
"vega": [0.12750177318341913],
59+
"rho": [-0.02417676577711979],
60+
"probability_of_profit_target": 0.8197909190785164,
61+
"profit_target_ranges": [(0.0, 175.15)],
62+
"probability_of_loss_limit": 0.14307836806156238,
63+
"loss_limit_ranges": [(177.15, float("inf"))],
64+
}
65+
4466

4567
def test_black_scholes():
4668
stock_price = 100.0
@@ -209,6 +231,40 @@ def test_100_perc_itm(nvidia):
209231
) == pytest.approx(PROB_100_ITM_RESULT)
210232

211233

234+
def test_naked_call():
235+
inputs = Inputs.model_validate(
236+
{
237+
"stock_price": 164.04,
238+
"volatility": 0.272,
239+
"start_date": "2021-11-22",
240+
"target_date": "2021-12-17",
241+
"interest_rate": 0.0002,
242+
"min_stock": 82.02,
243+
"max_stock": 246.06,
244+
"profit_target": 100.0,
245+
"loss_limit": -100.0,
246+
"model": "black-scholes",
247+
# The naked call strategy is defined
248+
"strategy": [
249+
{
250+
"type": "call",
251+
"strike": 175.00,
252+
"premium": 1.15,
253+
"n": 100,
254+
"action": "sell",
255+
}
256+
],
257+
}
258+
)
259+
260+
outputs = run_strategy(inputs)
261+
262+
assert isinstance(outputs, Outputs)
263+
assert outputs.model_dump(
264+
exclude={"data", "inputs"}, exclude_none=True
265+
) == pytest.approx(PROB_NAKED_CALL)
266+
267+
212268
def test_3_legs(nvidia):
213269
inputs = Inputs.model_validate(
214270
nvidia

0 commit comments

Comments
 (0)