Skip to content

Commit

Permalink
Merge pull request #1 from tejaskamtam/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
tejaskamtam authored Aug 22, 2023
2 parents 23e599c + fc891c9 commit 9ab766b
Show file tree
Hide file tree
Showing 12 changed files with 347 additions and 1 deletion.
6 changes: 6 additions & 0 deletions quantpyml/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# qol imports

from .returns import brownian_motion, geometric_brownian_motion
from .equity import EfficientFrontier, BlackScholes

__all__ = ['brownian_motion', 'geometric_brownian_motion', 'EfficientFrontier', 'BlackScholes']
6 changes: 6 additions & 0 deletions quantpyml/equity/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# import optimizers

from .efficient_frontier import EfficientFrontier
from .black_scholes import BlackScholes

__all__ = ['EfficientFrontier', 'BlackScholes']
File renamed without changes.
49 changes: 49 additions & 0 deletions quantpyml/equity/black_scholes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

from scipy.stats import norm
import numpy as np

class BlackScholes:
def __init__(self, price, strike, expiration: "T-days", vol: "annualized constant volatility", rate: "risk free rate" = 0.03, div: "dividend"=0):
self.S = price
self.K = strike
self.T = expiration/365
self.r = rate
self.sigma = vol
self.q = div


@staticmethod
def N(x):
return norm.cdf(x)

@property
def params(self):
return {'S': self.S,
'K': self.K,
'T': self.T,
'r':self.r,
'q':self.q,
'sigma':self.sigma}

def d1(self):
return (np.log(self.S/self.K) + (self.r -self.q + self.sigma**2/2)*self.T) / (self.sigma*np.sqrt(self.T))

def d2(self):
return self.d1() - self.sigma*np.sqrt(self.T)

def _call_value(self):
return self.S*np.exp(-self.q*self.T)*self.N(self.d1()) - self.K*np.exp(-self.r*self.T) * self.N(self.d2())

def _put_value(self):
return self.K*np.exp(-self.r*self.T) * self.N(-self.d2()) - self.S*np.exp(-self.q*self.T)*self.N(-self.d1())

def price(self, type_: "call (C), put (P), or both (B)" = 'C'):
if type_ == 'C':
return self._call_value()
if type_ == 'P':
return self._put_value()
if type_ == 'B':
return {'call': self._call_value(), 'put': self._put_value()}
else:
raise ValueError('Unrecognized type')

