数学がわからない

日々の勉強をアウトプットする。

直近安値を取得するコードをpython3で書く

直近安値について明確な定義はないと思うが、ここでは次のように、安値を曲線と見た場合の変曲点における極小値として求める。

直近安値取得関数

import numpy as np

def calc_most_recent_low(data, width=5):
    """
    直近安値を求める。
    :param data: 対象データ列。安値のリストを想定。
    :param width: 平均計算等のウィンドウ幅
    :return: 最小値リスト、変曲点リスト
    """"""  """
    # widthデータからの移動平均と最小値を取得
    temp = [np.array(data[width - 1:])]
    for n in range(width - 1):
        temp = np.insert(temp, 0, np.array(data[width - 1 - 1 - n:-1 - n]), axis=0)
    average_data = np.mean(temp, axis=0)
    min_data = np.min(temp, axis=0)
    # 要素数をdataと同じ要素数に揃える
    for n in range(width - 1):
        average_data = np.insert(average_data, 0, average_data[0])
        min_data = np.insert(min_data, 0, min_data[0])

    # 移動平均を曲線と見なして微分、符号が負から正に変わる変曲点を取得
    diff = average_data[1:] - average_data[0:-1]
    inflection_point = (diff[0:-1] <= 0) * (diff[1:] > 0)
    # 要素数を揃える。
    inflection_point = np.insert(inflection_point, 0, False)
    inflection_point = np.append(inflection_point, False)

    # 変曲点で最小値が更新される直近安値リストを生成
    most_recent_low = np.zeros(len(data))
    for n in range(len(most_recent_low)):
        if n == 0 or inflection_point[n]:
            most_recent_low[n] = min_data[n]
        else:
            most_recent_low[n] = most_recent_low[n - 1]

    return [most_recent_low, inflection_point, average_data]

結果の例

チャートで表示すると次の通りである。
f:id:rettouseinosugakubenkyo:20190117052954p:plain

ここでは青い点がその日の直近安値、赤い点が変曲点における安値を表している。
また、関数の引数widthは、安値曲線を移動平均とする場合のウィンドウ幅である。上記チャートでは安値は移動平均していないが、細かな安値を拾いたくない場合はこのwidthを2以上にして安値曲線を滑らかにしてやればいい。
f:id:rettouseinosugakubenkyo:20190117053441p:plain

widthを大きくするごとに、変曲点取得用の曲線が滑らかになり、細かな極小値を直近安値として取得しなくなることが分かる。

チャート表示関数

なお、上記で用いたローソク足移動平均線、直近安値を図示する関数は次の通りである。

import matplotlib.pyplot as plt
import mpl_finance


def plot_ohlc_and_mrl(df, days = 100, width = 1):
    # 直近安値を取得
    most_recent_low, inflection_point, aline = calc_most_recent_low(df.安値, width=width)
    
    # 表示
    fig = plt.figure(figsize=[15, 5])
    ax = fig.add_subplot(111)

    # ローソク足(データの後半をdays日分切り取り)
    ohlc = np.array([list(range(len(df))), list(df.始値), list(df.安値), list(df.高値), list(df.終値)]).T
    mpl_finance.candlestick_ohlc(ax, ohlc[-days:], width=0.7, colorup='g', colordown='r')

    # x軸
    x_index = range(len(df) - days, len(df))
    # 移動平均線
    ax.plot(x_index, aline[-days:])
    # 直近安値
    ax.plot(x_index, most_recent_low[-days:], 'b.')
    # 変曲点
    for i in x_index:
        if inflection_point[i]:
            ax.plot(i, most_recent_low[i], 'ro')

    # x軸ラベル
    skip = 5
    x_index_skip = range(len(df) - 1 - skip*(days//skip), len(df), skip)
    x_label = [x for x in df.index][-1-skip*(days//skip)::skip]
    plt.xticks(x_index_skip, x_label)

    # 表示データ範囲の指定
    ax.set_xlim(len(df) - days, len(df))

    ax.grid() # グリッド
    fig.autofmt_xdate() # x軸のオートフォーマット
    plt.show()

まとめ

以上、株価データから直近安値を取得するコードをpython3で書いた。このような直近安値は株売買の際のスクリーニングに使うことがある。
ただ、直近安値といっても定義は様々である。たとえば今回の移動平均のウィンドウサイズや、安値を使うのか、終値を使うのかでも違った値が出ることに注意が必要だろう。