2024-08-07

yfinance で1分足の為替データを監視

yfinance [1] [2] は、Yahoo Inc. が公開している API を利用した、Yahoo Finance の株価などの金融情報にアクセスしてデータを取得するために開発されたオープンソースの Python ライブラリです。

本ブログで yfinance を利用して1分足の為替データを取得、mplfinance でローソク足チャートを作成する方法を紹介しました [3]。今回は、紹介したスクリプトをベースにして、PySide6 で GUI 化しました。

今回のテーマ
  • Python で yfinance パッケージを利用して、3時間前から現在までの、ドル・円の為替レートの1分足のデータを取得してチャートにし、1分間隔で更新する GUI アプリを作ります。

下記の OS 環境で動作確認をしています。

RHEL 9.4 x86_64
Python 3.12.1
PySide6 6.7.2
mplfinance 0.12.10b0
yfinance 0.2.41

サンプルを以下に示しました。

qt_yfinance_exchange.py
import datetime as dt
import mplfinance as mpf
import pandas as pd
import sys
import yfinance as yf
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from PySide6.QtCore import QTimer
from PySide6.QtWidgets import (
QApplication,
QMainWindow,
)
class MyChart(FigureCanvas):
def __init__(self):
self.fig = Figure()
self.fig.subplots_adjust(left=0.2, right=0.95, top=0.9, bottom=0.15)
self.ax = self.fig.add_subplot(111)
super().__init__(self.fig)
def clearAxes(self):
axs = self.fig.axes
for ax in axs:
ax.cla()
def refreshDraw(self):
self.fig.canvas.draw()
def removeAxes(self):
axs = self.fig.axes
for ax in axs:
ax.remove()
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Exchange')
self.setFixedSize(400, 400)
self.ticker = yf.Ticker('USDJPY=X')
self.chart = MyChart()
self.setCentralWidget(self.chart)
self.draw_chart()
timer = QTimer(self)
timer.timeout.connect(self.draw_chart)
timer.start(60000)
def draw_chart(self):
df = self.get_exchange()
if len(df) == 0:
return
self.chart.clearAxes()
mpf.plot(df, type='candle', style='binance', ax=self.chart.ax, )
df0 = df.tail(1)
title = '%.3f JPY at %s' % (df0['Close'].iloc[0], str(df0.index[0].time()))
self.chart.ax.set_title(title)
self.chart.ax.set_ylabel('USD - JPY')
self.chart.ax.grid()
self.chart.refreshDraw()
def get_exchange(self) -> pd.DataFrame:
end = dt.datetime.now(dt.timezone(dt.timedelta(hours=9)))
delta = dt.timedelta(hours=3)
start = end - delta
df = self.ticker.history(start=start, end=end, interval='1m')
if len(df) > 0:
df.index = df.index.tz_convert('Asia/Tokyo')
return df
def main():
app = QApplication()
ex = Example()
ex.show()
sys.exit(app.exec())
if __name__ == '__main__':
main()

以下に実行例を示しました。

qt_yfinance_exchange.py の実行例

サンプルの説明

最初の MyChart クラスは、PySide6 で Matplotlib のチャートを PySide6 側でウィジェットとして扱えるようにする FigureCanvas を継承したクラスです。

class MyChart(FigureCanvas):
    def __init__(self):
        self.fig = Figure()
        self.fig.subplots_adjust(left=0.2, right=0.95, top=0.9, bottom=0.15)
        self.ax = self.fig.add_subplot(111)
        super().__init__(self.fig)
 
    def clearAxes(self):
        axs = self.fig.axes
        for ax in axs:
            ax.cla()
 
    def refreshDraw(self):
        self.fig.canvas.draw()
 
    def removeAxes(self):
        axs = self.fig.axes
        for ax in axs:
            ax.remove()

次の Example クラスは、ドル・円の為替レートの1分足のデータを取得してチャートに表示するメインプログラムです。

クラスの初期化メソッド(コンストラクタ)では、次の処理をしています。

  1. ウィンドウのタイトル、サイズを設定
  2. yfinanceTicker クラスのインスタンス self.ticker を定義
  3. 60,000 ミリ秒(= 1分)毎に self.draw_chart メソッドを実行するタイマーを起動
class Example(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Exchange')
        self.setFixedSize(400, 400)
 
        self.ticker = yf.Ticker('USDJPY=X')
        self.chart = MyChart()
        self.setCentralWidget(self.chart)
        self.draw_chart()
 
        timer = QTimer(self)
        timer.timeout.connect(self.draw_chart)
        timer.start(60000)

self.draw_chart メソッドでは、self.get_exchange メソッドでドル・円の為替レートの1分足のデータフレームを取得して、mplfinance パッケージ (= mpf) でローソク足チャートを描画しています。

def draw_chart(self):
    df = self.get_exchange()
    if len(df) == 0:
        return
 
    self.chart.clearAxes()
    mpf.plot(df, type='candle', style='binance', ax=self.chart.ax, )
 
    df0 = df.tail(1)
    title = '%.3f JPY at %s' % (df0['Close'].iloc[0], str(df0.index[0].time()))
    self.chart.ax.set_title(title)
    self.chart.ax.set_ylabel('USD - JPY')
    self.chart.ax.grid()
    self.chart.refreshDraw()

self.draw_chart メソッドでは、現在時刻と3時間前の時刻から、Ticker クラスのインスタンス self.tickerhistory メソッドで過去3時間のドル・円の為替レートの1分足のデータフレームを取得して、インデクスの時刻データのタイムゾーンを日本に変換して返します。

取引時間外で取得したデータフレームが空の場合は何もせずにそのまま空のデータフレームを返します。

def get_exchange(self) -> pd.DataFrame:
    end = dt.datetime.now(dt.timezone(dt.timedelta(hours=9)))
    delta = dt.timedelta(hours=3)
    start = end - delta
    df = self.ticker.history(start=start, end=end, interval='1m')
    if len(df) > 0:
        df.index = df.index.tz_convert('Asia/Tokyo')
    return df

取得するデータ量を最小限にする工夫をするべきですが、ここではアプリ側の処理をシンプルにするため。毎回、過去3時間のデータを全て取ってきてしまっています。

参考サイト

  1. ranaroussi/yfinance: Download market data from Yahoo! Finance's API
  2. yfinance · PyPI
  3. bitWalk's: yfinance で1分足の為替データを取得 [2024-08-01]
  4. QTimer - Qt for Python

 

ブログランキング・にほんブログ村へ bitWalk's - にほんブログ村 にほんブログ村 IT技術ブログ オープンソースへ
にほんブログ村

オープンソース - ブログ村ハッシュタグ
#オープンソース



0 件のコメント: