[解決!Python]Excelワークシートに株価チャートを作成するには(OpenPyXL)解決!Python

OpenPyXLが提供するStockChartクラスとBarChartクラスを使って、各種の株価チャート(ローソク足など、と棒グラフの組み合わせ)を作成する方法を紹介する。

» 2022年04月12日 05時00分 公開
[かわさきしんじDeep Insider編集部]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「解決!Python」のインデックス

連載目次

from openpyxl import Workbook

wb = Workbook()
ws = wb.active

values = [
    ['日付', '出来高', '始値', '高値', '安値', '終値'],
    ['2022年4月1日', 100300, 2289, 2289, 2212, 2263],
    ['2022年4月4日', 146700, 2299, 2375, 2265, 2375],
    ['2022年4月5日', 119400, 2398, 2434, 2376, 2390],
    ['2022年4月6日', 95600, 2389, 2396, 2330, 2360],
    ['2022年4月7日', 105800, 2329, 2329, 2268, 2274],
]


for v in values:
    ws.append(v)

wb.save('sample_chart.xlsx')

from openpyxl.chart import Reference, StockChart
from openpyxl.chart.axis import ChartLines
from openpyxl.chart.updown_bars import UpDownBars

rmin = ws.min_row
rmax = ws.max_row
cmin = ws.min_column
cmax = ws.max_column

# 株価チャート(ローソク足、始値-高値-安値-終値)
chart0 = StockChart()
labels = Reference(ws, min_col=cmin, min_row=rmin+1, max_row=rmax)
src = Reference(ws, min_col=cmin+2, max_col=cmax, min_row=rmin, max_row=rmax)
chart0.add_data(src, titles_from_data=True)
chart0.set_categories(labels)
chart0.title = '株価チャート(始値-高値-安値-終値)'  # グラフタイトル
chart0.anchor = 'A9'  # グラフの表示位置
chart0.width = 16  # グラフのサイズ
chart0.height = 8

# 各日の値を結ぶ線を削除
for idx, ser in enumerate(chart0.ser):
    ser.graphicalProperties.line.noFill = True

chart0.hiLowLines = ChartLines()  # 高低線(=上ヒゲ/下ヒゲ)を設定
chart0.upDownBars = UpDownBars()  # 陽線/陰線を設定
chart0.legend = None  # 凡例を削除

ws.add_chart(chart0)
wb.save('sample_chart.xlsx')

# 高低線を引くためのハック
from openpyxl.chart.data_source import NumData, NumVal
pts = [NumVal(idx=i) for i in range(rmin, rmax)]
dummy_cache = NumData(pt=pts)
chart0.ser[-1].val.numRef.numCache = dummy_cache
wb.save('sample_chart.xlsx')

# 陽線を赤で、陰線を青で描画する
from openpyxl.chart.shapes import GraphicalProperties
upPr = GraphicalProperties(solidFill='FF0000')
downPr = GraphicalProperties(solidFill='0000FF')
upBars = ChartLines(spPr=upPr)
downBars = ChartLines(spPr=downPr)
chart0.upDownBars = UpDownBars(upBars=upBars, downBars=downBars)

# 株価チャート(高値-安値-終値)
chart1 = StockChart()
src = Reference(ws, min_col=cmin+3, max_col=cmax, min_row=rmin, max_row=rmax)
chart1.add_data(src, titles_from_data=True)
chart1.set_categories(labels)
chart1.title = '株価チャート(高値-安値-終値)'  # グラフタイトル
chart1.anchor = 'A27'  # グラフの表示位置
chart1.width = 16  # グラフのサイズ
chart1.height = 10

for idx, ser in enumerate(chart1.ser):
    ser.graphicalProperties.line.noFill = True

chart1.hiLowLines = ChartLines()
chart1.legend = None
chart1.ser[-1].marker.symbol = 'dot'  # 終値を表すドット
chart1.ser[-1].marker.size = 8
chart1.ser[-1].val.numRef.numCache = dummy_cache  # 高低線を引くためのハック

ws.add_chart(chart1)

wb.save('sample_chart.xlsx')

# 株価チャート(出来高-始値-高値-安値-終値)
from openpyxl.chart import BarChart
from copy import deepcopy

bar0 = BarChart()
bar_src = Reference(ws, min_col=cmin+1, min_row=rmin, max_row=rmax)
bar0.add_data(bar_src, titles_from_data=True)
bar0.set_categories(labels)  # 項目名は流用

chart2 = deepcopy(chart0)
chart2.y_axis.axId = 99  # bar0.y_axis.axIdと違う値に
chart2.y_axis.majorGridlines = None
chart2.y_axis.tickLblPos = 'high'
bar0.title = '株価チャート(出来高-始値-高値-安値-終値)'
bar0.width = 20
bar0.height = 8
bar0.anchor = 'K9'
bar0.y_axis.title = '出来高'
bar0 += chart2

ws.add_chart(bar0)
wb.save('sample_chart.xlsx')

# 株価チャート(出来高-高値-安値-終値)
bar1 = BarChart()
bar_src = Reference(ws, min_col=cmin+1, min_row=rmin, max_row=rmax)
bar1.add_data(bar_src, titles_from_data=True)
bar1.set_categories(labels)  # 項目名は流用

chart3 = deepcopy(chart1)
chart3.y_axis.axId = 99  # bar0.y_axis.axIdと違う値に
chart3.y_axis.majorGridlines = None
chart3.y_axis.tickLblPos = 'high'
bar1.title = '株価チャート(出来高-始値-高値-安値-終値)'
bar1.width = 20
bar1.height = 8
bar1.anchor = 'K27'
bar1 += chart3

ws.add_chart(bar1)
wb.save('sample_chart.xlsx')

bar0.y_axis.title = '出来高'
wb.save('sample_chart.xlsx')


サンプルのワークシート

 本稿では以下のコードで作成したワークシートを例に取る。

from openpyxl import Workbook

wb = Workbook()
ws = wb.active

values = [
    ['日付', '出来高', '始値', '高値', '安値', '終値'],
    ['2022年4月1日', 100300, 2289, 2289, 2212, 2263],
    ['2022年4月4日', 146700, 2299, 2375, 2265, 2375],
    ['2022年4月5日', 119400, 2398, 2434, 2376, 2390],
    ['2022年4月6日', 95600, 2389, 2396, 2330, 2360],
    ['2022年4月7日', 105800, 2329, 2329, 2268, 2274],
]


for v in values:
    ws.append(v)


 これをExcelで表示したものを以下に示す。

サンプルのワークシート サンプルのワークシート

 日付の後には、出来高→始値→高値→安値→終値という順番にデータが並んでいることに注意。本稿で紹介するStockChartクラスでは、おおよそこのような順序でデータが並んでいることを前提としている。特に始値から終値の順序についてはこのように並べておくようにしよう(出来高については独立したグラフを棒グラフとして作成して、後でStockChartクラスのオブジェクトと1つにまとめるので、この位置でなくともよいが、始値から終値までの間にはない方がよい)。

株価チャート

 OpenPyXLを使って株価チャートを作成するには、openpyxl.chart.StockChartクラスを使用する。「株価チャート」といっているが、特定の期間に最小値と最大値を記録したデータであれば、StockChartクラスを使って、同様なグラフを描画できる。

 StockChartクラスを使うと、Excelにおける「株価チャート(始値-高値-安値-終値)」(いわゆるローソク足)と「株価チャート(高値-安値-終値)」(バーチャートに似たもの。ただし、始値を示す横線がない*1)の2種類が作成できる。また、openpyxl.chart.BarChartクラスと組み合わせることで「株価チャート(出来高-始値-高値-安値-終値)」と「株価チャート(出来高-高値-安値-終値)」を作成できる。

  • StockChartクラスのインスタンス(グラフ)を生成する
  • Referenceクラスを使って、グラフ作成の基となる範囲を指定する
  • グラフにデータ(上で作成したReferenceクラスのインスタンス)を渡す
  • グラフのタイトルなどの設定を行う
  • 出来高を含めるならBarChartクラスのインスタンスを生成して、出来高を表しているセル範囲や各種の属性を設定し、株価チャートとまとめる
  • ワークシートにグラフを挿入する

 株価チャート(StockChartクラス)で設定できる項目としては以下がある(一部)。

属性 説明
title属性 グラフのタイトル
anchor属性 グラフの挿入位置
width属性 グラフの横幅
height属性 グラフの高さ
hiLowLines属性 高低線(ローソク足の上ヒゲ/下ヒゲ)
upDownBars属性 陽線/陰線
ser属性 系列ごとのマーカーや線種の設定
株価チャートに設定可能な項目(一部)

