I have Pandas DataFrame object with Date, Open, Close, Low and High daily stock data. I want to calculate components of Ichimoku chart. I can get my data using the following cod
high_9 = pd.rolling_max(df.high, window= 9)
low_9 = pd.rolling_min(df.low, window= 9)
df['conversion_line'] = (high_9 + low_9) /2
high_26 = pd.rolling_max(df.high, window= 26)
low_26 = pd.rolling_min(df.low, window= 26)
df['base_line'] = (high_26 + low_26) / 2
df['leading_span_A'] = ((df.conversion_line + df.base_line) / 2).shift(30)
high_52 = pd.rolling_max(df.high, window= 52)
low_52 = pd.rolling_min(df.high, window= 52)
df['leading_span_B'] = ((high_52 + low_52) / 2).shift(30)
df['lagging_span'] = df.close.shift(-30)
fig,ax = plt.subplots(1,1,sharex=True,figsize = (20,9)) #share x axis and set a figure size
ax.plot(df.index, df.close,linewidth=4) # plot Close with index on x-axis with a line thickness of 4
# use the fill_between call of ax object to specify where to fill the chosen color
# pay attention to the conditions specified in the fill_between call
ax.fill_between(df.index,leading_span_A,df.leading_span_B,where = df.leading_span_A >= df.leading_span_B, color = 'lightgreen')
ax.fill_between(df.index,df.leading_span_A,df.leading_span_B,where = leading_span_A < df.leading_span_B, color = 'lightcoral')
I'm no financial expert or plotting expert but the following shows sample financial data and how to use rolling_max and rolling_min:
In [60]:
import pandas.io.data as web
import datetime
start = datetime.datetime(2010, 1, 1)
end = datetime.datetime(2013, 1, 27)
data=web.DataReader("F", 'yahoo', start, end)
high_prices = data['High']
close_prices = data['Close']
low_prices = data['Low']
dates = data.index
nine_period_high = df['High'].rolling(window=9).max()
nine_period_low = df['Low'].rolling(window=9).min()
ichimoku = (nine_period_high + nine_period_low) /2
ichimoku
Out[60]:
Date
2010-01-04 NaN
2010-01-05 NaN
2010-01-06 NaN
2010-01-07 NaN
2010-01-08 NaN
2010-01-11 NaN
2010-01-12 NaN
2010-01-13 NaN
2010-01-14 11.095
2010-01-15 11.270
2010-01-19 11.635
2010-01-20 11.730
2010-01-21 11.575
2010-01-22 11.275
2010-01-25 11.220
...
2013-01-04 12.585
2013-01-07 12.685
2013-01-08 13.005
2013-01-09 13.030
2013-01-10 13.230
2013-01-11 13.415
2013-01-14 13.540
2013-01-15 13.675
2013-01-16 13.750
2013-01-17 13.750
2013-01-18 13.750
2013-01-22 13.845
2013-01-23 13.990
2013-01-24 14.045
2013-01-25 13.970
Length: 771
Calling data[['High', 'Low', 'Close', 'ichimoku']].plot()
results in the following plot:
update
After @PedroLobito's comments pointing out the incomplete/incorrect formula I took @chilliq's answer and modified it for pandas versions 0.16.1 and above:
import pandas as pd
from pandas_datareader import data, wb
import datetime
start = datetime.datetime(2010, 1, 1)
end = datetime.datetime(2013, 1, 27)
d=data.DataReader("F", 'yahoo', start, end)
high_prices = d['High']
close_prices = d['Close']
low_prices = d['Low']
dates = d.index
nine_period_high = df['High'].rolling(window=9).max()
nine_period_low = df['Low'].rolling(window=9).min()
d['tenkan_sen'] = (nine_period_high + nine_period_low) /2
# Kijun-sen (Base Line): (26-period high + 26-period low)/2))
period26_high = high_prices.rolling(window=26).max()
period26_low = low_prices.rolling(window=26).min()
d['kijun_sen'] = (period26_high + period26_low) / 2
# Senkou Span A (Leading Span A): (Conversion Line + Base Line)/2))
d['senkou_span_a'] = ((d['tenkan_sen'] + d['kijun_sen']) / 2).shift(26)
# Senkou Span B (Leading Span B): (52-period high + 52-period low)/2))
period52_high = high_prices.rolling(window=52).max()
period52_low = low_prices.rolling(window=52).min()
d['senkou_span_b'] = ((period52_high + period52_low) / 2).shift(26)
# The most current closing price plotted 22 time periods behind (optional)
d['chikou_span'] = close_prices.shift(-22) # 22 according to investopedia
d.plot()
results in the following plot, unclear because as stated already I'm not a financial expert:
I wish the people who write the Ichimoku books were more explicit in their instructions in the calculations. Looking at the code above I'm assuming the following:
Plotting the first three from a chosen date to today's date results in three lines. The last two give a plot area ("cloud") along with two possible support/resistance lines defining the upper/lower "cloud" bounds. All this assumes the 'periods' are dates (they might be 15 minute periods for day traders as an example of other periods). Also, some books have senkou plan B shift 26 periods and some shift it 22 periods. I understand the original book by Goichi Hosoda had it twenty-six periods, so I used that value.
Thank you for writing the program. While I thought I understood what the authors of the books on this subject meant, I was never sure until I saw the code. Obviously the authors were not programmers or mathematicians doing proofs. I guess I'm just too linear!
Thanks to the previous answer, there is the code:
# Tenkan-sen (Conversion Line): (9-period high + 9-period low)/2))
period9_high = pd.rolling_max(high_prices, window=9)
period9_low = pd.rolling_min(low_prices, window=9)
tenkan_sen = (period9_high + period9_low) / 2
# Kijun-sen (Base Line): (26-period high + 26-period low)/2))
period26_high = pd.rolling_max(high_prices, window=26)
period26_low = pd.rolling_min(low_prices, window=26)
kijun_sen = (period26_high + period26_low) / 2
# Senkou Span A (Leading Span A): (Conversion Line + Base Line)/2))
senkou_span_a = ((tenkan_sen + kijun_sen) / 2).shift(26)
# Senkou Span B (Leading Span B): (52-period high + 52-period low)/2))
period52_high = pd.rolling_max(high_prices, window=52)
period52_low = pd.rolling_min(low_prices, window=52)
senkou_span_b = ((period52_high + period52_low) / 2).shift(26)
# The most current closing price plotted 22 time periods behind (optional)
chikou_span = close_prices.shift(-22) # 22 according to investopedia
EdChum's answer was very close in calculating the components for the Ichimoku Cloud.
The methodologies are correct but it missed to accommodate for the future dates for both leading_spans . When we are shifting the leading spans by 26 , pandas just shifts till the last date or last index and the extra(or future) 26 values are ignored.
Here's an implementation that accommodates for the future dates or future cloud formation
from datetime import timedelta
high_9 = df['High'].rolling(window= 9).max()
low_9 = df['Low'].rolling(window= 9).min()
df['tenkan_sen'] = (high_9 + low_9) /2
high_26 = df['High'].rolling(window= 26).max()
low_26 = df['Low'].rolling(window= 26).min()
df['kijun_sen'] = (high_26 + low_26) /2
# this is to extend the 'df' in future for 26 days
# the 'df' here is numerical indexed df
last_index = df.iloc[-1:].index[0]
last_date = df['Date'].iloc[-1].date()
for i in range(26):
df.loc[last_index+1 +i, 'Date'] = last_date + timedelta(days=i)
df['senkou_span_a'] = ((df['tenkan_sen'] + df['kijun_sen']) / 2).shift(26)
high_52 = df['High'].rolling(window= 52).max()
low_52 = df['Low'].rolling(window= 52).min()
df['senkou_span_b'] = ((high_52 + low_52) /2).shift(26)
# most charting softwares dont plot this line
df['chikou_span'] = df['Close'].shift(-22) #sometimes -26
tmp = df[['Close','senkou_span_a','senkou_span_b','kijun_sen','tenkan_sen']].tail(300)
a1 = tmp.plot(figsize=(15,10))
a1.fill_between(tmp.index, tmp.senkou_span_a, tmp.senkou_span_b)
import mplfinance as mpf
import pandas as pd
#Import the data into a "df", with headers, with the name of the stock like "stk = 'AAPL'"
#MPLFinance does not fill-in-between,hence there is no cloud.
#Tenkan Sen
tenkan_max = df['High'].rolling(window = 9, min_periods = 0).max()
tenkan_min = df['Low'].rolling(window = 9, min_periods = 0).min()
df['tenkan_avg'] = (tenkan_max + tenkan_min) / 2
#Kijun Sen
kijun_max = df['High'].rolling(window = 26, min_periods = 0).max()
kijun_min = df['Low'].rolling(window = 26, min_periods = 0).min()
df['kijun_avg'] = (kijun_max + kijun_min) / 2
#Senkou Span A
#(Kijun + Tenkan) / 2 Shifted ahead by 26 periods
df['senkou_a'] = ((df['kijun_avg'] + df['tenkan_avg']) / 2).shift(26)
#Senkou Span B
#52 period High + Low / 2
senkou_b_max = df['High'].rolling(window = 52, min_periods = 0).max()
senkou_b_min = df['Low'].rolling(window = 52, min_periods = 0).min()
df['senkou_b'] = ((senkou_b_max + senkou_b_min) / 2).shift(52)
#Chikou Span
#Current close shifted -26
df['chikou'] = (df['Close']).shift(-26)
#Plotting Ichimoku
#m_plots = ['kijun_avg', 'tenkan_avg',df[df.columns[5:]][-250:] ]
add_plots= [
mpf.make_addplot(df['kijun_avg'][-250:]),
mpf.make_addplot(df['tenkan_avg'][-250:]),
mpf.make_addplot(df['chikou'][-250:]),
mpf.make_addplot(df['senkou_a'][-250:]),
mpf.make_addplot(df['senkou_b'][-250:])
]
mpf.plot(df[-250:], type = 'candle', mav= 200, volume = True, ylabel = "Price", ylabel_lower = 'Volume', style = 'nightclouds', figratio=(15,10), figscale = 1.5, addplot = add_plots, title = '%s' %stk)