Skip to content

Commit

Permalink
Updated README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
rgaveiga committed Jan 19, 2025
1 parent 638e677 commit 12746d6
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 300 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.benchmarks
.mypy_cache
.pytest_cache
__pycache__
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Created a class `PoPOutputs` in models.py containing fields returned by `get_pop` in support.py
- Removed Laplace form `get_pop` in support.py
- Improved `get_pop` in support.py to return a `PoPOutputs` object with more information
- Added naked calls as an example of strategy

## 1.4.0 (2025-01-01)

Expand Down
335 changes: 36 additions & 299 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,16 @@ quick evaluation of option strategies.
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, 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.
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,
expected profit and expected loss.

The probability of profit (PoP) for the strategy is calculated based on the distribution
of estimated prices of the underlying asset on the user-defined target date.
Specifically, for the price range in the payoff where the strategy generates profit, the
PoP represents the probability that the stock price will fall within that range. This
distribution of underlying asset prices on the target date can be lognormal,
log-Laplace, or derived from the Black-Scholes model. Additionally, the distribution can
be obtained through simulations (e.g., Monte Carlo) or machine learning models.
The probability of profit (PoP), expected profit and expected loss at the user-defined target
date for the strategy are calculated by default using the Black-Scholes model. Alternatively,
the user can provide an array of underlying asset prices following a distribution other than
the normal (e.g. Laplace) or model other than the Black-Scholes model (e.g. Heston model) that
will be used in the calculations.

Despite the code having been developed with option strategies in mind, it can also be
used for strategies that combine options with stocks and/or take into account the
Expand All @@ -25,7 +24,9 @@ profits or losses of closed trades.
If you have any questions, corrections, comments or suggestions, just
[drop a message](mailto:[email protected]).

You can also reach me on [Linkedin](https://www.linkedin.com/in/roberto-gomes-phd-8a718317b/).
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).

## Installation

Expand All @@ -37,158 +38,11 @@ pip install optionlab

## Basic usage

Usage examples for several strategies can be found in Jupyter notebooks in the **examples**
directory.

The evaluation of a strategy is done by calling the `run_strategy` function provided by the library.
This function receives the input data either as a Python dictionary or an `Inputs` object.

The description of the input data follows:

---

- `stock_price` : float
- Spot price of the underlying.

- `volatility` : float
- Annualized volatility.

- `interest_rate` : float
- Annualized risk-free interest rate.

- `min_stock` : float
- Minimum value of the stock in the stock price domain.

- `max_stock` : float
- Maximum value of the stock in the stock price domain.

- `strategy` : list
- A list of strategy legs.

- `dividend_yield` : float, optional
- Annualized dividend yield. Default is 0.0.

- `profit_target` : float, optional
- Target profit level. Default is None, which means it is not calculated.

- `loss_limit` : float, optional
- Limit loss level. Default is None, which means it is not calculated.

- `opt_commission` : float
- Broker commission for options transactions. Default is 0.0.

- `stock_commission` : float
- Broker commission for stocks transactions. Default is 0.0.

- `compute_expectation` : logical, optional
- Whether or not the strategy's average profit and loss must be computed from a numpy
array of random terminal prices generated from the chosen distribution. Default is
False.

- `discard_nonbusinessdays` : logical, optional
- Whether to discard Saturdays and Sundays (and maybe holidays) when counting the
number of days between two dates. Default is True.

- `country` : string, optional
- Country for which the holidays will be considered if 'discard_nonbusinessdays' is
True. Default is 'US'.

- `start_date` : dt.date, optional
- Start date in the calculations. If not provided, days_to_target_date must be
provided.

- `target_date` : dt.date, optional
- Target date in the calculations. If not provided, days_to_target_date must be
provided.

- `days_to_target_date` : int, optional
- Number of days until the target date, typically the maturity date of the options.
If not provided, start_date and end_date must be provided.

- `distribution` : string, optional
- Statistical distribution used to compute probabilities. It can be 'black-scholes',
'normal', 'laplace' or 'array'. Default is 'black-scholes'.

