XSII
References
Load basic packages
import pandas as pd
import numpy as np
import os
import gc
import copy
from pathlib import Path
from datetime import datetime, timedelta, time, date
#this package is to download equity price data from yahoo finance
#the source code of this package can be found here: https://github.com/ranaroussi/yfinance/blob/main
import yfinance as yf
pd.options.display.max_rows = 100
pd.options.display.max_columns = 100
import warnings
warnings.filterwarnings("ignore")
import pytorch_lightning as pl
random_seed=1234
pl.seed_everything(random_seed)
Global seed set to 1234
1234
#S&P 500 (^GSPC), Dow Jones Industrial Average (^DJI), NASDAQ Composite (^IXIC)
#Russell 2000 (^RUT), Crude Oil Nov 21 (CL=F), Gold Dec 21 (GC=F)
#Treasury Yield 10 Years (^TNX)
#benchmark_tickers = ['^GSPC', '^DJI', '^IXIC', '^RUT', 'CL=F', 'GC=F', '^TNX']
benchmark_tickers = ['^GSPC']
tickers = benchmark_tickers + ['GSK', 'NVO', 'AROC', 'CELH']
#https://github.com/ranaroussi/yfinance/blob/main/yfinance/base.py
# def history(self, period="1mo", interval="1d",
# start=None, end=None, prepost=False, actions=True,
# auto_adjust=True, back_adjust=False,
# proxy=None, rounding=False, tz=None, timeout=None, **kwargs):
dfs = {}
for ticker in tickers:
cur_data = yf.Ticker(ticker)
hist = cur_data.history(period="max", start='2000-01-01')
print(datetime.now(), ticker, hist.shape, hist.index.min(), hist.index.max())
dfs[ticker] = hist
2022-09-10 21:19:27.898196 ^GSPC (5710, 7) 1999-12-31 00:00:00 2022-09-09 00:00:00
2022-09-10 21:19:28.268001 GSK (5710, 7) 1999-12-31 00:00:00 2022-09-09 00:00:00
2022-09-10 21:19:28.628727 NVO (5710, 7) 1999-12-31 00:00:00 2022-09-09 00:00:00
2022-09-10 21:19:28.933448 AROC (3791, 7) 2007-08-21 00:00:00 2022-09-09 00:00:00
2022-09-10 21:19:29.205023 CELH (3938, 7) 2007-01-22 00:00:00 2022-09-09 00:00:00
ticker = 'GSK'
dfs[ticker].tail(5)
| Open | High | Low | Close | Volume | Dividends | Stock Splits | |
|---|---|---|---|---|---|---|---|
| Date | |||||||
| 2022-09-02 | 31.600000 | 31.969999 | 31.469999 | 31.850000 | 8152600 | 0.0 | 0.0 |
| 2022-09-06 | 31.650000 | 31.760000 | 31.370001 | 31.469999 | 5613900 | 0.0 | 0.0 |
| 2022-09-07 | 31.209999 | 31.590000 | 31.160000 | 31.490000 | 4822000 | 0.0 | 0.0 |
| 2022-09-08 | 30.910000 | 31.540001 | 30.830000 | 31.510000 | 6620900 | 0.0 | 0.0 |
| 2022-09-09 | 31.950001 | 31.969999 | 31.730000 | 31.889999 | 3556800 | 0.0 | 0.0 |
Define XSII calculation function
-
def XSII(CLOSE, HIGH, LOW, N=102, M=7):
AA = MA((2CLOSE + HIGH + LOW)/4, 5)
TD1 = AAN/100; TD2 = AA(200-N) / 100 CC = ABS((2CLOSE + HIGH + LOW)/4 - MA(CLOSE,20))/MA(CLOSE,20) DD = DMA(CLOSE,CC); TD3=(1+M/100)DD; TD4=(1-M/100)DD return TD1, TD2, TD3, TD4def DMA(S, A):
if isinstance(A,(int,float)): return pd.Series(S).ewm(alpha=A,adjust=False).mean().values
A=np.array(A); A[np.isnan(A)]=1.0; Y= np.zeros(len(S)); Y[0]=S[0]
for i in range(1,len(S)): Y[i]=A[i]S[i]+(1-A[i])Y[i-1]
return Y
#https://github.com/mpquant/MyTT/blob/ea4f14857ecc46a3739a75ce2e6974b9057a6102/MyTT.py
def cal_xsii(ohlc: pd.DataFrame,
slow_period: int = 102, fast_period: int = 7) -> pd.DataFrame:
"""
XS II
"""
ohlc = ohlc.copy(deep=True)
ohlc.columns = [c.lower() for c in ohlc.columns]
p = (2*ohlc["close"] + ohlc["high"] + ohlc["low"])/4
aa_ = p.rolling(5).mean()
td1 = aa_*slow_period/100
td2 = aa_*(200-slow_period)/100
p1_ = ohlc["close"].rolling(20).mean()
cc_ = (p - p1_).abs()/p1_
def _dma(s, a):
if isinstance(a, (int, float)):
return pd.Series(s).ewm(alpha=a,adjust=False).mean().values
a=np.array(a)
a[np.isnan(a)]=1.0
y= np.zeros(len(s))
y[0]=s[0]
for i in range(1,len(s)):
y[i]=a[i]*s[i]+(1-a[i])*y[i-1]
return y
dd_ = _dma(ohlc["close"], cc_)
td3 = (1+fast_period/100)*dd_
td4 = (1-fast_period/100)*dd_
return pd.DataFrame(data={'XSII1': td1,
'XSII2': td2,
'XSII3': td3,
'XSII4':td4},
index=ohlc.index)
Calculate CCI
df = dfs[ticker][['Open', 'High', 'Low', 'Close', 'Volume']]
df = df.round(2)
cal_xsii
<function __main__.cal_xsii(ohlc: pandas.core.frame.DataFrame, slow_period: int = 102, fast_period: int = 7) -> pandas.core.frame.DataFrame>
df_ta = cal_xsii(df, slow_period = 102, fast_period = 7)
df = df.merge(df_ta, left_index = True, right_index = True, how='inner' )
del df_ta
gc.collect()
122
display(df.head(5))
display(df.tail(5))
| Open | High | Low | Close | Volume | XSII1 | XSII2 | XSII3 | XSII4 | |
|---|---|---|---|---|---|---|---|---|---|
| Date | |||||||||
| 1999-12-31 | 19.60 | 19.67 | 19.52 | 19.56 | 139400 | NaN | NaN | 20.9292 | 18.1908 |
| 2000-01-03 | 19.58 | 19.71 | 19.25 | 19.45 | 556100 | NaN | NaN | 20.8115 | 18.0885 |
| 2000-01-04 | 19.45 | 19.45 | 18.90 | 18.95 | 367200 | NaN | NaN | 20.2765 | 17.6235 |
| 2000-01-05 | 19.21 | 19.58 | 19.08 | 19.58 | 481700 | NaN | NaN | 20.9506 | 18.2094 |
| 2000-01-06 | 19.38 | 19.43 | 18.90 | 19.30 | 853800 | 19.74567 | 18.97133 | 20.6510 | 17.9490 |
| Open | High | Low | Close | Volume | XSII1 | XSII2 | XSII3 | XSII4 | |
|---|---|---|---|---|---|---|---|---|---|
| Date | |||||||||
| 2022-09-02 | 31.60 | 31.97 | 31.47 | 31.85 | 8152600 | 33.09798 | 31.80002 | 36.994370 | 32.153985 |
| 2022-09-06 | 31.65 | 31.76 | 31.37 | 31.47 | 5613900 | 32.77362 | 31.48838 | 36.741790 | 31.934453 |
| 2022-09-07 | 31.21 | 31.59 | 31.16 | 31.49 | 4822000 | 32.44722 | 31.17478 | 36.536150 | 31.755719 |
| 2022-09-08 | 30.91 | 31.54 | 30.83 | 31.51 | 6620900 | 32.19681 | 30.93419 | 36.363699 | 31.605832 |
| 2022-09-09 | 31.95 | 31.97 | 31.73 | 31.89 | 3556800 | 32.22231 | 30.95869 | 36.272807 | 31.526832 |
#https://github.com/matplotlib/mplfinance
#this package help visualize financial data
import mplfinance as mpf
import matplotlib.colors as mcolors
all_colors = list(mcolors.CSS4_COLORS.keys())#"CSS Colors"
# all_colors = list(mcolors.TABLEAU_COLORS.keys()) # "Tableau Palette",
# all_colors = list(mcolors.BASE_COLORS.keys()) #"Base Colors",
#https://github.com/matplotlib/mplfinance/issues/181#issuecomment-667252575
#list of colors: https://matplotlib.org/stable/gallery/color/named_colors.html
#https://github.com/matplotlib/mplfinance/blob/master/examples/styles.ipynb
def make_3panels2(main_data, add_data, chart_type='candle', names=None, figratio=(14,9)):
"""
main chart type: default is candle. alternatives: ohlc, line
example:
start = 200
names = {'main_title': 'MAMA: MESA Adaptive Moving Average',
'sub_tile': 'S&P 500 (^GSPC)', 'y_tiles': ['price', 'Volume [$10^{6}$]']}
make_candle(df.iloc[-start:, :5], df.iloc[-start:][['MAMA', 'FAMA']], names = names)
"""
style = mpf.make_mpf_style(base_mpf_style='yahoo', #charles
base_mpl_style = 'seaborn-whitegrid',
# marketcolors=mpf.make_marketcolors(up="r", down="#0000CC",inherit=True),
gridcolor="whitesmoke",
gridstyle="--", #or None, or - for solid
gridaxis="both",
edgecolor = 'whitesmoke',
facecolor = 'white', #background color within the graph edge
figcolor = 'white', #background color outside of the graph edge
y_on_right = False,
rc = {'legend.fontsize': 'small',#or number
#'figure.figsize': (14, 9),
'axes.labelsize': 'small',
'axes.titlesize':'small',
'xtick.labelsize':'small',#'x-small', 'small','medium','large'
'ytick.labelsize':'small'
},
)
if (chart_type is None) or (chart_type not in ['ohlc', 'line', 'candle', 'hollow_and_filled']):
chart_type = 'candle'
len_dict = {'candle':2, 'ohlc':3, 'line':1, 'hollow_and_filled':2}
kwargs = dict(type=chart_type, figratio=figratio, volume=True, volume_panel=1,
panel_ratios=(4,2), tight_layout=True, style=style, returnfig=True)
if names is None:
names = {'main_title': '', 'sub_tile': ''}
added_plots = {
'XSII1': mpf.make_addplot(add_data['XSII1'], panel=0, color='dodgerblue', width=1, secondary_y=False),
'XSII2': mpf.make_addplot(add_data['XSII2'], panel=0, color='orange', width=1, secondary_y=False),
'XSII3': mpf.make_addplot(add_data['XSII3'], panel=0, color='green', width=1, secondary_y=False),
'XSII4': mpf.make_addplot(add_data['XSII4'], panel=0, color='red', width=1, secondary_y=False),
}
fig, axes = mpf.plot(main_data, **kwargs,
addplot=list(added_plots.values()),
)
# add a new suptitle
fig.suptitle(names['main_title'], y=1.05, fontsize=12, x=0.1295)
axes[0].legend([None]*6)
handles = axes[0].get_legend().legendHandles
axes[0].legend(handles=handles[2:],labels=list(added_plots.keys()))
axes[0].set_title(names['sub_tile'], fontsize=10, style='italic', loc='left')
# axes[0].set_ylabel(names['y_tiles'][0])
# axes[2].set_ylabel(names['y_tiles'][1])
return fig, axes
start = -300
end = df.shape[0]
names = {'main_title': f'{ticker}',
'sub_tile': 'XSII'}
aa_, bb_ = make_3panels2(df.iloc[start:end][['Open', 'High', 'Low', 'Close', 'Volume']],
df.iloc[start:end][['XSII1', 'XSII2', 'XSII3', 'XSII4']],
chart_type='hollow_and_filled',names = names)
