Last active
January 28, 2021 16:46
-
-
Save ghost355/83cfc0791ae3f4b41611b6d5c98e1f39 to your computer and use it in GitHub Desktop.
full history stock chart like IBD in multipage pdf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
from tqdm import tqdm | |
from bs4 import BeautifulSoup | |
import requests | |
import pandas_ta as ta | |
import yfinance as yf | |
import pandas as pd | |
import numpy as np | |
import mplfinance as mpf | |
import matplotlib.pyplot as plt | |
import matplotlib.ticker as mticker | |
import matplotlib.dates as mdates | |
from matplotlib.backends.backend_pdf import PdfPages | |
# !!! you need set stock symbol, if you want set other index | |
# how many bars you want on each page, and how many bars overlaping you want | |
STOCK = 'TSLA' | |
INDEX = '^GSPC' # S&P500 | |
bar_in_page = 220 | |
shift = 35 | |
# get stock data | |
def get_ohlc (stock, period = 'max', interval = '1d'): | |
df_ohlc = yf.Ticker(stock.upper()).history(actions = False, period = period, interval = interval) | |
return df_ohlc | |
df = get_ohlc(STOCK) # main DataFrame for join everything | |
df_idx = get_ohlc(INDEX) | |
df=df.join(df_idx['Close'], rsuffix='_idx') | |
# add TA columns | |
df.ta.sma(length=50,append=True) | |
df.ta.sma(length=200,append=True) | |
df.ta.sma(length=150,append=True) | |
df.ta.ema(length=20,append=True) | |
df['VOL_50'] = df.ta.sma(close=df['volume'], length=50) | |
# add RS-line column | |
stock_close = df['close'] | |
ind_close = df['Close_idx'] | |
df['rs_line'] = stock_close/ind_close*100 * stock_close.shift(60)/(stock_close/ind_close *100).shift(60)*0.68 # 0.68 for placing like in IBD chart | |
# add space to the right side of chart | |
dfpad = df.tail(2).copy() | |
dfpad.loc[:,:] = float('nan') | |
newdf = df.append(dfpad) | |
df = newdf | |
# todo - get financial info like EPS and Sales | |
def get_macro_info(stock="AAPL", period='q'): | |
pass | |
# make chunks for export in multiple pages pdf, I guess there is the way to do the same better | |
iter_list = list(range(len(df))) | |
#bar_in_page = 220 | |
#shift = 35 | |
chunks = [iter_list[i:i + bar_in_page] for i in range(0, len(iter_list), bar_in_page-shift)] | |
pages = [(x[0],x[-1]+1) for x in chunks] # pages[n][0] - slice start, pages[n][1] - slice end | |
# styling chart | |
mc = mpf.make_marketcolors(up='#2A3FE5', down='#DB39AD', inherit=True) | |
base_style = { 'axes.titlesize': 5, | |
'axes.labelsize': 5, | |
'lines.linewidth': 3, | |
'lines.markersize': 4, | |
'ytick.left': False, | |
'ytick.right': True, | |
'ytick.labelleft': False, | |
'ytick.labelright': True, | |
'xtick.labelsize': 6, | |
'ytick.labelsize': 6, | |
'axes.linewidth': 0.8, | |
'grid.alpha': 0.2} | |
ibd = mpf.make_mpf_style(marketcolors=mc, mavcolors=['green', 'red', 'black', 'blue'], y_on_right=True, rc=base_style) | |
def get_pdf(pages): | |
for (start,end) in pages: | |
### !!! temporary replace to chunks loop | |
df_slice = df[start:end] | |
print(start,end) | |
# ======== starting plot ======= | |
# making grid of axis | |
egrid = (21,29) | |
fig = mpf.figure(style=ibd, figsize=(11, 8)) | |
ax1 = plt.subplot2grid(egrid,(2,0),colspan=29,rowspan=15) | |
ax3 = plt.subplot2grid(egrid,(0,0),colspan=29,rowspan=2,sharex=ax1) | |
ax2 = plt.subplot2grid(egrid,(17,0),colspan=29,rowspan=4,sharex=ax1) | |
# Set locator intervals | |
lim_bottom =min(df_slice['rs_line'].min(), df_slice['SMA_200'].min()) | |
lim_top = max(df_slice['rs_line'].max(), df_slice['SMA_200'].max(),df_slice['close'].max()) | |
# Включаем видимость делений: | |
ax1.minorticks_on() | |
ax1.grid(which='major',color='k') | |
ax1.grid(which='minor',color='gray') | |
ax2.grid(which='major',color='gray') | |
ax2.tick_params(axis='x', which='major', pad = 8) | |
ax1.tick_params(axis='x', which='both',labelbottom= False, labeltop=False ) | |
ax3.tick_params(axis='x', which='both',labelbottom= False, labeltop=False, bottom=False, top=True, direction='in') | |
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%m')) | |
ax1.xaxis.set_major_locator(mticker.IndexLocator(base=30, offset=0)) | |
ax1.xaxis.set_minor_formatter(mdates.DateFormatter('%d')) | |
ax1.xaxis.set_minor_locator(mticker.IndexLocator(base=5, offset=0)) | |
maxprice = df_slice.high.max() | |
if maxprice > 100: | |
locator_size = 100 | |
elif maxprice < 10: | |
locator_size = 1 | |
else: | |
locator_size = 10 | |
ax1.yaxis.set_major_locator(mticker.MultipleLocator(locator_size)) | |
ax1.yaxis.set_minor_locator(mticker.MultipleLocator(locator_size/4)) | |
ax2.yaxis.set_major_locator(mticker.MultipleLocator(df_slice['volume'].max()/5)) | |
# additional lines | |
sp500 = mpf.make_addplot( df_slice['Close_idx'], color='black', width=0.9, panel=0, title=f'{STOCK.upper()} {df_slice.index[0]} - {df_slice.index[-1]}', ax=ax3) | |
vol50 = mpf.make_addplot( | |
df_slice['VOL_50'], panel=2, color='red', width=0.6, ax=ax2) | |
rs_line = mpf.make_addplot( | |
df_slice['rs_line'], ax=ax1, color='blue', width=1.2, alpha=0.35, panel=1) | |
sma200 = mpf.make_addplot( | |
df_slice['SMA_200'], ax=ax1,color='black', width=0.8, panel=1) | |
sma50 = mpf.make_addplot( | |
df_slice['SMA_50'], ax=ax1,color='red', width=0.6, panel=1) | |
sma150 = mpf.make_addplot( | |
df_slice['SMA_150'], ax=ax1,color='gray', width=0.2, alpha=0.8, panel=1) | |
ema20 = mpf.make_addplot( | |
df_slice['EMA_20'], ax=ax1,color='green', width=0.3, panel=1) | |
mpf.plot(df_slice, ax=ax1, volume=ax2,addplot=[sp500, rs_line, sma200, sma150, sma50, ema20, vol50], datetime_format="%b'20",tight_layout=True, xrotation=0, | |
scale_width_adjustment=dict(volume=0.2),ylim=(lim_bottom*0.1,lim_top*1.1)) | |
# scale_width_adjustment=dict(volume=0.2), addplot=[sp500, rs_line, sma200, sma150, sma50, ema20, vol50], | |
# datetime_format="%b'20",tight_layout=True, xrotation=0, ylim=(lim_bottom*0.1,lim_top*1.1),update_width_config=dict(ohlc_linewidth=0.9,ohlc_ticksize=0.4) | |
# remove gaps among axis panels | |
plt.tight_layout(h_pad= -0.8) | |
fig.savefig(f'figure{end}.pdf') | |
get_pdf(pages) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment