Skip to content

feat: Add README and code comments #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
66 changes: 64 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,68 @@
## Black-Scholes model in pure Python
### Without SciPy, NumPy or other external dependencies

Use **example_greeks.py** to calculate *Theo, Delta, Theta, Vega, Gamma* for single option
# PyOption Pricing & Greeks

Use **example_plot.py** to visualize your position with *Matplotlib*
This project provides a set of tools in Python for calculating the theoretical price of options using the Black-Scholes-Merton (BSM) model, as well as the main Greeks (Delta, Vega, Theta, and Gamma). Additionally, it offers functionalities to visualize the P&L (Profit and Loss) and the Greeks of an option portfolio under different price scenarios and expiration dates.

## Key Features

* **Option Pricing:** Implementation of the Black-Scholes-Merton model to calculate the theoretical price of call and put options.
* **Greeks Calculation:** Provides functions to calculate option sensitivities:
* **Delta ($\Delta$):** Measures the sensitivity of the option price to a change in the underlying asset price.
* **Vega ($\nu$):** Measures the sensitivity of the option price to a change in the implied volatility of the underlying asset.
* **Theta ($\Theta$):** Measures the sensitivity of the option price to the passage of time (time decay).
* **Gamma ($\Gamma$):** Measures the rate of change of Delta with respect to a change in the underlying asset price.
* **Portfolio Analysis:** Allows for the analysis of a portfolio composed of multiple options and the underlying asset, calculating the total Greeks and P&L of the portfolio.
* **Graphical Visualization:** Utilizes the `matplotlib` library to generate graphs of:
* Portfolio P&L as a function of the underlying asset price for different expiration dates.
* The Greeks (Delta, Theta, Vega, Gamma) of the portfolio as a function of the underlying asset price for different expiration dates.
* **(In Development) Delta Neutral Search:** The `searching.py` module appears to contain in-development functionalities for finding prices where a specific individual option neutralizes the portfolio's Delta.

## How to Use

### Prerequisites

* Python 3.x
* `matplotlib` library

### Installation

1. Ensure you have Python 3 installed on your system.
2. Install the `matplotlib` library using pip if you haven't already:
```bash
pip install matplotlib
```

### Usage Examples

1. **Calculating Greeks for an Option:** Run the `exemple_greeks.py` script:
```bash
python exemple_greeks.py
```
This script demonstrates how to instantiate the `BSM` class and calculate the theoretical price, Delta, Theta, Vega, and Gamma for a Bitcoin option with example parameters.

2. **Visualizing Portfolio P&L and Greeks:** Run the `exemple_plot.py` script:
```bash
python exemple_plot.py
```
This script uses the `Plot` class to generate graphs showing the P&L, Delta, Theta, Vega, and Gamma of an option portfolio defined within the script, across different expiration dates. The legends on the graphs indicate the number of days until expiration.