- `mc_prices_number` : int, optional
- Number of random terminal prices to be generated when calculating the average
profit and loss of a strategy. Default is 100,000.

---

The `strategy` attribute is a list of strategy legs, where each leg can be of type
`Option`, `Stock`, or `ClosedPosition`.

The `Option` structure:

---

- `type` : string
- Either 'call' or 'put'. It is mandatory.

- `strike` : float
- Option strike price. It is mandatory.

- `premium` : float
- Option premium. It is mandatory.

- `n` : int
- Number of options. It is mandatory.

- `action` : string
- Either 'buy' or 'sell'. It is mandatory.

- `prev_pos` : float
- Premium effectively paid or received in a previously opened position. If positive,
it means that the position remains open and the payoff calculation takes this price
into account, not the current price of the option. If negative, it means that the
position is closed and the difference between this price and the current price is
considered in the payoff calculation.

- `expiration` : string | int
- Expiration date or days to maturity.

---

`Stock`:

---

- `type` : string
- It must be 'stock'. It is mandatory.

- `n` : int
- Number of shares. It is mandatory.

- `action` : string
- Either 'buy' or 'sell'. It is mandatory.

- `prev_pos` : float
- Stock price effectively paid or received in a previously opened position. If
positive, it means that the position remains open and the payoff calculation
takes this price into account, not the current price of the stock. If negative, it
means that the position is closed and the difference between this price and the
current price is considered in the payoff calculation.

---

For a non-determined previously opened position to be closed, which might consist
of any combination of calls, puts and stocks, the `ClosedPosition` must contain two
keys:

---

- `type` : string
- It must be 'closed'. It is mandatory.

- `prev_pos` : float
- The total value of the position to be closed, which can be positive if it made
a profit or negative if it is a loss. It is mandatory.

---

For example, let's say we wanted to calculate the probability of profit for naked
calls on Apple stocks with maturity on December 17, 2021. The strategy setup consisted
of selling 100 175.00 strike calls for 1.15 each on November 22, 2021.
The evaluation of a strategy is done by calling the `run_strategy` function provided by
the library. This function receives the input data either as a Python dictionary or an
`Inputs` object. For example, let's say we wanted to calculate the probability of profit
for naked calls on Apple stocks with maturity on December 17, 2021. The strategy setup
consisted of selling 100 175.00 strike calls for 1.15 each on November 22, 2021.

```python
input_data = {
Expand Down Expand Up @@ -219,151 +73,34 @@ from optionlab import run_strategy, plot_pl

out = run_strategy(input_data)

print(out)

plot_pl(out)
```

The variable `out` contains an `Outputs` object with the following structure:
The variable `out` is an `Outputs` object that contains the results from the
calculations. By calling `print` with `out` as an argument, these results are
displayed on screen. The `plot_pl` function, in turn, takes an `Outputs` object as
its argument and plots the profit/loss diagram for the strategy.

---

- `probability_of_profit` : float
- Probability of the strategy yielding at least $0.01.

- `profit_ranges` : list
- A list of minimum and maximum stock prices defining ranges in which the strategy
makes at least $0.01.

- `strategy_cost` : float
- Total strategy cost.

- `per_leg_cost` : list
- A list of costs, one per strategy leg.

- `implied_volatility` : list
- A Python list of implied volatilities, one per strategy leg.

- `in_the_money_probability` : list
- A list of ITM probabilities, one per strategy leg.

- `delta` : list
- A list of Delta values, one per strategy leg.

- `gamma` : list
- A list of Gamma values, one per strategy leg.

- `theta` : list
- A list of Theta values, one per strategy leg.

- `vega` : list
- A list of Vega values, one per strategy leg.

- `minimum_return_in_the_domain` : float
- Minimum return of the strategy within the stock price domain.

- `maximum_return_in_the_domain` : float
- Maximum return of the strategy within the stock price domain.

- `probability_of_profit_target` : float, optional
- Probability of the strategy yielding at least the profit target.