*1 ExcelやOpenPyXLで作成できる「株価チャート(高値-安値-終値)」は株価の動きを示す「バーチャート」に似ている。バーチャートでは縦線で高値と安値を表し、そこに始値と終値を示す横線が付加されるが、株価チャート(高値-安値-終値)では始値を示す横線がない点には注意しよう。また、OpenPyXLのBarChartクラスはいわゆる棒グラフを描画するためのものであり、株価の動きを示すバーチャートとは関係ないことにも注意すること。


株価チャート(始値-高値-安値-終値)

 株価チャート(始値-高値-安値-終値)を作成する基本的なコード例を以下に示す。

from openpyxl.chart import Reference, StockChart
from openpyxl.chart.axis import ChartLines
from openpyxl.chart.updown_bars import UpDownBars

rmin = ws.min_row
rmax = ws.max_row
cmin = ws.min_column
cmax = ws.max_column

# 株価チャート(ローソク足、始値-高値-安値-終値)
chart0 = StockChart()
labels = Reference(ws, min_col=cmin, min_row=rmin+1, max_row=rmax)
src = Reference(ws, min_col=cmin+2, max_col=cmax, min_row=rmin, max_row=rmax)
chart0.add_data(src, titles_from_data=True)
chart0.set_categories(labels)
chart0.title = '株価チャート(始値-高値-安値-終値)'  # グラフタイトル
chart0.anchor = 'A9'  # グラフの表示位置
chart0.width = 16  # グラフのサイズ
chart0.height = 8

# 各日の値を結ぶ線を削除
for idx, ser in enumerate(chart0.ser):
    ser.graphicalProperties.line.noFill = True

chart0.hiLowLines = ChartLines()  # 高低線を設定
chart0.upDownBars = UpDownBars()  # 陽線/陰線を設定
chart0.legend = None  # 凡例を削除

# 高低線を引くためのハック
from openpyxl.chart.data_source import NumData, NumVal
pts = [NumVal(idx=i) for i in range(rmin, rmax)]
dummy_cache = NumData(pt=pts)
chart0.ser[-1].val.numRef.numCache = dummy_cache

ws.add_chart(chart0)
wb.save('sample_chart.xlsx')


 このコードでは、まずStockChartクラスのインスタンスを生成し、X軸の項目名となる範囲を変数labelsに、Y軸の値となる値(始値、高値、安値、終値)を変数srcに設定し、それらをStockChartクラスのインスタンスに渡している。特にY軸の値は先ほども述べたように、この順序で並べるのを忘れないようにしよう。

 次に、各日の始値、高値、安値、終値を線でつながないように、各系列のgraphicalPrperties.line.noFill属性の値をTrueとしている。そして、1日単位の高値と安値をつなぐ高低線を引くために、hiLowLines属性にChartLineクラスのインスタンスを設定し、陽線/陰線を描くためにupDownBarsクラスのインスタンスを設定している。

 その後の「高低線を引くためのハック」というのは、OpenPyXLの株価チャートの紹介ページで述べられている通り、Excelの不具合により高低線が表示されないのを回避するためのものだ。

 最後に凡例を削除している。これにより、次のような株価チャートが描画される。

株価チャート(始値-高値-安値-終値) 株価チャート(始値-高値-安値-終値)

 陽線と陰線(中央の矩形。白は終値>始値、つまり値上がりしたことを、黒は終値<始値、つまり値下がりしたことを表す)に色を付けることも可能だ。例えば、陽線を赤で、陰線を青で描画するには次のようにする。

from openpyxl.chart.shapes import GraphicalProperties
upPr = GraphicalProperties(solidFill='FF0000')
downPr = GraphicalProperties(solidFill='0000FF')
upBars = ChartLines(spPr=upPr)
downBars = ChartLines(spPr=downPr)
chart0.upDownBars = UpDownBars(upBars=upBars, downBars=downBars)


 このコードでは塗りつぶしの色を赤('FF0000')と青('0000FF')としたGraphicalPropertiesオブジェクトを定義し、それらを使ってChartLinesクラスのオブジェクトを生成している。そして、塗りつぶし色が赤のChartLinesオブジェクトを陽線(upBars引数)に指定して、塗りつぶし色が青のChartLinesオブジェクトを陰線(downBars引数)に指定している。これにより、株価チャートは次のようになる。

陽線と陰線を赤と青で表現 陽線と陰線を赤と青で表現

株価チャート(高値-安値-終値)

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。