Skip to content

Commit

Permalink
Updated examples and blacked source
Browse files Browse the repository at this point in the history
  • Loading branch information
rgaveiga committed Jan 19, 2025
1 parent c4bc9b5 commit 638e677
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 40 deletions.
26 changes: 20 additions & 6 deletions examples/naked_call.ipynb

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions optionlab/black_scholes.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def get_option_price(
Parameters
----------
option_type : str
`OptionType` literal value, which must be either 'call' or 'put'.
`OptionType` literal value, which must be either **call** or **put**.
s0 : float | numpy.ndarray
Spot price(s) of the underlying asset.
x : float | numpy.ndarray
Expand Down Expand Up @@ -140,7 +140,7 @@ def get_delta(
Parameters
----------
option_type : str
`OptionType` literal value, which must be either 'call' or 'put'.
`OptionType` literal value, which must be either **call** or **put**.
d1 : float | numpy.ndarray
`d1` in Black-Scholes formula.
years_to_maturity : float
Expand Down Expand Up @@ -217,7 +217,7 @@ def get_theta(
Parameters
----------
option_type : str
`OptionType` literal value, which must be either 'call' or 'put'.
`OptionType` literal value, which must be either **call** or **put**.
s0 : float
Spot price of the underlying asset.
x : float | numpy.ndarray
Expand Down Expand Up @@ -307,7 +307,7 @@ def get_rho(
Parameters
----------
option_type : OptionType
`OptionType` literal value, which must be either 'call' or 'put'.
`OptionType` literal value, which must be either **call** or **put**.
x : float | numpy.ndarray
Strike price(s).
r : float
Expand Down Expand Up @@ -432,7 +432,7 @@ def get_implied_vol(
Parameters
----------
option_type : str
`OptionType` literal value, which must be either 'call' or 'put'.
`OptionType` literal value, which must be either **call** or **put**.
oprice : float
Market price of an option.
s0 : float
Expand Down Expand Up @@ -474,7 +474,7 @@ def get_itm_probability(
Parameters
----------
option_type : str
`OptionType` literal value, which must be either 'call' or 'put'.
`OptionType` literal value, which must be either **call** or **put**.
d2 : float | numpy.ndarray
`d2` in Black-Scholes formula.
years_to_maturity : float
Expand Down
38 changes: 19 additions & 19 deletions optionlab/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ class Stock(BaseLeg):
Attributes
----------
type : str
It must be 'stock'. It is mandatory.
It must be **stock**.
n : int
Number of shares. It is mandatory.
Number of shares.
action : str
`Action` literal value, which must be either 'buy' or 'sell'. It is mandatory.
`Action` literal value, which must be either **buy** or **sell**.
prev_pos : float | None, optional
Stock price effectively paid or received in a previously opened position.
If positive, the position remains open and the payoff calculation considers
Expand All @@ -48,24 +48,23 @@ class Option(BaseLeg):
Attributes
----------
type : str
`OptionType` literal value, which must be either 'call' or 'put'. It is
mandatory.
`OptionType` literal value, which must be either **call** or **put**.
strike : float
Option strike price. It is mandatory.
Strike price.
premium : float
Option premium. It is mandatory.
Option premium.
n : int
Number of options. It is mandatory
Number of options.
action : str
`Action` literal value, which must be either 'buy' or 'sell'.
`Action` literal value, which must be either **buy** or **sell**.
prev_pos : float | None, optional
Premium effectively paid or received in a previously opened position. If
positive, the position remains open and the payoff calculation considers
this price instead of the current price of the option. If negative, the
position is closed and the difference between this price and the current
price is included in the payoff calculation. The default is None, which
means this option position is not a previously opened position.
expiration : str | int | None, optional.
expiration : str | int | None, optional
Expiration date or number of days remaining to maturity. The default is
None.
"""
Expand All @@ -89,10 +88,10 @@ class ClosedPosition(BaseModel):
Attributes
----------
type : str
It must be 'closed'. It is mandatory.
It must be **closed**.
prev_pos : float
The total amount of the closed position. If positive, it resulted in a
profit; if negative, it incurred a loss. It is mandatory.
profit; if negative, it incurred a loss.
"""

type: Literal["closed"] = "closed"
Expand All @@ -115,7 +114,7 @@ class BlackScholesModelInputs(TheoreticalModelInputs):
Attributes
----------
model : str
It must be either 'black-scholes' or 'normal'.
It must be either **black-scholes** or **normal**.
stock_price : float
Stock price.
volatility : float
Expand Down Expand Up @@ -143,7 +142,7 @@ class LaplaceInputs(TheoreticalModelInputs):
Attributes
----------
model : str
It must be 'laplace'.
It must be **laplace**.
stock_price : float
Stock price.
mu : float
Expand All @@ -168,7 +167,7 @@ class ArrayInputs(BaseModel):
Attributes
----------
model : str
It must be 'array'.
It must be **array**.
array : numpy.ndarray
Array of strategy returns.
"""
Expand Down Expand Up @@ -223,7 +222,7 @@ class Inputs(BaseModel):
Number of business days in a year. The default is 252.
country : str, optional
Country whose holidays will be counted if `discard_nonbusinessdays` is
set to True. The default is 'US'.
set to True. The default is **US**.
start_date : datetime.date, optional
Start date in the calculations. If not provided, `days_to_target_date`
must be provided.
Expand All @@ -234,8 +233,9 @@ class Inputs(BaseModel):
Days remaining to the target date. If not provided, `start_date` and
`target_date` must be provided.
model : str, optional
Theoretical model used in the calculations. It can be 'black-scholes'
(the same as 'normal') or 'array'. The default is 'black-scholes'.
Theoretical model used in the calculations of probability of profit. It
can be **black-scholes** (the same as **normal**) or **array**. The default
is **black-scholes**.
array : numpy.ndarray | None, optional
Array of terminal stock prices. The default is None.
"""
Expand Down Expand Up @@ -491,7 +491,7 @@ def __str__(self):

class PoPOutputs(BaseModel):
"""
Defineas the output data from a probability of profit (PoP) calculation.
Defines the output data from a probability of profit (PoP) calculation.
Attributes
----------
Expand Down
18 changes: 9 additions & 9 deletions optionlab/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ def get_pl_profile(
Parameters
----------
option_type : str
`OptionType` literal value, which must be either 'call' or 'put'.
`OptionType` literal value, which must be either **call** or **put**.
action : str
`Action` literal value, which must be either 'buy' or 'sell'.
`Action` literal value, which must be either **buy** or **sell**.
x : float
Strike price.
val : float
Expand Down Expand Up @@ -80,7 +80,7 @@ def get_pl_profile_stock(
s0 : float
Initial stock price.
action : str
`Action` literal value, which must be either 'buy' or 'sell'.
`Action` literal value, which must be either **buy** or **sell**.
n : int
Number of shares.
s : numpy.ndarray
Expand Down Expand Up @@ -124,9 +124,9 @@ def get_pl_profile_bs(
Parameters
----------
option_type : str
`OptionType` literal value, which must be either 'call' or 'put'.
`OptionType` literal value, which must be either **call** or **put**.
action : str
`Action` literal value, which must be either 'buy' or 'sell'.
`Action` literal value, which must be either **buy** or **sell**.
x : float
Strike price.
val : float
Expand Down Expand Up @@ -428,11 +428,11 @@ def _get_pl_option(
Parameters
----------
option_type : str
`OptionType` literal value, which must be either 'call' or 'put'.
`OptionType` literal value, which must be either **call** or **put**.
opvalue : float
Option price.
action : str
`Action` literal value, which must be either 'buy' or 'sell'.
`Action` literal value, which must be either **buy** or **sell**.
s : numpy.ndarray
Array of stock prices.
x : float
Expand All @@ -459,7 +459,7 @@ def _get_payoff(option_type: OptionType, s: np.ndarray, x: float) -> np.ndarray:
Parameters
----------
option_type : str
`OptionType` literal value, which must be either 'call' or 'put'.
`OptionType` literal value, which must be either **call** or **put**.
s : numpy.ndarray
Array of stock prices.
x : float
Expand Down Expand Up @@ -488,7 +488,7 @@ def _get_pl_stock(s0: float, action: Action, s: np.ndarray) -> np.ndarray:
s0 : float
Spot price of the underlying asset.
action : str
`Action` literal value, which must be either 'buy' or 'sell'.
`Action` literal value, which must be either **buy** or **sell**.
s : numpy.ndarray
Array of stock prices.
Expand Down
56 changes: 56 additions & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,28 @@
"rho": [0.08536880237502181, -0.07509774107468528],
}

PROB_NAKED_CALL = {
"probability_of_profit": 0.8389215512144531,
"profit_ranges": [(0.0, 176.14)],
"expected_profit": 115.0,
"expected_loss": -707.0,
"per_leg_cost": [114.99999999999999],
"strategy_cost": 114.99999999999999,
"minimum_return_in_the_domain": -6991.999999999999,
"maximum_return_in_the_domain": 114.99999999999999,
"implied_volatility": [0.256],
"in_the_money_probability": [0.1832371984432129],
"delta": [-0.20371918274704337],
"gamma": [0.023104402361599465],
"theta": [0.091289876347897],
"vega": [0.12750177318341913],
"rho": [-0.02417676577711979],
"probability_of_profit_target": 0.8197909190785164,
"profit_target_ranges": [(0.0, 175.15)],
"probability_of_loss_limit": 0.14307836806156238,
"loss_limit_ranges": [(177.15, float("inf"))],
}


def test_black_scholes():
stock_price = 100.0
Expand Down Expand Up @@ -209,6 +231,40 @@ def test_100_perc_itm(nvidia):
) == pytest.approx(PROB_100_ITM_RESULT)


def test_naked_call():
inputs = Inputs.model_validate(
{
"stock_price": 164.04,
"volatility": 0.272,
"start_date": "2021-11-22",
"target_date": "2021-12-17",
"interest_rate": 0.0002,
"min_stock": 82.02,
"max_stock": 246.06,
"profit_target": 100.0,
"loss_limit": -100.0,
"model": "black-scholes",
# The naked call strategy is defined
"strategy": [
{
"type": "call",
"strike": 175.00,
"premium": 1.15,
"n": 100,
"action": "sell",
}
],
}
)

outputs = run_strategy(inputs)

assert isinstance(outputs, Outputs)
assert outputs.model_dump(
exclude={"data", "inputs"}, exclude_none=True
) == pytest.approx(PROB_NAKED_CALL)


def test_3_legs(nvidia):
inputs = Inputs.model_validate(
nvidia
Expand Down

0 comments on commit 638e677

Please sign in to comment.