- `profit_target_ranges` : list, optional
- A list of minimum and maximum stock prices defining ranges in which the strategy
makes at least the profit target.

- `probability_of_loss_limit` : float, optional
- Probability of the strategy losing at least the loss limit.

- `average_profit_from_mc` : float, optional
- Average profit as calculated from Monte Carlo-created terminal stock prices for
which the strategy is profitable.

- `average_loss_from_mc` : float, optional
- Average loss as calculated from Monte Carlo-created terminal stock prices for
which the strategy ends in loss.

- `probability_of_profit_from_mc` : float, optional
- Probability of the strategy yielding at least $0.01 as calculated from Monte
Carlo-created terminal stock prices.
---

To obtain the probability of profit of the naked call example above:

```python
print(f"Probability of Profit (PoP): {(out.probability_of_profit * 100.0):.1f}%%") # 84.5%, according to the calculations
```

The `plot_pl` function takes an `Outputs` object as its argument and plots the profit/loss
diagram for the strategy.
Usage examples for a number of popular options trading strategies can be found in the
Jupyter notebooks in the **examples** directory.

## Contributions

### Dev setup

This repository uses `poetry` as a package manager. Install `poetry` as per the
[poetry docs](https://python-poetry.org/docs/#installing-with-pipx). It is
recommended to install `poetry` version 1.4.0 if there are issues with the latest
versions.

Once `poetry` is installed, set up your virtual environment for the repository with
the following:

```
cd optionlab/
python3.10 venv venv
source venv/bin/activate
poetry install
```

That should install all your dependencies and make you ready to contribute. Please
add tests for all new features and bug fixes and make sure you are formatting
with [black](https://github.com/psf/black).

Optionally, to use Jupyter, you can install it with: `pip install juypter`.

#### Git Hooks

This repo uses git hooks. Git hooks are scripts that run automatically every time
a particular event occurs in a Git repository. These events can include committing,
merging, and pushing, among others. Git hooks allow developers to enforce certain
standards or checks before actions are completed in the repository, enhancing the
workflow and code quality.

The pre-commit framework is a tool that leverages Git hooks to run checks on the
code before it is committed to the repository. By using pre-commit, developers can
configure various plugins or hooks that automatically check for syntax errors,
formatting issues, or even run tests on the code being committed. This ensures that
only code that passes all the defined checks can be added to the repository, helping
to maintain code quality and prevent issues from being introduced.

To install the pre-commit framework on a system with Homebrew, follow these steps:

```
brew install pre-commit
```

Once pre-commit is installed, navigate to the root directory of your Git repository
where you want to enable pre-commit hooks. Then, run the following command to set up
pre-commit for that repository. This command installs the Git hook scripts that the
pre-commit framework will use to run checks before commits.

```
pre-commit install
```

Now, before each commit, the pre-commit hooks you've configured will automatically
run. If any hook fails, the commit will be aborted, allowing you to fix the issues
before successfully committing your changes. This process helps maintain a high code
quality and ensures that common issues are addressed early in
the development process.

To check all files in a repository with pre-commit, use:

```
pre-commit run --all-files
```
Contributions are definitely welcome. However, it should be mentioned that this
repository uses [poetry](https://python-poetry.org/) as a package manager and
[git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) with
[pre-commit](https://pre-commit.com/)to customize actions on the repository.

## Disclaimer

This is free software and is provided as is. The author makes no guarantee that its
results are accurate and is not responsible for any losses caused by the use of the
code. Bugs can be reported as issues.
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.

Bugs can be reported as issues.
2 changes: 1 addition & 1 deletion optionlab/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ class Inputs(BaseModel):
Minimum value of the stock in the stock price domain.
max_stock : float
Maximum value of the stock in the stock price domain.
strategy : list
strategy : list[StrategyLeg]
A list of strategy legs.
dividend_yield : float, optional
Annualized dividend yield. The default is 0.0.
Expand Down

0 comments on commit 12746d6

Please sign in to comment.