Value Chart
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', 'PFE', 'DAL']
#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-05 18:44:16.687789 ^GSPC (5706, 7) 1999-12-31 00:00:00 2022-09-02 00:00:00
2022-09-05 18:44:17.075204 GSK (5706, 7) 1999-12-31 00:00:00 2022-09-02 00:00:00
2022-09-05 18:44:17.528449 NVO (5706, 7) 1999-12-31 00:00:00 2022-09-02 00:00:00
2022-09-05 18:44:17.934598 PFE (5706, 7) 1999-12-31 00:00:00 2022-09-02 00:00:00
2022-09-05 18:44:18.322396 DAL (3863, 7) 2007-05-03 00:00:00 2022-09-02 00:00:00
ticker = 'DAL'
dfs[ticker].tail(5)
| Open | High | Low | Close | Volume | Dividends | Stock Splits | |
|---|---|---|---|---|---|---|---|
| Date | |||||||
| 2022-08-29 | 32.200001 | 32.349998 | 31.850000 | 32.029999 | 8758400 | 0.0 | 0 |
| 2022-08-30 | 32.250000 | 32.450001 | 31.469999 | 31.719999 | 7506400 | 0.0 | 0 |
| 2022-08-31 | 31.969999 | 32.020000 | 31.059999 | 31.070000 | 7450000 | 0.0 | 0 |
| 2022-09-01 | 30.650000 | 31.139999 | 29.940001 | 31.090000 | 8572700 | 0.0 | 0 |
| 2022-09-02 | 31.440001 | 31.830000 | 30.700001 | 30.940001 | 8626500 | 0.0 | 0 |
Define Value Chart calculation function
def cal_vc(ohlc: pd.DataFrame, period: int = 5) -> pd.DataFrame:
"""
Value chart
Implementation based on a book by Mark Helweg & David Stendahl: Dynamic Trading Indicators: Winning with Value Charts and Price Action Profile
:period: Specifies the number of Periods used for VC calculation
"""
ohlc = ohlc.copy(deep=True)
ohlc.columns = [c.lower() for c in ohlc.columns]
float_axis = ((ohlc['high'] + ohlc['low']) / 2).rolling(window=period).mean()
vol_unit = (ohlc['high'] - ohlc['low']).rolling(window=period).mean() * 0.2
value_chart_high = pd.Series((ohlc['high'] - float_axis) / vol_unit, name="Value Chart High")
value_chart_low = pd.Series((ohlc['low'] - float_axis) / vol_unit, name="Value Chart Low")
value_chart_close = pd.Series((ohlc['close'] - float_axis) / vol_unit, name="Value Chart Close")
value_chart_open = pd.Series((ohlc['open'] - float_axis) / vol_unit, name="Value Chart Open")
return pd.concat([value_chart_high, value_chart_low, value_chart_close, value_chart_open], axis=1)
Calculate Value Chart
df = dfs[ticker][['Open', 'High', 'Low', 'Close', 'Volume']]
df = df.round(2)
cal_vc
<function __main__.cal_vc(ohlc: pandas.core.frame.DataFrame, period: int = 5) -> pandas.core.frame.DataFrame>
df_ta = cal_vc(df, period=14)
df = df.merge(df_ta, left_index = True, right_index = True, how='inner' )
del df_ta
gc.collect()
84
display(df.head(5))
display(df.tail(5))
| Open | High | Low | Close | Volume | Value Chart High | Value Chart Low | Value Chart Close | Value Chart Open | |
|---|---|---|---|---|---|---|---|---|---|
| Date | |||||||||
| 2007-05-03 | 19.32 | 19.50 | 18.25 | 18.40 | 8052800 | NaN | NaN | NaN | NaN |
| 2007-05-04 | 18.88 | 18.96 | 18.39 | 18.64 | 5437300 | NaN | NaN | NaN | NaN |
| 2007-05-07 | 18.83 | 18.91 | 17.94 | 18.08 | 2646300 | NaN | NaN | NaN | NaN |
| 2007-05-08 | 17.76 | 17.76 | 17.14 | 17.44 | 4166100 | NaN | NaN | NaN | NaN |
| 2007-05-09 | 17.54 | 17.94 | 17.44 | 17.58 | 7541100 | NaN | NaN | NaN | NaN |
| Open | High | Low | Close | Volume | Value Chart High | Value Chart Low | Value Chart Close | Value Chart Open | |
|---|---|---|---|---|---|---|---|---|---|
| Date | |||||||||
| 2022-08-29 | 32.20 | 32.35 | 31.85 | 32.03 | 8758400 | -8.612076 | -11.652911 | -10.558210 | -9.524327 |
| 2022-08-30 | 32.25 | 32.45 | 31.47 | 31.72 | 7506400 | -6.824895 | -12.613924 | -11.137131 | -8.006329 |
| 2022-08-31 | 31.97 | 32.02 | 31.06 | 31.07 | 7450000 | -8.178180 | -13.839511 | -13.780539 | -8.473041 |
| 2022-09-01 | 30.65 | 31.14 | 29.94 | 31.09 | 8572700 | -11.129482 | -17.822709 | -11.408367 | -13.862550 |
| 2022-09-02 | 31.44 | 31.83 | 30.70 | 30.94 | 8626500 | -5.741325 | -11.979495 | -10.654574 | -7.894322 |
df[['Value Chart High','Value Chart Low', 'Value Chart Close', 'Value Chart Open']].hist(bins=50, figsize=(10, 4))
array([[<AxesSubplot:title={'center':'Value Chart High'}>,
<AxesSubplot:title={'center':'Value Chart Low'}>],
[<AxesSubplot:title={'center':'Value Chart Close'}>,
<AxesSubplot:title={'center':'Value Chart Open'}>]], dtype=object)