105 changes: 105 additions & 0 deletions quantpyml/equity/bs.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"# reference: https://www.codearmo.com/python-tutorial/options-trading-black-scholes-model\n",
"\n",
"from scipy.stats import norm\n",
"import numpy as np\n",
"\n",
"class BlackScholes:\n",
" def __init__(self, price, strike, expiration: \"T-days\", vol: \"annualized constant volatility\", rate: \"risk free rate\" = 0.03, div: \"dividend\"=0):\n",
" self.S = price\n",
" self.K = strike\n",
" self.T = expiration/365\n",
" self.r = rate\n",
" self.sigma = vol\n",
" self.q = div\n",
" \n",
" \n",
" @staticmethod\n",
" def N(x):\n",
" return norm.cdf(x)\n",
" \n",
" @property\n",
" def params(self):\n",
" return {'S': self.S, \n",
" 'K': self.K, \n",
" 'T': self.T, \n",
" 'r':self.r,\n",
" 'q':self.q,\n",
" 'sigma':self.sigma}\n",
" \n",
" def d1(self):\n",
" return (np.log(self.S/self.K) + (self.r -self.q + self.sigma**2/2)*self.T) / (self.sigma*np.sqrt(self.T))\n",
" \n",
" def d2(self):\n",
" return self.d1() - self.sigma*np.sqrt(self.T)\n",
" \n",
" def _call_value(self):\n",
" return self.S*np.exp(-self.q*self.T)*self.N(self.d1()) - self.K*np.exp(-self.r*self.T) * self.N(self.d2())\n",
" \n",
" def _put_value(self):\n",
" return self.K*np.exp(-self.r*self.T) * self.N(-self.d2()) - self.S*np.exp(-self.q*self.T)*self.N(-self.d1())\n",
" \n",
" def price(self, type_: \"call (C), put (P), or both (B)\" = 'C'):\n",
" if type_ == 'C':\n",
" return self._call_value()\n",
" if type_ == 'P':\n",
" return self._put_value() \n",
" if type_ == 'B':\n",
" return {'call': self._call_value(), 'put': self._put_value()}\n",
" else:\n",
" raise ValueError('Unrecognized type')\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'call': 0.25237702353658875, 'put': 0.17021901090664926}\n"
]
}
],
"source": [
"K = 100\n",
"r = 0.1\n",
"T = 1\n",
"sigma = 0.3\n",
"S = 100\n",
"print(BlackScholes(S, K, T, r, sigma).price('B'))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "torch",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.16"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@

import numpy as np
import matplotlib.pyplot as plt
import sklearn as sk
import scipy.optimize as spo
import pandas as pd

Expand Down
Empty file removed quantpyml/optimizers/__init__.py
Empty file.
6 changes: 6 additions & 0 deletions quantpyml/returns/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# imports

from .brownian_motion import brownian_motion
from .geometric_brownian_motion import geometric_brownian_motion

__all__ = ['brownian_motion', 'geometric_brownian_motion']
120 changes: 120 additions & 0 deletions quantpyml/returns/brownian_motion.ipynb

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions quantpyml/returns/brownian_motion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# implementation of arithmetic brownian motion

import numpy as np

def brownian_motion(nsims=10, ksteps: "number of time steps"=10000, t: "time step" = 0.01, mu: "drift or mean" = 0, sigma: "scaling or standard deviation" = 1):
"""
Weiner process: W(t) ~ N(0,t)
Brownian Motion: X(t) = mu*t + sigma*W(t)
Standard Brownian Motion: X(t) = W(t)
Geometric Brownian Motion: X(t) = exp[(mu-sigma^2/2)*t + sigma*W(t)]
"""
def X():
return mu*t + sigma*np.random.normal(loc=0, scale=np.sqrt(t), size=ksteps)
x = np.array([i*t for i in range(ksteps)])
sims = []
for i in range(nsims):
y = np.cumsum(X())
sims.append(y)
return sims, x
20 changes: 20 additions & 0 deletions quantpyml/returns/geometric_brownian_motion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# implementation of geometric brownian motion

import numpy as np

def geometric_brownian_motion(nsims=10, ksteps: "number of time steps"=1000, t: "time step" = 1, mu: "drift or mean" = 0.0001, sigma: "scaling or standard deviation" = 0.02):
"""
Weiner process: W(t) ~ N(0,t)
Brownian Motion: X(t) = X0 + mu*t + sigma*W(t)
Standard Brownian Motion: X(t) = X0 + W(t)
Geometric Brownian Motion: X(t) = X0 + exp((u-sigma^2/2)*t + sigma*W(t))
"""
def X():
return (mu-sigma**2/2)*t + sigma*np.random.normal(loc=0, scale=np.sqrt(t), size=ksteps)
x = np.array([i*t for i in range(ksteps)])
sims = []
for i in range(nsims):
y = np.exp(np.cumsum(X()))
sims.append(y)
return sims, x

16 changes: 16 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from quantpyml import brownian_motion
import matplotlib.pyplot as plt
import numpy as np

sims, x = brownian_motion()
# sims, x = geometric_brownian_motion()
for i in range(len(sims)):
plt.plot(x, sims[i])
# plot a trend line for all the simulations
plt.plot(x, np.mean(sims, axis=0), color='black', linewidth=3, label='trend')
plt.xlabel('Time')
plt.ylabel('Value')
plt.title('Brownian Motion')
plt.legend()
plt.show()

0 comments on commit 9ab766b

Please sign in to comment.