3. **(In Development) Delta Neutral Search:** The `searching.py` script contains a `Search` class with a `searchDelta` method. To use it (remember it's under development), you can execute the script and observe the output:
```bash
python searching.py
```
The output displays a table with the underlying asset price, option type, strike price, quantity, individual option Delta, total portfolio Delta, and the theoretical option price, searching for points where the individual option's Delta offsets the total portfolio Delta.

## Project Structure

* `bsm.py`: Contains the implementation of the `BSM` class with methods to calculate the theoretical price (theo), the Greeks (delta, vega, theta, gamma), and the standard normal distribution functions (pdf and cdf).
* `pricing.py`: Extends the `BSM` class and implements methods to calculate the total Greeks (`deltaFull`, `vegaFull`, `thetaFull`, `gammaFull`) and the P&L (`p_l`) of a portfolio of assets and options.
* `plot.py`: Utilizes the `Pricing` class and the `matplotlib` library to generate graphs of the portfolio's P&L and Greeks as a function of the underlying asset price for different expiration dates.
* `exemple_greeks.py`: An example script demonstrating how to use the `BSM` class to calculate the Greeks of a single option.
* `exemple_plot.py`: An example script that uses the `Plot` class to generate graphical visualizations of an option portfolio.
* `searching.py`: A script containing a `Search` class with functionalities under development to assist in finding delta-neutral positions, comparing the delta of an individual option with the total portfolio delta.

## Contributing

Contributions are welcome! Feel free to open issues to report bugs or suggest improvements, and submit pull requests with your implementations.
101 changes: 61 additions & 40 deletions example_plot.py
Original file line number Diff line number Diff line change
@@ -1,51 +1,72 @@
from plot import Plot
import matplotlib.pyplot as plt

# Creates an instance of the Plot class, which inherits pricing functionalities
plot = Plot()

# Defines the number of days in a year (used to convert time for the BSM model)
god = 365
# Defines the price increment to generate points on the graphs
step = 10
# Defines the depth (range) of the price around the current price for the graphs
deep = 7500

exp = 30 / god
exp2 = 15 / god
exp3 = 5 / god
# Defines different expiration times in years
exp = 30 / god # Approximately 30 days
exp2 = 15 / god # Approximately 15 days
exp3 = 5 / god # Approximately 5 days

# Defines the current price (spot price) of the underlying asset
fPrice = 21000

# Initializes a list to store the parameters of the positions in the portfolio
params = []

dType = 'F'
quant = 1
price = 20000
strike = 0
vola = 0
params.append({'dType': dType, 'price': price, 'quant': quant, 'strike': strike, 'vola': vola, 'exp': exp})

dType = 'C'
quant = 1
price = 500
strike = 25000
vola = 0.75
params.append({'dType': dType, 'price': price, 'quant': quant, 'strike': strike, 'vola': vola, 'exp': exp})

dType = 'P'
quant = 1
price = 100
strike = 15000
vola = 0.75
params.append({'dType': dType, 'price': price, 'quant': quant, 'strike': strike, 'vola': vola, 'exp': exp})

dType = 'P'
quant = -1
price = 25
strike = 10000
vola = 1.5
params.append({'dType': dType, 'price': price, 'quant': quant, 'strike': strike, 'vola': vola, 'exp': exp})

# Adds a position of the underlying asset (F - Future/Forward)
params.append({
'dType': 'F', # Type: Future/Forward asset
'quant': 1, # Quantity: 1 (long 1 unit)
'price': 20000, # Purchase price of the asset
'strike': 0, # Strike not applicable for the asset
'vola': 0, # Volatility not applicable for the asset
'exp': exp # Expiration time (irrelevant for the asset, but needed in the structure)
})

# Adds a long position (buy - 1) of a call option (C - Call)
params.append({
'dType': 'C', # Type: Call Option
'quant': 1, # Quantity: 1 (long 1 contract)
'price': 500, # Premium paid for the option
'strike': 25000, # Strike Price
'vola': 0.75, # Implied Volatility (75%)
'exp': exp # Expiration time
})

# Adds a long position (buy - 1) of a put option (P - Put)
params.append({
'dType': 'P', # Type: Put Option
'quant': 1, # Quantity: 1 (long 1 contract)
'price': 100, # Premium paid for the option
'strike': 15000, # Strike Price
'vola': 0.75, # Implied Volatility (75%)
'exp': exp # Expiration time
})

# Adds a short position (sell - -1) of a put option (P - Put)
params.append({
'dType': 'P', # Type: Put Option
'quant': -1, # Quantity: -1 (short 1 contract)
'price': 25, # Premium received for selling the option
'strike': 10000, # Strike Price
'vola': 1.5, # Implied Volatility (150%)
'exp': exp # Expiration time
})

# Defines the lower and upper price limits for the graphs
bePriceS = fPrice - deep
bePriceF = fPrice + deep

# Plots the Profit/Loss (P/L) of the portfolio for different expiration times
plot.plotPL(bePriceS, bePriceF, params, exp, step)
plot.plotPL(bePriceS, bePriceF, params, exp2, step)
plot.plotPL(bePriceS, bePriceF, params, exp3, step)
Expand All @@ -56,6 +77,7 @@
plt.legend()
plt.show()

# Plots the Delta of the portfolio for different expiration times
plot.plotDelta(bePriceS, bePriceF, params, exp, step)
plot.plotDelta(bePriceS, bePriceF, params, exp2, step)
plot.plotDelta(bePriceS, bePriceF, params, exp3, step)
Expand All @@ -66,6 +88,7 @@
plt.ylabel("Delta")
plt.show()

# Plots the Theta of the portfolio for different expiration times
plot.plotTheta(bePriceS, bePriceF, params, exp, step)
plot.plotTheta(bePriceS, bePriceF, params, exp2, step)
plot.plotTheta(bePriceS, bePriceF, params, exp3, step)
Expand All @@ -76,6 +99,7 @@
plt.ylabel("Theta")
plt.show()

# Plots the Vega of the portfolio for different expiration times
plot.plotVega(bePriceS, bePriceF, params, exp, step)
plot.plotVega(bePriceS, bePriceF, params, exp2, step)
plot.plotVega(bePriceS, bePriceF, params, exp3, step)
Expand All @@ -86,6 +110,7 @@
plt.ylabel("Vega")
plt.show()

# Plots the Gamma of the portfolio for different expiration times
plot.plotGamma(bePriceS, bePriceF, params, exp, step)
plot.plotGamma(bePriceS, bePriceF, params, exp2, step)
plot.plotGamma(bePriceS, bePriceF, params, exp3, step)
Expand All @@ -96,13 +121,9 @@
plt.ylabel("Gamma")
plt.show()


print('D:\t', round(plot.deltaFull(fPrice, params, exp), 2))

print('V:\t', round(plot.vegaFull(fPrice, params, exp), 2))

print('T:\t', round(plot.thetaFull(fPrice, params, exp), 2))

print('G:\t', round(plot.gammaFull(fPrice, params, exp), 2))

# Prints the aggregated (Full) values of the Greeks and P/L at the current price
print('Delta:\t', round(plot.deltaFull(fPrice, params, exp), 2))
print('Vega:\t', round(plot.vegaFull(fPrice, params, exp), 2))
print('Theta:\t', round(plot.thetaFull(fPrice, params, exp), 2))
print('Gamma:\t', round(plot.gammaFull(fPrice, params, exp), 2))
print('P/L:\t', plot.p_l(fPrice, params, exp))