#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 = ['dodgerblue', 'firebrick','limegreen','skyblue','lightgreen', 'navy','yellow','plum', 'yellowgreen']
# 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, mid_panel, chart_type='candle', names=None,
figratio=(14,9), fill_weights = (0, 0)):
"""
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=2,
panel_ratios=(4,2,1), tight_layout=True, style=style, returnfig=True)
if names is None:
names = {'main_title': '', 'sub_tile': ''}
added_plots = { }
fb_bbands2_ = dict(y1=fill_weights[0]*np.ones(mid_panel.shape[0]),
y2=fill_weights[1]*np.ones(mid_panel.shape[0]),color="lightskyblue",alpha=0.1,interpolate=True)
fb_bbands2_['panel'] = 1
fb_bbands= [fb_bbands2_]
i = 0
for name_, data_ in mid_panel.iteritems():
added_plots[name_] = mpf.make_addplot(data_, panel=1, width=1, color=all_colors[i], secondary_y=False)
i = i + 1
fig, axes = mpf.plot(main_data, **kwargs,
addplot=list(added_plots.values()),
fill_between=fb_bbands)
# add a new suptitle
fig.suptitle(names['main_title'], y=1.05, fontsize=12, x=0.1285)
axes[0].set_title(names['sub_tile'], fontsize=10, style='italic', loc='left')
# axes[2].set_ylabel('WAVEPM10')
# axes[0].set_ylabel(names['y_tiles'][0])
# axes[2].set_ylabel(names['y_tiles'][1])
return fig, axes
start = -50
end = df.shape[0]
names = {'main_title': f'{ticker}' ,
'sub_tile': 'Value Charts'}
aa_, bb_ = make_3panels2(df.iloc[start:end][['Open', 'High', 'Low', 'Close', 'Volume']],
df.iloc[start:end][['Value Chart High',
'Value Chart Low', 'Value Chart Close', 'Value Chart Open']],
chart_type='hollow_and_filled',names = names,
fill_weights = (-2, 2))
