Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python/Pandas calculate Ichimoku chart components

Tags:

python

pandas

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 code:

high_prices = data['High']
close_prices = data['Close']
low_prices = data['Low']
dates = data['Date']  # contains datetime objects

I need to calculate the following series (Ichimoku calls it Tenkan-Sen line):

(9-period high + 9-period low) / 2

  • 9-period high = the highest High value of last 9 days,
  • 9-period low = the lowest Low value of last 9 days, so both should begin on 9th day.

enter image description here

I've found a solution in R language here, but it's difficult for me to translate it to Python/Pandas code.

Ichimoku chart contains of more components, but when I will know how to count Tenkan-Sen line in Pandas, I will be able to count all of them (I will share the code).

like image 869
chilliq Avatar asked Feb 12 '15 12:02

chilliq


5 Answers

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
like image 144
chilliq Avatar answered Oct 05 '22 02:10

chilliq


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:

enter image description here

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:

enter image description here

like image 24
EdChum Avatar answered Oct 05 '22 03:10

EdChum


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)

Ichimoku Cloud

like image 32
Naveen Avatar answered Oct 05 '22 02:10

Naveen


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)
like image 44
Brijesh Avatar answered Oct 05 '22 02:10

Brijesh


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:

  1. tenkan-sen: (9 period max high + 9 period min low)/2 Pick a date. Look the for maximum high price over the previous nine periods. Look for the minimum low price over the same nine periods. Add the two prices together and divide by two. Plot the result on the date's Y-axis.
  2. kiju-sen: (26 period max high + 26 period min low)/2 Use the same date as for the tenkan-sen. Look for the maximum high price over the previous twenty-six periods. Look for the minimum low price over the same twenty-six periods. Add the two prices and divide by two. Plot the result on the date's Y-axis.
  3. chikou span: Plot on the Y-axis the date's closing price twenty-six periods to the left of the chosen date.
  4. senkou span A: (tenkan-sen + kiju-sen)/2 shifted twenty-six periods to right. Start at the extreme left most date of the plot. Add the values of the tenkan-sen and kiju-sen. Divide the sum by 2. Plot the resulting value on the the date twenty-six periods to the right. Continue this until you get to today's date.
  5. senkou span B: (52 period maximum high price + 52 period minimum low price)/2 shifted 26 periods to the right. Again start at the extreme left most date of the plot. Find the maximum high price of the previous 52 periods. Find the minimum low price of the same 52 periods. Divide the sum by 2. Plot the resulting value on the the date twenty-six periods to the right. Continue this until you get to today's date.

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!

like image 21
TonyK Avatar answered Oct 05 '22 03:10

TonyK