株価の推移を日々自動で取得する

  • URLをコピーしました!
目次

はじめに

株式投資や企業分析において、日々の株価データを取得することは重要な要素です。この記事では、東証一部上場企業の時価総額上位100社に対して、Yahoo Financeから日々の株価データを取得してデータベースに格納する方法を紹介します。Pythonを使って株価データを取得し、データベースに格納する手順を説明します。
※時価総額上位100社、は取得したタイミングのものになります

データベースの作成

まずはSQLiteデータベースを作成しましょう。SQLiteは軽量で使いやすいデータベースであり、Pythonの標準ライブラリに含まれています。次の手順でデータベースを作成し、企業名と企業コードのテーブル、並びに株価データを格納するテーブルを作成します。

まず、SQLiteを使うためのsqlite3ライブラリをインポートします。

import sqlite3

次に、データベースとの接続を作成し、カーソルオブジェクトを取得します。

conn = sqlite3.connect("stock_data.db")
cursor = conn.cursor()

ここで、stock_data.dbはデータベースファイル名です。ファイルが存在しない場合、新しいデータベースファイルが作成されます。

東証一部上場企業の時価総額上位100社の企業名、企業コードを取得してデータベースへ格納

東証一部上場企業の時価総額上位100社の企業名と銘柄コードリストを取得して、データベースに格納しておきます。ここでは、ウェブサイトからスクレイピングする方法を紹介します。PythonのrequestsとBeautifulSoupライブラリを使って、ウェブページから情報を取得します。また、取得したデータをデータベースに格納するために、sqlite3ライブラリを使用します。

まず、必要なライブラリをインストールします。

pip install requests beautifulsoup4

次に、以下のコードを実行して、東証一部上場企業の時価総額上位100社の企業名と銘柄コードリストを取得し、データベースに格納します。

import requests
from bs4 import BeautifulSoup
import sqlite3

# 時価総額上位100社の企業名と銘柄コードが掲載されているウェブサイトのURLを指定してください
#私は日経の時価総額ランキングから企業名と銘柄のみ取得しました。
#現在値を定期的に取得するなどの行為は規約に反する恐れがあるので避けましょう
#https://www.nikkei.com/info/copyright.html

url = "企業名と銘柄コードが掲載されているウェブサイト"  

response = requests.get(url)
soup = BeautifulSoup(response.content, "html.parser")

company_ticker_list = []

# BeautifulSoupを使って適切なタグやクラスを指定し、企業名と銘柄コードを取得します。
# 以下は一例です。実際に使用するウェブサイトに応じて、適切に変更してください。
#この部分のコードが上手くできない場合はwebサイトからテーブルをcsvにコピーする等でも良いでしょう
table = soup.findAll("table")[0]
rows = table.findAll("tr")
for row in rows:
    company = row.select_one("企業名").text.strip()
    ticker = row.select_one("銘柄コード").text.strip()
    company_ticker_list.append((company, ticker))

# データベースに格納
conn = sqlite3.connect("stock_data.db")
cursor = conn.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS company_ticker (company TEXT, ticker TEXT)")

for company, ticker in company_ticker_list:
    cursor.execute("INSERT INTO company_ticker (company, ticker) VALUES (?, ?)", (company, ticker))

conn.commit()
conn.close()

print("企業名と銘柄コードがデータベースに格納されました。")

# 結果の表示
print("企業名と銘柄コードリスト:")
for company, ticker in company_ticker_list:
    print(f"{company}: {ticker}")

このコードは、指定したウェブサイトから企業名と銘柄コードを取得し、リストに格納します。その後、sqlite3ライブラリを使用して、取得したデータをデータベースに格納します。最後に、格納されたデータを表示します。

株価データの収集

まず、以下のコマンドを実行して、必要なライブラリをインストールしましょう。

pip install pandas-datareader yfinance

次に、株価データを格納するテーブルを作成します。テーブルには、以下のカラムを持たせます。

  • id: プライマリキー
  • ticker: 銘柄コード
  • date: 日付
  • open: 始値
  • high: 高値
  • low: 安値
  • close: 終値
  • volume: 出来高
  • dividends: 配当金
  • stock_splits: 株式分割

以下のコードを実行して、テーブルを作成します。

cursor.execute("""
CREATE TABLE IF NOT EXISTS stock_data (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    ticker TEXT NOT NULL,
    date DATE NOT NULL,
    open REAL,
    high REAL,
    low REAL,
    close REAL,
    volume REAL,
    dividends REAL,
    stock_splits REAL
);
""")

最後に、テーブル作成の変更をコミットし、データベースとの接続を閉じます。

conn.commit()
conn.close()

これで、株価データを保存するためのSQLiteデータベースが作成されました。次のステップでは、データベースに株価データを格納する方法を説明します。

Yahoo Financeから株価データを取得する関数の作成

前述の記事で取得した東証一部上場企業の時価総額上位100社の銘柄コードを使って、指定した日付の株価データを取得するための関数を作成します。Pythonのライブラリを使って、Yahoo Financeから株価データを取得します。以下のコードを実行して、指定した日付の株価データを取得する関数を作成します。

