The following example shows you how to draw multiple subplots with different widths and heights. It also tells you the answers to some other questions.
- How to do technical analysis of a stock?
- How to draw double y-axis plot?
- How to set height of a subplot?
import numpy as np
import talib
import emoji
import pandas as pd
from datetime import datetime,date
from ta import add_all_ta_features
from ta.utils import dropna
import plotly.graph_objects as go
import chart_studio.plotly as py
from plotly.subplots import make_subplots
candleRank=pd.read_csv('CandleStick_rankings.csv')
candle_names = talib.get_function_groups()['Pattern Recognition']
candleRank=candleRank.set_index('Unnamed: 0')
#------------------------------------
Year=2020
Month=5
fnlist='nasdq100List.txt'
fns=pd.read_csv(fnlist)
path='nasdq100/'
#-------------------------------------
for fn0 in fns.symbles[:1]:
stockname=fn0.replace('.csv','')
fn=path + stockname + '.csv'
fn=fn.replace(' ','')
figfilename="images/nasdq100/" + stockname + '_Technical_Analysis.png'
figfilename=figfilename.replace(' ','')
df0=pd.read_csv(fn)
#! convert Date to datetime
df0['Date']=df0['Date'].astype('datetime64[ns]')
df0=df0.rename(columns={'Date':'date'})
#! drop nan data
df0 = dropna(df0)
df0 = add_all_ta_features(df0, open="Open", high="High", low="Low", close="Close", volume="Volume")
df=df0.iloc[-62:]
minVolume=df['Volume'].min()
maxVolume=df['Volume'].max()
minClose=df['Close'].min()
maxClose=df['Close'].max()
strdate=df["date"].dt.strftime("%m/%d/%y").iloc[-1]
tradingClosePCT=np.round((df0.Close.iloc[-1]/maxClose)*100,2)
tradingVolumePCT=np.round((df0.Volume.iloc[-1]/maxVolume)*100,2)
str4Volume="Volume is " + str(tradingVolumePCT) +'% of 3-month maximum'
if(df['Volume'].tail(1).values ==minVolume):
str4Volume='Trading volume hits 3-month record low.'
if(df['Volume'].tail(1).values ==maxVolume):
str4Volume='Trading volume hits 3-month record high.'
str4Close='Price is ' + str(tradingClosePCT) +'% of 3-month record high'
if(df.Close.tail(1).values==minClose):
str4Close='Close price dips to the 3-month record low.'
if(df.Close.tail(1).values==maxClose):
str4Close='Close price soars to the 3-month record high.'
ratePCT=np.round((df0.Close.iloc[-1]/df0.Close.iloc[-2]-1)*100,2)
strPriceChange='Price change ' + str(ratePCT) +'%'
if(ratePCT>5):
strPriceChange='Price soars ' + str(ratePCT) +'%'
if(ratePCT<-5):
strPriceChange='Price dips ' + str(ratePCT) +'%'
df1=df0.iloc[-5:]
op=df1['Open']
hi=df1['High']
lo=df1['Low']
cl=df1['Close']
pattern_columns=['Open_2','High_2','Low_2','Close_2','Open_1','High_1','Low_1','Close_1'] \
+ list(df.columns) + ['PatternName','Bull2Bear']
df_pattern=pd.DataFrame(columns=pattern_columns)
for candle in candle_names:
df[candle] = getattr(talib, candle)(op, hi, lo, cl)
df=df[candle_names].tail(1)
#print(df[candle_names])
df_candles=df[candle_names].sum(axis=1)
if(df_candles.values==0):
aboutThePatterns = stockname + " has no pattern!"
else:
for candle in candle_names:
if(df[candle].values==0):
df=df.drop(candle,axis=1)
aboutThePatterns=''
for col in df.columns:
if(df[col].values<0):
bull2bear=col + '_Bear'
else:
bull2bear=col+ '_Bull'
if (bull2bear in list(candleRank.index)):
strRank=str(candleRank.loc[bull2bear,'Rank'])
else:
strRank=''
aboutThePatterns = aboutThePatterns + \
"Pattern(s): " + \
bull2bear + ",Rank=" + strRank
aboutThePatterns=aboutThePatterns.replace(' ',' ').replace('CDL','')
s1='<img src="https://github.com/ziwangdeng/TechnicalAnalysis/blob/master/nasdq/'
s2=stockname + '_Technical_Analysis.png?raw=true"'
s2=s2.replace(' ','').replace('.TO','_TO')
s3=' alt="Technical_Analysis" width="100%" height="1600"><br>'
ss=s1 + s2 + s3
print(ss)
df=df0.iloc[-10:]
#! set subplot heights
fig = make_subplots(
rows=12, cols=1,
specs=[
[{"rowspan":1,"secondary_y": True}],
[{"rowspan":1,"secondary_y": True}],
[{"rowspan":1,"secondary_y": True}],
[{"rowspan":4,"secondary_y": False}],
[None],
[None],
[None],
[{"rowspan":1,"secondary_y": True}],
[{"rowspan":1,"secondary_y": True}],
[{"rowspan":1,"secondary_y": True}],
[{"rowspan":2,"secondary_y": False}],
[None],
])
# ADX
fig.add_trace(go.Scatter(x=df.date,
y=df.trend_adx,
mode='lines',
name="ADX",
line=dict(color='rgb(30,30,30)',
width=2)),row=1,col=1,secondary_y=False)
fig.add_trace(go.Scatter(x=df.date,
y=df.trend_adx_pos,
mode='lines',
name="D+",
line=dict(color='rgb(0,200,0)',
width=1)),row=1,col=1,secondary_y=False)
fig.add_trace(go.Scatter(x=df.date,
y=df.trend_adx_neg,
mode='lines',
name="D-",
line=dict(color='rgb(200,0,0)',
width=1)),row=1,col=1,secondary_y=False)
#TSI
#! double yaxes
fig.add_trace(go.Scatter(x=df.date,
y=df.momentum_tsi,
mode='lines',
name="TSI",
line=dict(color='rgb(0,0,230)',
width=2)),row=1,col=1,secondary_y=True)
x1=df.date.iloc[0]
x2=df.date.iloc[-1]
y1=-20
y2=20
fig.add_trace(go.Scatter(x=[x1,x2],
y=[y1,y1],
mode='lines',
name='overSold',
line=dict(color='rgb(0,200,0)',
width=1,dash='dash')),row=1,col=1,secondary_y=True)
fig.add_trace(go.Scatter(x=[x1,x2],
y=[y2,y2],
mode='lines',
name='overBought',
line=dict(color='rgb(200,0,0)',
width=1,dash='dash')),row=1,col=1,secondary_y=True)
#RSI
fig.add_trace(go.Scatter(x=df.date,
y=df.momentum_rsi,
mode='lines',
name="RSI",
line=dict(color='rgb(30,30,30)',
width=2)),row=2,col=1,secondary_y=False)
x1=df.date.iloc[0]
x2=df.date.iloc[-1]
y1=30
y2=70
fig.add_trace(go.Scatter(x=[x1,x2],
y=[y1,y1],
mode='lines',
name='Over-Sold',
line=dict(color='rgb(0,200,0)',
width=1,dash='dash')),row=2,col=1,secondary_y=False)
fig.add_trace(go.Scatter(x=[x1,x2],
y=[y2,y2],
mode='lines',
name='Over-Bought',
line=dict(color='rgb(200,0,0)',
width=1,dash='dash')),row=2,col=1,secondary_y=False)
# SR
fig.add_trace(go.Scatter(x=df.date,
y=df.momentum_stoch,
mode='lines',
name="SR",
line=dict(color='rgb(0,0,230)',
width=2)),row=2,col=1,secondary_y=True)
fig.add_trace(go.Scatter(x=df.date,
y=df.momentum_stoch_signal,
mode='lines',
name="SR_signal",
line=dict(color='rgb(0,0,230)',
width=1)),row=2,col=1,secondary_y=True)
x1=df.date.iloc[0]
x2=df.date.iloc[-1]
y1=20
y2=80
fig.add_trace(go.Scatter(x=[x1,x2],
y=[y1,y1],
mode='lines',
name='Over-Sold',
line=dict(color='rgb(0,100,0)',
width=1,dash='dot')),row=2,col=1,secondary_y=True)
fig.add_trace(go.Scatter(x=[x1,x2],
y=[y2,y2],
mode='lines',
name='Over-Bought',
line=dict(color='rgb(100,0,0)',
width=1,dash='dot')),row=2,col=1,secondary_y=True)
#MACD
fig.add_trace(go.Scatter(x=df['date'],
y=df.trend_macd,
mode='lines',
line=dict(color='rgb(30,30,30)',width=2), name="MACD"),row=3,col=1,secondary_y=False)
fig.add_trace(go.Scatter(x=df['date'],
y=df.trend_macd_signal,mode='lines',
line=dict(color='rgb(30,30,30)',width=1),
name="MACD Signal"),row=3,col=1,secondary_y=False)
fig.add_trace(go.Bar(x=df['date'],
y=df.trend_macd_diff,
base=0,
marker_color='lightslategrey',
name="MACD Difference"),row=3,col=1,secondary_y=False)
#TRIX
fig.add_trace(go.Scatter(x=df.date,
y=df.trend_trix,
mode='lines',
name="TRIX",
line=dict(color='rgb(0,0,230)',
width=2)),row=3,col=1,secondary_y=True)
x1=df.date.iloc[0]
x2=df.date.iloc[-1]
y1=0
y2=0
fig.add_trace(go.Scatter(x=[x1,x2],
y=[y1,y1],
mode='lines',
name='Zero Line',
line=dict(color='rgb(130,130,130)',
width=1,dash='dash')),row=3,col=1,secondary_y=True)
# bollinger band
fig.add_trace(go.Candlestick(x=df['date'],
open=df['Open'],
high=df['High'],
low=df['Low'],
close=df['Close']
),row=4,col=1)
fig.add_trace(go.Scatter(x=df.date,
y=df.volatility_bbm,
mode='lines',
name="BBM",
line=dict(color='rgb(30,30,30)', width=2, dash='dash')),row=4,col=1)
fig.add_trace(go.Scatter(x=df.date,
y=df.volatility_bbh,
mode='lines', name="BBH",
line=dict(color='rgb(130,130,130)', width=1, dash='dash')),row=4,col=1)
fig.add_trace(go.Scatter(x=df.date,
y=df.volatility_bbl,
mode='lines',
name="BBL",
line=dict(color='rgb(130,130,130)', width=1, dash='dash')),row=4,col=1)
fig.add_trace(go.Scatter(x=df.date,
y=df.trend_sma_fast,
mode='lines',
name="SMA_Fast",
line=dict(color='rgb(0,0,230)', width=1)),row=4,col=1)
fig.add_trace(go.Scatter(x=df.date,
y=df.trend_sma_slow,
mode='lines',
name="SMA_Slow",
line=dict(color='rgb(0,0,230)', width=2)),row=4,col=1)
fig.add_trace(go.Scatter(x=df.date,
y=df.trend_ema_fast,
mode='lines',
name="EMA_Fast",
line=dict(color='rgb(0,230,230)', width=1)),row=4,col=1)
fig.add_trace(go.Scatter(x=df.date,
y=df.trend_ema_slow,
mode='lines',
name="EMA_Slow",
line=dict(color='rgb(0,230,230)', width=2)),row=4,col=1)
fig.add_trace(go.Scatter(x=df.date,
y=df.volatility_dch,
mode='lines',
name="Donchian_H",
line=dict(color='rgb(230,230,0)', width=1)),row=4,col=1)
fig.add_trace(go.Scatter(x=df.date,
y=df.volatility_dcl,
mode='lines',
name="Donchian_L",
line=dict(color='rgb(230,230,0)', width=1)),row=4,col=1)
# Volume
fig.add_trace(go.Bar(x=df.date,
y=df.Volume,
base=0,
name="Volume",
marker_color='rgb(130,130,130)'),row=8,col=1,secondary_y=False)
# Volume OBV
fig.add_trace(go.Scatter(x=df.date,
y=df.volume_obv,
name="Volume_OBV",
line=dict(color='rgb(0, 0, 230)',
width=2)),row=8,col=1,secondary_y=True)
# Chaikin Money Flow (CMF)
basevalue=df.volume_cmf.min
fig.add_trace(go.Bar(x=df.date,
y=df.volume_cmf,
name="Volume_CMF",
marker_color='rgb(130,130,130)'),row=9,col=1,secondary_y=False)
# FI
# basevalue=df.volume_cmf.min
fig.add_trace(go.Scatter(x=df.date,
y=df.volume_fi,
name="Volume_FI",
line=dict(color='rgb(0, 0, 230)',
width=2)),row=9,col=1,secondary_y=True)
# Volume-price Trend (VPT)
fig.add_trace(go.Bar(x=df.date,
y=df.volume_vpt,
base=0,
name="volume_vpt",
marker_color='rgb(130,130,130)'),row=10,col=1,secondary_y=False)
# ADI
fig.add_trace(go.Scatter(x=df.date,
y=df.volume_adi,
name="Volume_ADI",
line=dict(color='rgb(0, 0, 230)',
width=2)),row=10,col=1,secondary_y=True)
fig.add_annotation(
x=1,
y=5,
ax=1,ay=0,
font=dict(color='blue'),
text=emoji.emojize(':thumbs_up:'),row=11,col=1)
fig.add_annotation(
x=41,
y=1,
ax=1,ay=0,
font=dict(color='blue'),
text=emoji.emojize(':thumbs_up:'),row=11,col=1)
fig.add_trace(go.Scatter(
x=[1,1.5,1.5,1.5,1.5,1.5],
y=[4.75,4.00,3.25,2.5,1.75],
name="Summary",
mode='markers+text',
text=['Summary:',aboutThePatterns,strPriceChange,str4Close,str4Volume],
textposition='middle right',
textfont=dict(family='sans serif',
size=14,
color='black')),row=11,col=1)
fig.add_annotation( x=35,
y=1.25,
ax=1,ay=0,font=dict(color='#aaaaaa'),
text="ziwangdeng.com",row=11,col=1)
fig.update_yaxes(title_text="ADX", row=1, col=1,secondary_y=False,
showline=True,linecolor='#888888', mirror=True,
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_yaxes(title_text="TSI", row=1, col=1,secondary_y=True,
showline=True,linecolor='#888888', mirror=True,
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_xaxes(row=1,col=1,
showline=True,linecolor='#888888', mirror=True,
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_yaxes(title_text="RSI", row=2, col=1,secondary_y=False,
showline=True,linecolor='#888888', mirror=True,
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_yaxes(title_text="SR", row=2, col=1,secondary_y=True,
showline=True,linecolor='#888888', mirror=True,
zerolinewidth=1, zerolinecolor='#00ffff',
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_xaxes(row=2,col=1,
showline=True,linecolor='#888888', mirror=True,
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_yaxes(title_text="MACD", row=3, col=1,secondary_y=False,
showline=True,linecolor='#888888', mirror=True,
zerolinewidth=1, zerolinecolor='#00ffff',
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_yaxes(title_text="TRIX", row=3, col=1,secondary_y=True,
showline=True,linecolor='#888888', mirror=True,
zerolinewidth=1, zerolinecolor='#00ffff',
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_xaxes(row=3,col=1,
showline=True,linecolor='#888888', mirror=True,
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_yaxes(title_text="BB,SMA,EMA,DC", row=4, col=1,secondary_y=False,
showline=True,linecolor='#888888', mirror=True,
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_xaxes(row=4,col=1,
showline=True,linecolor='#888888', mirror=True,
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_yaxes(title_text="Volume", row=8, col=1,secondary_y=False,
showline=True,linecolor='#888888', mirror=True,
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_yaxes(title_text="OBV", row=8, col=1,secondary_y=True)
fig.update_xaxes(row=8,col=1,
showline=True,linecolor='#888888', mirror=True,
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_yaxes(title_text="CMF", row=9, col=1,secondary_y=False,
showline=True,linecolor='#888888', mirror=True,
zerolinewidth=1, zerolinecolor='#00ffff',
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_yaxes(title_text="FI", row=9, col=1,secondary_y=True,
showline=True,linecolor='#888888', mirror=True,
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_xaxes(row=9,col=1,
showline=True,linecolor='#888888', mirror=True,
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_yaxes(title_text="VPT", row=10, col=1,secondary_y=False,
showline=True,linecolor='#888888', mirror=True,
zerolinewidth=1, zerolinecolor='#00ffff',
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_yaxes(title_text="ADI", row=10, col=1,secondary_y=True,
showline=True,linecolor='#888888', mirror=True,
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_xaxes(row=10,col=1,
showline=True,linecolor='#888888', mirror=True,
showgrid=True, gridwidth=1, gridcolor='#eeeeee')
fig.update_yaxes(row=11, col=1,showline=True,linecolor='#888888',
mirror=True,showgrid=False,zeroline=False)
fig.update_xaxes(row=11,col=1,showline=True,linecolor='#888888',
mirror=True,showgrid=False,zeroline=False)
fig.update_layout(height=1600,
title_text=stockname + ' ' + strdate + ' ' + str(ratePCT)+'%',
xaxis4 = {"rangeslider": {"visible": False}},
plot_bgcolor='rgb(255,255,255)'
)
fig.update_annotations(dict(showarrow=False),row=11,col=1)
fig.show()
fig.write_image(figfilename)
