quantmod 0.0.4__tar.gz → 0.0.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {quantmod-0.0.4 → quantmod-0.0.5}/PKG-INFO +18 -3
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/__init__.py +3 -10
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/derivatives/__init__.py +2 -4
- quantmod-0.0.5/quantmod/derivatives/optionchain.py +249 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/indicators/indicators.py +27 -22
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/markets/yahoo.py +30 -15
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/models/__init__.py +5 -1
- quantmod-0.0.5/quantmod/models/binomial.py +184 -0
- quantmod-0.0.5/quantmod/models/blackscholes.py +393 -0
- quantmod-0.0.5/quantmod/models/montecarlo.py +145 -0
- quantmod-0.0.5/quantmod/models/optioninputs.py +49 -0
- quantmod-0.0.5/quantmod/risk/__init__.py +26 -0
- quantmod-0.0.5/quantmod/risk/var.py +108 -0
- quantmod-0.0.5/quantmod/risk/varbacktest.py +124 -0
- quantmod-0.0.5/quantmod/risk/varinputs.py +62 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/timeseries/performance.py +56 -49
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/timeseries/timeseries.py +12 -15
- quantmod-0.0.5/quantmod/version.py +1 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod.egg-info/PKG-INFO +18 -3
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod.egg-info/SOURCES.txt +4 -3
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod.egg-info/requires.txt +4 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/setup.py +9 -10
- quantmod-0.0.4/quantmod/derivatives/options.py +0 -47
- quantmod-0.0.4/quantmod/models/blackscholes.py +0 -156
- quantmod-0.0.4/quantmod/models/montecarlo.py +0 -115
- quantmod-0.0.4/quantmod/models/optioninputs.py +0 -44
- quantmod-0.0.4/quantmod/risk/__init__.py +0 -27
- quantmod-0.0.4/quantmod/risk/riskinputs.py +0 -36
- quantmod-0.0.4/quantmod/risk/var.py +0 -103
- quantmod-0.0.4/quantmod/risk/varbacktester.py +0 -85
- quantmod-0.0.4/quantmod/version.py +0 -1
- {quantmod-0.0.4 → quantmod-0.0.5}/LICENSE.txt +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/README.md +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/_version.py +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/datasets/__init__.py +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/datasets/data/__init__.py +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/datasets/data/nifty50.csv +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/datasets/data/spx.csv +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/datasets/dataloader.py +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/indicators/__init__.py +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/main.py +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/markets/__init__.py +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/markets/bb.py +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/timeseries/__init__.py +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod/utils.py +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod.egg-info/dependency_links.txt +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod.egg-info/entry_points.txt +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod.egg-info/not-zip-safe +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/quantmod.egg-info/top_level.txt +0 -0
- {quantmod-0.0.4 → quantmod-0.0.5}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: quantmod
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.5
|
|
4
4
|
Summary: Quantmod Python Package
|
|
5
5
|
Home-page: https://kannansingaravelu.com/
|
|
6
6
|
Author: Kannan Singaravelu
|
|
@@ -9,7 +9,6 @@ License: Apache License 2.0
|
|
|
9
9
|
Keywords: python,quant,quantmod,quantmod-python
|
|
10
10
|
Platform: any
|
|
11
11
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
14
13
|
Classifier: Operating System :: OS Independent
|
|
15
14
|
Classifier: Intended Audience :: Developers
|
|
@@ -20,13 +19,29 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
20
19
|
Requires-Python: >=3.10
|
|
21
20
|
Description-Content-Type: text/markdown
|
|
22
21
|
License-File: LICENSE.txt
|
|
22
|
+
Requires-Dist: joblib
|
|
23
|
+
Requires-Dist: jugaad-data
|
|
24
|
+
Requires-Dist: matplotlib
|
|
23
25
|
Requires-Dist: numpy>=2.0.2
|
|
24
26
|
Requires-Dist: pandas>=2.2.2
|
|
25
27
|
Requires-Dist: pydantic>=2.8.2
|
|
26
28
|
Requires-Dist: scipy>=1.13.1
|
|
29
|
+
Requires-Dist: sqlalchemy>=2.0.38
|
|
27
30
|
Requires-Dist: tabulate>=0.9.0
|
|
28
31
|
Requires-Dist: urllib3==1.26.15
|
|
29
32
|
Requires-Dist: yfinance>=0.2.43
|
|
33
|
+
Dynamic: author
|
|
34
|
+
Dynamic: author-email
|
|
35
|
+
Dynamic: classifier
|
|
36
|
+
Dynamic: description
|
|
37
|
+
Dynamic: description-content-type
|
|
38
|
+
Dynamic: home-page
|
|
39
|
+
Dynamic: keywords
|
|
40
|
+
Dynamic: license
|
|
41
|
+
Dynamic: platform
|
|
42
|
+
Dynamic: requires-dist
|
|
43
|
+
Dynamic: requires-python
|
|
44
|
+
Dynamic: summary
|
|
30
45
|
|
|
31
46
|
|
|
32
47
|
Quantmod Python package is inspired by the quantmod package for R. This new tool is designed to assist quantitative traders and data analysts with the development, testing, and rapid prototyping of trading strategies. quantmod features a straightforward and intuitive interface aimed at simplifying workflows and boosting productivity.
|
|
@@ -23,14 +23,7 @@
|
|
|
23
23
|
from . import version
|
|
24
24
|
from .main import hello
|
|
25
25
|
|
|
26
|
-
from quantmod import
|
|
27
|
-
derivatives,
|
|
28
|
-
indicators,
|
|
29
|
-
markets,
|
|
30
|
-
models,
|
|
31
|
-
timeseries,
|
|
32
|
-
datasets
|
|
33
|
-
)
|
|
26
|
+
from quantmod import derivatives, indicators, markets, models, timeseries, datasets
|
|
34
27
|
|
|
35
28
|
|
|
36
29
|
__all__ = [
|
|
@@ -40,8 +33,8 @@ __all__ = [
|
|
|
40
33
|
"markets",
|
|
41
34
|
"models",
|
|
42
35
|
"timeseries",
|
|
43
|
-
"datasets"
|
|
36
|
+
"datasets",
|
|
44
37
|
]
|
|
45
38
|
|
|
46
39
|
__version__ = version.version
|
|
47
|
-
__author__ = "Kannan Singaravelu"
|
|
40
|
+
__author__ = "Kannan Singaravelu"
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import numpy as np
|
|
3
|
+
from jugaad_data.nse import NSELive
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# construct a class object
|
|
7
|
+
class OptionChain:
|
|
8
|
+
"""
|
|
9
|
+
A class to fetch and process option chain data from NSE (National Stock Exchange).
|
|
10
|
+
|
|
11
|
+
Parameters
|
|
12
|
+
----------
|
|
13
|
+
symbol : str
|
|
14
|
+
Trading symbol (e.g., 'NIFTY', 'BANKNIFTY' or any equity symbol)
|
|
15
|
+
expiry_date : str
|
|
16
|
+
Expiry date of the options
|
|
17
|
+
|
|
18
|
+
Attributes
|
|
19
|
+
----------
|
|
20
|
+
option_chain : pandas.DataFrame
|
|
21
|
+
Processed option chain data
|
|
22
|
+
call_option_data : pandas.DataFrame
|
|
23
|
+
Call options data
|
|
24
|
+
put_option_date : pandas.DataFrame
|
|
25
|
+
Put options data
|
|
26
|
+
option_pain : float
|
|
27
|
+
Maximum pain strike price
|
|
28
|
+
|
|
29
|
+
Methods
|
|
30
|
+
-------
|
|
31
|
+
get_option_price()
|
|
32
|
+
Get the option price (last traded, bid, or ask) for a specific option
|
|
33
|
+
get_synthetic_futures()
|
|
34
|
+
Calculate synthetic futures price for a given strike price
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(self, symbol, expiry_date):
|
|
38
|
+
self.n = NSELive()
|
|
39
|
+
self.symbol = symbol
|
|
40
|
+
self.expiry_date = expiry_date
|
|
41
|
+
|
|
42
|
+
# flatten json and convert to dataframe
|
|
43
|
+
if symbol in ["NIFTY", "BANKNIFTY"]:
|
|
44
|
+
df = self.n.index_option_chain(self.symbol)["records"]["data"]
|
|
45
|
+
else:
|
|
46
|
+
df = self.n.equities_option_chain(self.symbol)["records"]["data"]
|
|
47
|
+
df = pd.json_normalize(df).fillna(0)
|
|
48
|
+
self.df = df[df["expiryDate"] == self.expiry_date]
|
|
49
|
+
|
|
50
|
+
# the __dict__ attributes
|
|
51
|
+
self.option_chain = self._get_option_chain()
|
|
52
|
+
self.call_option_data = self._get_call_option_data()
|
|
53
|
+
self.put_option_data = self._get_put_option_data()
|
|
54
|
+
self.option_pain = self._get_option_pain()
|
|
55
|
+
|
|
56
|
+
# get option chain
|
|
57
|
+
def _get_option_chain(self):
|
|
58
|
+
"""
|
|
59
|
+
Retrieve the complete option chain data.
|
|
60
|
+
|
|
61
|
+
Returns
|
|
62
|
+
-------
|
|
63
|
+
pandas.DataFrame
|
|
64
|
+
Complete option chain data for the specified symbol and expiry
|
|
65
|
+
"""
|
|
66
|
+
return self.df
|
|
67
|
+
|
|
68
|
+
# Create function to get call and put options
|
|
69
|
+
def _get_call_option_data(self):
|
|
70
|
+
"""
|
|
71
|
+
Extract and process call option data from the option chain.
|
|
72
|
+
|
|
73
|
+
Returns
|
|
74
|
+
-------
|
|
75
|
+
pandas.DataFrame
|
|
76
|
+
Processed call options data with simplified column names
|
|
77
|
+
"""
|
|
78
|
+
calls = self.option_chain.iloc[:, 21:].reset_index(drop=True)
|
|
79
|
+
cols = [i[3:] for i in calls.columns]
|
|
80
|
+
calls.columns = cols
|
|
81
|
+
return calls
|
|
82
|
+
|
|
83
|
+
def _get_put_option_data(self):
|
|
84
|
+
"""
|
|
85
|
+
Extract and process put option data from the option chain.
|
|
86
|
+
|
|
87
|
+
Returns
|
|
88
|
+
-------
|
|
89
|
+
pandas.DataFrame
|
|
90
|
+
Processed put options data with simplified column names
|
|
91
|
+
"""
|
|
92
|
+
puts = self.option_chain.iloc[:, 2:21].reset_index(drop=True)
|
|
93
|
+
cols = [i[3:] for i in puts.columns]
|
|
94
|
+
puts.columns = cols
|
|
95
|
+
return puts
|
|
96
|
+
|
|
97
|
+
# get option price
|
|
98
|
+
def get_option_price(self, strike, opt_type, txn_type=None):
|
|
99
|
+
"""
|
|
100
|
+
Get the option price (last traded, bid, or ask) for a specific option.
|
|
101
|
+
|
|
102
|
+
Parameters
|
|
103
|
+
----------
|
|
104
|
+
strike : float
|
|
105
|
+
Strike price of the option
|
|
106
|
+
opt_type : str
|
|
107
|
+
Option type ('CE' for Call or 'PE' for Put)
|
|
108
|
+
txn_type : str, optional
|
|
109
|
+
Transaction type ('buy', 'sell', or None for last price)
|
|
110
|
+
|
|
111
|
+
Returns
|
|
112
|
+
-------
|
|
113
|
+
float
|
|
114
|
+
Option price based on the specified parameters
|
|
115
|
+
"""
|
|
116
|
+
price_type = (
|
|
117
|
+
"bidprice"
|
|
118
|
+
if txn_type == "sell"
|
|
119
|
+
else "askPrice"
|
|
120
|
+
if txn_type == "buy"
|
|
121
|
+
else "lastPrice"
|
|
122
|
+
)
|
|
123
|
+
col = f"{opt_type}.{price_type}"
|
|
124
|
+
|
|
125
|
+
return float(self.df[self.df["strikePrice"] == strike][col].iloc[0])
|
|
126
|
+
|
|
127
|
+
# get synthetic futures
|
|
128
|
+
def get_synthetic_futures(self, strike):
|
|
129
|
+
"""
|
|
130
|
+
Calculate synthetic futures price for a given strike price.
|
|
131
|
+
Synthetic Futures price = Strike + Call - Put
|
|
132
|
+
|
|
133
|
+
Parameters
|
|
134
|
+
----------
|
|
135
|
+
strike : float
|
|
136
|
+
Strike price for which to calculate synthetic futures
|
|
137
|
+
|
|
138
|
+
Returns
|
|
139
|
+
-------
|
|
140
|
+
float
|
|
141
|
+
Synthetic futures price
|
|
142
|
+
"""
|
|
143
|
+
return (
|
|
144
|
+
strike
|
|
145
|
+
+ self.get_option_price(strike, opt_type="CE", txn_type="buy")
|
|
146
|
+
- self.get_option_price(strike, opt_type="PE", txn_type="sell")
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
def _get_option_pain(self) -> float:
|
|
150
|
+
"""
|
|
151
|
+
Calculate the maximum pain point - the strike price where the total value of all
|
|
152
|
+
options (calls and puts) would cause the most financial pain to option writers.
|
|
153
|
+
|
|
154
|
+
Returns
|
|
155
|
+
-------
|
|
156
|
+
float
|
|
157
|
+
Strike price at which maximum pain occurs
|
|
158
|
+
"""
|
|
159
|
+
# Get data from class attributes
|
|
160
|
+
strikes = np.array(self.option_chain["strikePrice"], dtype=float)
|
|
161
|
+
call_oi = np.array(self.call_option_data["openInterest"], dtype=float)
|
|
162
|
+
put_oi = np.array(self.put_option_data["openInterest"], dtype=float)
|
|
163
|
+
|
|
164
|
+
# Calculate pain for each possible expiry price
|
|
165
|
+
total_pain = []
|
|
166
|
+
|
|
167
|
+
for expiry_price in strikes:
|
|
168
|
+
# Calculate call options pain
|
|
169
|
+
call_pain = sum(
|
|
170
|
+
call_oi[i] * max(0, expiry_price - strike)
|
|
171
|
+
for i, strike in enumerate(strikes)
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
# Calculate put options pain
|
|
175
|
+
put_pain = sum(
|
|
176
|
+
put_oi[i] * max(0, strike - expiry_price)
|
|
177
|
+
for i, strike in enumerate(strikes)
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# Total pain at this price level
|
|
181
|
+
total_pain.append(call_pain + put_pain)
|
|
182
|
+
|
|
183
|
+
# Find strike with minimum pain
|
|
184
|
+
max_pain_index = np.argmin(total_pain)
|
|
185
|
+
return float(strikes[max_pain_index])
|
|
186
|
+
|
|
187
|
+
def plot_pain_analysis(self):
|
|
188
|
+
"""
|
|
189
|
+
Plot pain analysis for the option chain.
|
|
190
|
+
"""
|
|
191
|
+
# Get data from class attributes
|
|
192
|
+
strikes = np.array(self.option_chain["strikePrice"], dtype=float)
|
|
193
|
+
call_oi = np.array(self.call_option_data["openInterest"], dtype=float)
|
|
194
|
+
put_oi = np.array(self.put_option_data["openInterest"], dtype=float)
|
|
195
|
+
|
|
196
|
+
results = []
|
|
197
|
+
|
|
198
|
+
for expiry_price in strikes:
|
|
199
|
+
# Calculate call options pain
|
|
200
|
+
call_pain = sum(
|
|
201
|
+
call_oi[i] * max(0, expiry_price - strike)
|
|
202
|
+
for i, strike in enumerate(strikes)
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
# Calculate put options pain
|
|
206
|
+
put_pain = sum(
|
|
207
|
+
put_oi[i] * max(0, strike - expiry_price)
|
|
208
|
+
for i, strike in enumerate(strikes)
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
results.append(
|
|
212
|
+
{
|
|
213
|
+
"Strike": expiry_price,
|
|
214
|
+
"Call Pain": call_pain,
|
|
215
|
+
"Put Pain": put_pain,
|
|
216
|
+
"Total Pain": call_pain + put_pain,
|
|
217
|
+
}
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
analysis = pd.DataFrame(results)
|
|
221
|
+
# Plot the pain distribution (requires matplotlib)
|
|
222
|
+
try:
|
|
223
|
+
import matplotlib.pyplot as plt
|
|
224
|
+
|
|
225
|
+
plt.figure(figsize=(10, 6))
|
|
226
|
+
plt.plot(
|
|
227
|
+
analysis["Strike"], analysis["Total Pain"], "b-", label="Total Pain"
|
|
228
|
+
)
|
|
229
|
+
plt.plot(
|
|
230
|
+
analysis["Strike"], analysis["Call Pain"], "g--", label="Call Pain"
|
|
231
|
+
)
|
|
232
|
+
plt.plot(analysis["Strike"], analysis["Put Pain"], "r--", label="Put Pain")
|
|
233
|
+
plt.axvline(
|
|
234
|
+
x=self._get_option_pain(),
|
|
235
|
+
color="k",
|
|
236
|
+
linestyle=":",
|
|
237
|
+
label=f"Max Pain Strike: {self._get_option_pain():}",
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
plt.title("Option Pain Analysis")
|
|
241
|
+
plt.xlabel("Strike Price")
|
|
242
|
+
plt.ylabel("Pain Value")
|
|
243
|
+
plt.legend()
|
|
244
|
+
plt.grid(True)
|
|
245
|
+
|
|
246
|
+
except ImportError:
|
|
247
|
+
print("\nMatplotlib not installed. Skipping plot generation.")
|
|
248
|
+
|
|
249
|
+
plt.show()
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
2
|
|
|
3
|
+
|
|
3
4
|
def ATR(df: pd.DataFrame, lookback: int = 14) -> pd.Series:
|
|
4
5
|
"""
|
|
5
6
|
Calculate the Average True Range (ATR).
|
|
@@ -20,20 +21,20 @@ def ATR(df: pd.DataFrame, lookback: int = 14) -> pd.Series:
|
|
|
20
21
|
pd.Series
|
|
21
22
|
series containing the ATR values for each period
|
|
22
23
|
"""
|
|
23
|
-
|
|
24
|
+
|
|
24
25
|
df = df.copy()
|
|
25
26
|
df.rename(columns=str.lower, inplace=True)
|
|
26
|
-
|
|
27
|
-
df[
|
|
28
|
-
df[
|
|
29
|
-
df[
|
|
30
|
-
|
|
31
|
-
df[
|
|
32
|
-
df[
|
|
33
|
-
|
|
34
|
-
data = df.drop([
|
|
35
|
-
|
|
36
|
-
return data[
|
|
27
|
+
|
|
28
|
+
df["H-L"] = abs(df["high"] - df["low"])
|
|
29
|
+
df["H-PC"] = abs(df["high"] - df["close"].shift(1))
|
|
30
|
+
df["L-PC"] = abs(df["low"] - df["close"].shift(1))
|
|
31
|
+
|
|
32
|
+
df["TR"] = df[["H-L", "H-PC", "L-PC"]].max(axis=1, skipna=False)
|
|
33
|
+
df["ATR"] = df["TR"].rolling(lookback).mean()
|
|
34
|
+
|
|
35
|
+
data = df.drop(["H-L", "H-PC", "L-PC"], axis=1) # drop columns
|
|
36
|
+
|
|
37
|
+
return data["ATR"]
|
|
37
38
|
|
|
38
39
|
|
|
39
40
|
def BBands(series: pd.Series, lookback: int, multiplier: float = 2) -> pd.Series:
|
|
@@ -77,7 +78,7 @@ def SMA(series: pd.Series, lookback: int) -> pd.Series:
|
|
|
77
78
|
time series to calculate the Moving Average for
|
|
78
79
|
lookback : int
|
|
79
80
|
lookback period for the Moving Average
|
|
80
|
-
|
|
81
|
+
|
|
81
82
|
Returns
|
|
82
83
|
-------
|
|
83
84
|
pd.Series
|
|
@@ -86,6 +87,7 @@ def SMA(series: pd.Series, lookback: int) -> pd.Series:
|
|
|
86
87
|
|
|
87
88
|
return series.rolling(lookback).mean()
|
|
88
89
|
|
|
90
|
+
|
|
89
91
|
def EMA(series: pd.Series, lookback: int) -> pd.Series:
|
|
90
92
|
"""
|
|
91
93
|
Exponential Moving Average
|
|
@@ -96,7 +98,7 @@ def EMA(series: pd.Series, lookback: int) -> pd.Series:
|
|
|
96
98
|
time series to calculate the Exponential Moving Average for
|
|
97
99
|
lookback : int
|
|
98
100
|
lookback period for the Exponential Moving Average
|
|
99
|
-
|
|
101
|
+
|
|
100
102
|
Returns
|
|
101
103
|
-------
|
|
102
104
|
pd.Series
|
|
@@ -120,7 +122,7 @@ def MACD(series: pd.Series, lookback: int, fast: int, slow: int) -> pd.Series:
|
|
|
120
122
|
fast period for the MACD
|
|
121
123
|
slow : int
|
|
122
124
|
slow period for the MACD
|
|
123
|
-
|
|
125
|
+
|
|
124
126
|
Returns
|
|
125
127
|
-------
|
|
126
128
|
pd.Series
|
|
@@ -128,13 +130,17 @@ def MACD(series: pd.Series, lookback: int, fast: int, slow: int) -> pd.Series:
|
|
|
128
130
|
"""
|
|
129
131
|
|
|
130
132
|
# Calculate MACD line
|
|
131
|
-
macd =
|
|
132
|
-
|
|
133
|
+
macd = (
|
|
134
|
+
series.ewm(span=fast, adjust=False).mean()
|
|
135
|
+
- series.ewm(span=slow, adjust=False).mean()
|
|
136
|
+
)
|
|
137
|
+
|
|
133
138
|
# Calculate Signal line from the MACD line
|
|
134
139
|
signal = macd.ewm(span=lookback, adjust=False).mean()
|
|
135
|
-
|
|
140
|
+
|
|
136
141
|
return macd, signal
|
|
137
142
|
|
|
143
|
+
|
|
138
144
|
def RSI(series: pd.Series, lookback: int) -> pd.Series:
|
|
139
145
|
"""
|
|
140
146
|
Relative Strength Index
|
|
@@ -145,7 +151,7 @@ def RSI(series: pd.Series, lookback: int) -> pd.Series:
|
|
|
145
151
|
time series to calculate the RSI for
|
|
146
152
|
lookback : int
|
|
147
153
|
lookback period for the RSI
|
|
148
|
-
|
|
154
|
+
|
|
149
155
|
Returns
|
|
150
156
|
-------
|
|
151
157
|
pd.Series
|
|
@@ -158,10 +164,9 @@ def RSI(series: pd.Series, lookback: int) -> pd.Series:
|
|
|
158
164
|
# Separate gains and losses
|
|
159
165
|
gain = (delta.where(delta > 0, 0)).rolling(window=lookback).mean()
|
|
160
166
|
loss = (-delta.where(delta < 0, 0)).rolling(window=lookback).mean()
|
|
161
|
-
|
|
167
|
+
|
|
162
168
|
# Calculate the Relative Strength (RS)
|
|
163
169
|
rs = gain / loss
|
|
164
|
-
|
|
170
|
+
|
|
165
171
|
# Calculate RSI
|
|
166
172
|
return 100 - (100 / (1 + rs))
|
|
167
|
-
|
|
@@ -46,32 +46,38 @@ from typing import Union, List
|
|
|
46
46
|
# # Ensure cache directory exists
|
|
47
47
|
# if not os.path.exists(CACHE_DIR):
|
|
48
48
|
# os.makedirs(CACHE_DIR)
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
# cache_file = _get_cache_file_name(tickers, start_date, end_date, period, interval)
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
# # Check if cached file exists
|
|
53
53
|
# if os.path.exists(cache_file):
|
|
54
54
|
# # print(f"Loading data from cache: {cache_file}")
|
|
55
55
|
# return joblib.load(cache_file)
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
# try:
|
|
58
58
|
# # Download data from yfinance
|
|
59
59
|
# data = yf.download(tickers, start=start_date, end=end_date, auto_adjust=True, progress=False, period=period, interval=interval)
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
# # Save data to cache
|
|
62
62
|
# joblib.dump(data, cache_file)
|
|
63
63
|
# # print(f"Data cached to: {cache_file}")
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
# except Exception as e:
|
|
66
66
|
# print(f"Error downloading data: {e}")
|
|
67
67
|
# raise
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
# return data
|
|
70
70
|
|
|
71
71
|
|
|
72
|
-
def getData(
|
|
72
|
+
def getData(
|
|
73
|
+
tickers: Union[str, List[str]],
|
|
74
|
+
start_date: str = None,
|
|
75
|
+
end_date: str = None,
|
|
76
|
+
period: str = "1mo",
|
|
77
|
+
interval: str = "1d",
|
|
78
|
+
) -> pd.DataFrame:
|
|
73
79
|
"""
|
|
74
|
-
Retrieve data
|
|
80
|
+
Retrieve data using yfinance library for specified tickers.
|
|
75
81
|
|
|
76
82
|
Parameters
|
|
77
83
|
----------
|
|
@@ -94,16 +100,25 @@ def getData(tickers: Union[str, List[str]], start_date: str = None, end_date: st
|
|
|
94
100
|
DataFrame with OHLC[A]V (Open, High, Low, Close, Adj Close, Volume).
|
|
95
101
|
"""
|
|
96
102
|
|
|
97
|
-
cols = [
|
|
98
|
-
data = yf.download(
|
|
99
|
-
|
|
103
|
+
cols = ["Open", "High", "Low", "Close", "Volume"]
|
|
104
|
+
data = yf.download(
|
|
105
|
+
tickers,
|
|
106
|
+
start=start_date,
|
|
107
|
+
end=end_date,
|
|
108
|
+
auto_adjust=True,
|
|
109
|
+
progress=False,
|
|
110
|
+
multi_level_index=False,
|
|
111
|
+
period=period,
|
|
112
|
+
interval=interval,
|
|
113
|
+
)
|
|
114
|
+
|
|
100
115
|
return data[cols]
|
|
101
116
|
|
|
102
117
|
|
|
103
|
-
# Retrieve ticker object
|
|
118
|
+
# Retrieve ticker object using yfinance library
|
|
104
119
|
def getTicker(ticker: str) -> yf.Ticker:
|
|
105
120
|
"""
|
|
106
|
-
Retrieve ticker object
|
|
121
|
+
Retrieve ticker object using yfinance library.
|
|
107
122
|
|
|
108
123
|
Parameters
|
|
109
124
|
----------
|
|
@@ -118,7 +133,7 @@ def getTicker(ticker: str) -> yf.Ticker:
|
|
|
118
133
|
|
|
119
134
|
# for all available options, refer yfinance
|
|
120
135
|
# .info
|
|
121
|
-
# .history
|
|
136
|
+
# .history
|
|
122
137
|
# .actions
|
|
123
138
|
# .dividends
|
|
124
139
|
# .splits
|
|
@@ -138,7 +153,7 @@ def getTicker(ticker: str) -> yf.Ticker:
|
|
|
138
153
|
# .earnings_dates
|
|
139
154
|
# .isin
|
|
140
155
|
# .options
|
|
141
|
-
|
|
156
|
+
# . option_chain('YYYY-MM-DD')
|
|
142
157
|
# .news
|
|
143
158
|
|
|
144
159
|
return yf.Ticker(ticker)
|
|
@@ -19,10 +19,14 @@
|
|
|
19
19
|
from .optioninputs import OptionInputs
|
|
20
20
|
from .blackscholes import BlackScholesOptionPricing
|
|
21
21
|
from .montecarlo import MonteCarloOptionPricing
|
|
22
|
+
from .binomial import OptionType, ExerciseStyle, BinomialOptionPricing
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
__all__ = [
|
|
25
26
|
"OptionInputs",
|
|
26
|
-
"
|
|
27
|
+
"OptionType",
|
|
28
|
+
"ExerciseStyle",
|
|
29
|
+
"BlackScholesOptionPricing",
|
|
27
30
|
"MonteCarloOptionPricing",
|
|
31
|
+
"BinomialOptionPricing",
|
|
28
32
|
]
|