import yfinance as yf
from datetime import datetime

def get_stock_price(ticker, start_date, end_date):
    # Yahoo Financeから株価データを取得
    stock = yf.Ticker(f"{ticker}.T")
    df = stock.history(start=start_date, end=end_date)

    return df

# データベースから銘柄コードを取得
conn = sqlite3.connect("stock_data.db")
cursor = conn.cursor()
cursor.execute("SELECT ticker FROM company_ticker")
tickers = [row[0] for row in cursor.fetchall()]
conn.close()

# 例:2023年4月1日の株価データを取得
start_date = datetime(2023, 4, 1)
end_date = datetime(2023, 4, 2)

for ticker in tickers:
    stock_data = get_stock_price(ticker, start_date, end_date)
    print(f"{ticker}: {stock_data}")

このコードは、指定した銘柄コードと日付を引数に取るget_stock_price関数を作成します。この関数は、Yahoo Financeから株価データを取得し、pandas DataFrame形式で返します。データベースから銘柄コードを取得し、各銘柄に対して株価データを取得します。

この関数を使って、東証一部上場企業の時価総額上位100社の銘柄コードに対応する株価データを簡単に取得することができます。株価データは、他の分析や処理に利用できます。

株価データを収集していく

前述の記事で作成したget_stock_price関数を使って、東証一部上場企業の時価総額上位100社の銘柄コードに対応する株価データをデータベースに格納します。データの取得は、過去のデータが存在しなくなるまで続け、取得できなくなったら終了します。

まず、stock_priceという名前の新しいテーブルを作成します。このテーブルには、銘柄コード、日付、始値、高値、安値、終値、出来高のカラムが含まれます。

