投資のためのデータサイエンス

個人の投資活動に役立つデータ分析にまつわる話題を綴ります。

Pythonによるカギ足チャートの描画

(2023/12/11) それまでのコードでは、一部のケースで最後のトレンド反転時点以降の株価が全く表示されないため、データの最新時点の値は必ず描画対象とするようにコードを修正しました。

「カギ足チャート」はローソク足等に比べてユーザは少ないと思われますが、愛用者はある程度はいるらしく、カギ足チャートの見方に関するネット記事は多く見かけます。しかし、カギ足チャートをPythonで描画する方法となるとネット検索してもほとんど見かけません。唯一、海外のStackOverflowの投稿でPythonによるカギ足チャート描画コードの原案のようなものを見つけたので、そのコードをベースに独自に開発することにしました。

まずいつものように必要なライブラリをインポートします。

import matplotlib.pyplot as plt
import pandas as pd
import yfinance as yf
import matplotlib.dates as mdates
from datetime import datetime, timedelta
import numpy as np
from pandas_datareader import data as pdr
import matplotlib.dates as mdates

同じくYahoo! Financeから株価データを取得します。

# Define the stock symbol and timeframe
symbol = '7203.T' # 7203はトヨタ自動車
end_date = datetime.today()
start_date = end_date - timedelta(days=180)  # 6 months before today
yf.pdr_override()
# yahooサイトからデータをダウンロード
stock_data = pdr.get_data_yahoo(symbol, start_date, end_date)
stock_data.head()

次に、カギ足チャートの描画のベースとなるデータフレームを作成する関数を定義します。新しいデータフレームにはトレンドが反転した日付のデータ行のみを残します。描画に必要な「直近の天底」の値は新たにExtremeという名前の列を作ってそこで保持します。

def KagiChart(df,delta):
    # カギ足描画のためのデータフレームの初期化
    kagi_df = pd.DataFrame(columns=['Date', 'Open', 'High', 'Low', 'Close', 'Volume', 'Extreme', 'Direc'])

    # データの出発点における設定
    trend = 0
    kagi = df.iloc[0]['Close']
    kagi_df.loc[0] = [df.iloc[0]['Date'], df.iloc[0]['Open'], df.iloc[0]['High'], df.iloc[0]['Low'],
                      df.iloc[0]['Close'], df.iloc[0]['Volume'], df.iloc[0]['Close'], 'Line']

    # 2行目以降のデータの扱い
    m = df.shape[0] - 1
    k = 1
    for i in range(1, m):
        # 下降トレンド中で価格変化が上昇反転ルールを満たした場合
        if trend <= 0 and df.iloc[i]['Close'] > kagi+delta:
            kagi_df.loc[k] = [df.iloc[i]['Date'], df.iloc[i]['Open'], df.iloc[i]['High'], df.iloc[i]['Low'],
                              df.iloc[i]['Close'], df.iloc[i]['Volume'], kagi, 'up']
            kagi = df.iloc[i]['Close']
            trend = 1
            k += 1
        # 上昇トレンド中で価格変化が下降反転ルールを満たした場合
        elif trend >= 0 and df.iloc[i]['Close'] < kagi-delta:
            kagi_df.loc[k] = [df.iloc[i]['Date'], df.iloc[i]['Open'], df.iloc[i]['High'], df.iloc[i]['Low'],
                              df.iloc[i]['Close'], df.iloc[i]['Volume'], kagi, 'down']
            kagi = df.iloc[i]['Close']
            trend = -1
            k += 1
        # 下降トレンド中で引き続き下降を示した場合
        elif trend <= 0 and df.iloc[i]['Close'] <= kagi:
            kagi = df.iloc[i]['Close']
        # 上昇トレンド中で引き続き上昇を示した場合
        elif trend >= 0 and df.iloc[i]['Close'] >= kagi:
            kagi = df.iloc[i]['Close']
        # 上記以外の場合は何もしない
        
    # データの最終行における設定
    kagi_df.loc[k] = [df.iloc[m]['Date'], df.iloc[m]['Open'], df.iloc[m]['High'], df.iloc[m]['Low'],
                      df.iloc[m]['Close'], df.iloc[m]['Volume'], df.iloc[m]['Close'], 'End']
    return kagi_df

次に株価データを準備して上記の関数を呼び出し、実際に描画します。ここでのポイントはグラフのX軸は行番号(インデックス)を用いますが、描画に際してX軸のティックマークには対応する日付を表示させることです。また、手作業で描く場合には現在のトレンドと同方向の新値はX軸の同じ位置で線を延長しますが、ここでは直近時点以外は反転してX軸上で一つ前に進んでから1時点前の位置で線を繋ぎたしています。

# 株価データの準備
df = stock_data.copy().reset_index()
delta = 10 # 反転基準価格差の設定
df_kagi = KagiChart(df,delta)
print(df_kagi.tail(10))
Date = df_kagi['Date']
Close = df_kagi['Close']
extreme = df_kagi['Extreme']
direction = df_kagi['Direc']
# X軸変数として用いるインデックスの生成
indices = range(len(Date))
fig, ax = plt.subplots(figsize =(10,6))
# 軸目盛には日付を対応させる
plt.xticks(indices, [date.strftime('%Y-%m-%d') for date in Date])
fig.autofmt_xdate()
# 上又は下方向の垂直線を描画し、同じくその起点から左方向へ水平線を描画し、一つ前の時点で垂直線を付け足す
for i in range(1,len(Date)):
    if direction[i] == 'Line':
        ax.plot([indices[i], indices[i]], [extreme[i], Close[i]], color='b')
    elif direction[i] == 'End':
        ax.plot([indices[i-1], indices[i-1]], [extreme[i], Close[i-1]], color='b')
    elif direction[i] == 'up':
        ax.plot([indices[i], indices[i]], [extreme[i], Close[i]], color='b')
        ax.plot([indices[i-1], indices[i-1]], [extreme[i], Close[i-1]], color='b')
        plt.hlines(extreme[i], xmin=indices[i-1], xmax=indices[i], color='b')
    else:
        ax.plot([indices[i], indices[i]], [extreme[i], Close[i]], color='b')
        ax.plot([indices[i-1], indices[i-1]], [extreme[i], Close[i-1]], color='b')
        plt.hlines(extreme[i], xmin=indices[i-1], xmax=indices[i],color='b')
# グラフタイトルと軸ラベルを設定する
ax.set_title('Kagi Chart for '+symbol+' (delta='+str(delta)+')')
ax.set_xlabel('Date')
ax.set_ylabel('Close')
plt.show()

反転ルールは固定値幅以外にも騰落率を用いる方法などがありますが、コード上の修正は容易と思われます。