53
Help us understand the problem. What are the problem?

posted at

updated at

flaskで作った株価チャート配信サーバー

はじめに

株価の時系列データが入ったcsvファイルがあればmplfinanceを使用すれば、pythonが動作する環境で簡単に株価チャートを表示させることができます。この株価チャートをwebブラウザでいつでも見れるようにするのが本稿の趣旨です。

使用するのは、python, mplfinance, flaskでこれらをまとめてdocker-composeでサクッと動かします。

実行環境

ディレクトリ構成

working_dir/
    Dockerfile
    docker-compose.yml
    opt/
        flask_chart.py
        share/
            data/
                1000/
                    1001.csv
                    1002.csv
                    ...
                2000/
                ...
                9000/
                    9001.csv
                    ...

data/ ディレクトリの中に、1000/ ~ 9000/ のサブディレクトリを切ってその中に、「証券コード.csv」という名前の株価日足時系列データが置かれているものとします。

株価日足時系列データのcsvファイルの例は以下。

1301.csv
2015/01/05,275,277,274,275,239000000
2015/01/06,274,275,270,272,480000000
2015/01/07,270,273,270,271,217000000
  ...
2020/11/25,2839,2846,2795,2831,27800000
2020/11/26,2820,2826,2801,2809,8700000
2020/11/27,2807,2825,2803,2819,22000000

Flaskによる株価チャートサーバ

Flaskはpythonでwebサーバの振る舞いを記述できるんでとても便利。matplotlibで作ったグラフをFlaskで配信する例がネットに多くありますが、matplotlibだけでなく、mplfinanceのplotも同じ方法で出来ちゃうんです。

title=flask_chart.py
import os
import numpy as np
import io
from flask import Flask, send_file, request
from flask_cors import CORS
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

import pandas as pd
import mplfinance as mpf

app = Flask(__name__)
CORS(app)

# http://サーバ名:5000/
@app.route('/')
def root():
    return "Chart Server"

# http://サーバ名:5000/candle?code=1001&term=200&volume=True
@app.route("/candle")
def candle():
    code = request.args.get('code', default=None, type=int)
    term = request.args.get('term', default=200, type=int)
    volume = request.args.get('volume', default="True", type=str)
    code_dir = int(code/1000)*1000
    input_path = "/root/opt/share/data/" + str(code_dir) + "/" + str(code) + ".csv"
    df = load_stock_price_csv(input_path, term=term)
    image = io.BytesIO()
    if len(df)>1:
        mpf.plot(df, title=str(code), type='candle',
                 mav=[5, 25, 75], volume=str2bool(volume))
    plt.savefig(image, format='png')
    image.seek(0)
    return send_file(image, attachment_filename="image.png")

def str2bool(s):
     return s.lower() in ["True", "true", "TRUE", "1"]

def load_stock_price_csv(path, term=0):
    if os.path.exists(path):
        df = pd.read_csv(path, header=None, names=['Date','Open','High','Low','Close','Volume'], encoding='UTF-8')
    else:
        df = pd.DataFrame([[0, 0, 0, 0, 0, 0]])
        df.columns = ['Date','Open','High','Low','Close','Volume']
    df['Date'] = pd.to_datetime(df['Date'])
    df = df.set_index("Date")
    if term>0:
        df = df.tail(term)
    return df

if __name__ == '__main__':
     app.run(host='0.0.0.0', port=5000, debug=True)

http://サーバ名:5000/

によりroot()が走ります。ここでは、クライアントに"Chart Server"という文字列を表示させるだけです。

http://サーバ名:5000/candle?code=6897&term=200&volume=True

によりcandle()が走ります。

candle()では、urlパラメータを抽出し、それに従いmpl.plot()でチャートを表示し、それを(メモリ上の)imageにpngでセーブし、クライアントに返します。

docker-composeによる実装

pythonの実行イメージを作って、そこでflaskサーバを稼働させています。

title=Dockerfile
FROM python:3
USER root

RUN apt-get update
RUN apt-get -y install locales && \
    localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm

RUN apt-get install -y vim
RUN pip install --upgrade pip && \
    pip install --upgrade setuptools && \
    pip install --upgrade Flask flask_cors mplfinance
CMD ["python", "/root/opt/flask_chart.py"]

株価データが置かれている場所を、opt/shareにマウントしています。

title=docker-compose.yml
version: '3'
services:
  chart:
    restart: always
    build: .
    container_name: 'chart'
    working_dir: '/root/opt'
    tty: true
    ports:
      - 5000:5000
    volumes:
      - ./opt:/root/opt
      - /home/samba/share/muzinzo:/root/opt/share

株価サーバの起動

$ docker-compose up -d --build

必要に応じてサーバの5000番ポートを開けて、webブラウザで、

http://サーバ名:5000/candle?code=6897&term=120&volume=True

を叩けば株価チャートが見れます。

chart2.png

とてもお手軽に、株価チャート配信サーバを構築できました。サーバでスクリーニングした結果を表示させたり、ページをデコったりと、夢は広がります。

参考までに、株価データを用意したり、チャートを描画したりは、拙文

がお役に立てるかもしれません。

2020/02/11追記

その後、少しWebアプリっぽくしてみました。とは言っても、単なる実装なんで、あえて追記するほどのものではありません。ソースはGutHubに置いています。

2021/2/16追記

作成したサイトをFrozen-Flaskで静的htmlサイトに変換し、GitHubに置いてデモサイトを作ってみました。レスポンシブデザインではないので、PC専用ですが。。

chart3.png

以上

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
53
Help us understand the problem. What are the problem?