conn = sqlite3.connect("stock_data.db")
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS stock_price
                  (ticker TEXT, date DATE, open REAL, high REAL, low REAL, close REAL, volume INTEGER)''')
conn.commit()

次に、以下のコードを実行して、東証一部上場企業の時価総額上位100社の銘柄コードに対応する株価データをデータベースに格納します。データの取得は、過去のデータが存在しなくなるまで続け、取得できなくなったら終了します。

from datetime import timedelta

def store_stock_data(ticker, start_date):
    end_date = datetime.now()

    while start_date <= end_date:
        try:
            stock_data = get_stock_price(ticker, end_date - timedelta(days=7), end_date)
            if stock_data.empty:
                break

            for index, row in stock_data.iterrows():
                cursor.execute("INSERT INTO stock_price (ticker, date, open, high, low, close, volume) VALUES (?, ?, ?, ?, ?, ?, ?)",
                               (ticker, index.date(), row["Open"], row["High"], row["Low"], row["Close"], row["Volume"]))

            end_date -= timedelta(days=7)
        except Exception as e:
            print(f"Error for {ticker} on {start_date}: {e}")
            break

    conn.commit()

# 銘柄コードリストを使って、各銘柄の株価データをデータベースに格納
start_date = datetime(2023, 4, 1)

for ticker in tickers:
    print(f"Storing stock data for {ticker}")
    store_stock_data(ticker, start_date)

# データベースを閉じる
conn.close()

このコードは、store_stock_data関数を使って、各銘柄の株価データをデータベースに格納します。データの取得は、現在のデータから過去にさかのぼっていき、過去のデータが存在しなくなるか指定した開始日まで続けます。日々取得しようとすると非稼働日がエラーになってしまいます。また、長い期間を指定すると省略された状態で値が返却されてしまうため、取得単位を一週間としています。大変時間がかかる処理のため、実際には半年や一年ごとで取得しなおすようにしましょう。この方法により、データベースに東証一部上場企業の時価総額上位100社の銘柄コードに対応する株価データが格納されます。

株価の取得(一括)

最初に少しずつ株価を取得していくと、アクセス回数の制限にあたる場合などもありますので、別の手法として一括で取得する方法も記載しておきます。yahoo_finance_api2を用いて日足でとれるだけの範囲のデータを取得しています。必要に応じてこちらも使ってください。

from yahoo_finance_api2 import share
from yahoo_finance_api2.exceptions import YahooFinanceError
import pandas as pd
import sqlite3
import datetime

# データベースから銘柄コードを取得
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
#一度テーブルをクリアしておきます
cursor.execute('''DROP TABLE stock_price''')
cursor.execute('''CREATE TABLE IF NOT EXISTS stock_price
                  (ticker TEXT, date DATE, open REAL, high REAL, low REAL, close REAL, volume INTEGER,PRIMARY KEY(ticker,date))''')
conn.commit()
cursor.execute("SELECT ticker FROM company_ticker")
tickers = [row[0] for row in cursor.fetchall()]

def get_stock_price(ticker):
    # Yahoo Financeから株価データを取得
  stock = share.Share(f"{ticker}.T")
  symbol_data = None
  try:
    symbol_data = stock.get_historical(
      share.PERIOD_TYPE_YEAR, 30,
      share.FREQUENCY_TYPE_DAY, 1)
    df = pd.DataFrame(symbol_data.values(), index=symbol_data.keys()).T
    df.timestamp = pd.to_datetime(df.timestamp, unit='ms')
    df.index = pd.DatetimeIndex(df.timestamp, name='timestamp').tz_localize('UTC').tz_convert('Asia/Tokyo')
    return df
  except YahooFinanceError as e:
    print(e.message)
 
def store_stock_data(ticker):
  stock_data = get_stock_price(ticker)
  for index ,row in stock_data.iterrows():
#日付によって欠損データが存在します。その場合isnull()がTrueになるので、すべての列に欠損がないかチェックします
    if row.isnull().sum() == 0:
      cursor.execute("INSERT INTO stock_price (ticker, date, open, high, low, close, volume) VALUES (?, ?, ?, ?, ?, ?, ?) ON CONFLICT(ticker, date) DO NOTHING",
         (ticker, row["timestamp"].date(), row["open"], row["high"], row["low"], row["close"], row["volume"]))
  conn.commit()

for ticker in tickers:
    print(f"Storing stock data for {ticker}")
    store_stock_data(ticker)

# データベースを閉じる
conn.close()

定期的に株価データを取得してデータベースに格納するスケジューリング

定期的に東証一部上場企業の時価総額上位100社の銘柄コードに対応する株価データを取得し、データベースに格納する方法を紹介します。定期実行の手段は幾つもありますが、すべてPythonで閉じる場合を一例として挙げておきます。Pythonでスケジューリングを行うために、scheduleというライブラリを使用します。まず、scheduleライブラリをインストールしましょう。

pip install schedule

次に、以下のコードを使って、定期的に株価データを取得してデータベースに格納するスケジューリングを設定します。

import schedule
import time

def job():
    start_date = datetime.now().date()
    for ticker in tickers:
        print(f"Storing stock data for {ticker}")
        store_stock_data(ticker, start_date)

# 毎日午後6時に株価データを取得してデータベースに格納するスケジューリングを設定
schedule.every().day.at("18:00").do(job)

# スケジューリングを実行する無限ループ
while True:
    schedule.run_pending()
    time.sleep(60)

このコードは、jobという関数を定義し、毎日午後6時に実行されるようスケジューリングを設定しています。この関数では、現在の日付を取得し、その日の株価データをデータベースに格納します。最後に、whileループを使ってスケジューリングを実行し続けます。

これで、定期的に株価データを取得してデータベースに格納するスケジューリングが設定されました。毎日午後6時に、東証一部上場企業の時価総額上位100社の銘柄コードに対応する株価データがデータベースに格納されます。

apschedulerを使った方法

apschedulerは、Pythonで高度なスケジューリングを行うためのライブラリです。まず、apschedulerライブラリをインストールします。

pip install apscheduler
from apscheduler.schedulers.blocking import BlockingScheduler

def job():
    start_date = datetime.datetime.now().date()
    for ticker in tickers:
        print(f"Storing stock data for {ticker}")
        store_stock_data(ticker, start_date)

# スケジューラのインスタンスを作成
scheduler = BlockingScheduler()

# 毎日午後6時にjob()関数を実行するスケジューリングを設定
scheduler.add_job(job, 'cron', hour=18, minute=0)

# スケジューラを開始
scheduler.start()

このコードは、BlockingSchedulerクラスのインスタンスを作成し、add_job()メソッドを使って、毎日午後6時にjob()関数が実行されるようスケジューリングを設定しています。最後に、start()メソッドでスケジューラを開始します。

どちらの方法も、一日一回同じ時間にタスクを実行するスケジューリングを行うことができます。用途や状況に応じて、適切な方法を選択してください。

まとめ

このブログ記事では、Pythonを使って東証一部上場企業の時価総額上位100社の銘柄コードに対応する株価データを取得し、データベースに格納する方法を紹介しました。以下は、本記事で取り上げた手順の概要です。

  1. データベースの作成
  2. 東証一部上場企業の時価総額上位100社の企業名、企業コードを取得してデータベースへ格納
  3. Yahoo Financeから株価データを取得する関数の作成
  4. 株価データをデータベースに格納する方法
  5. 定期的に株価データを取得してデータベースに格納するスケジューリング

本記事で説明した方法を使えば、東証一部上場企業の時価総額上位100社の銘柄コードに対応する株価データを取得し、データベースに格納することができます。さらに、スケジューリングを設定して、定期的に株価データを取得してデータベースに格納することも可能です。

これらの手法を活用して、株価データを取得し、データベースに格納するシステムを構築しましょう。株価データを自動的に収集することで、株式投資や企業分析に役立つ情報を効率的に収集できます。

バーマン
プロダクトマネージャー
ソフトウェア開発に長く従事しています。
・機械学習のサンプルコード作成
・生成型AIから調べたことのまとめ
・これまでのビジネスで経験したことのまとめ
を記事として作成させていただいています。
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次