メインコンテンツへスキップ
見出し画像

分足株価データベースを作成 ~MySQLでDB化 株式分割/統合 完全自動計算~

    こんにちはRcatです。
    さて、この連休でやっとやりたいことに手がつけられそうです。
    手始めに、まずは以下で紹介している方法で取得したデータの加工を行っていきます。前提なのでまだの方はこちらを先にご覧ください。


    はじめに

    利用規約

    情報や作品の活用時は事前に利用規約をご確認ください。

    コメントについて

    利用規約のガイドラインを確認の上コメントしてください


    概要

    今回何をするかと言うと、まずはデータの整合性チェックです。
    上記のツールは日々株価のデータを収集するためのツールですが、収集することはできてもそれを編集する機能はありません。
    何が問題になるかと言うと株式分割です。株式分割が行われると急に株価が変動します。
    証券会社から取得する時点の情報は自動的に最適化されますが、自分のところにあるデータはそうではありません。

    というわけで、今回は自動的に株式分割を検出し、自動で最適化までを行っていこうと思います。


    事前準備

    DB化する

    上記のツールではCSVとして取得するのが前提ですが、今後利用するにあたりデータベースにした方が扱いやすいと思うので、まずはデータベースに移動してしまいます。
    ※手軽にCSVがいいという方もいると思いますので、今後も分足の取得はCSVを継続します。取得→アップロードという手順にします。

    データベースって?

    今回の話はプログラミング色が強いわけではないので、こういう関連は全くという方もいると思いますので、簡単に説明します。

    今回使用するのはMySQLというデータベースです。種類は関係データベースとなります。
    関係データベースは簡単に言えばCSVの表が入っているデータベースです。大きな箱の中にたくさんの表が入っているだけです。なので、イメージとしてはそんなに難しいものではありません。

    大枠としては、サーバーの中に複数のデータベースがあり、その中にCSVファイルのようなテーブルがたくさん作れるというものです。
    今回は専用のデータベースを1つと各銘柄ごとにテーブルを作ります。

    画像

    今回データベース化する理由としてはデータを取り出す時において処理が楽だからです。
    現時点では日付ごとでデータが分かれていますが、ではある銘柄の最大株価を出力したいとなった場合どうすればいいでしょうか?
    全てのファイルを開いて一番大きい値を探さなきゃいけないですね。
    しかし、これがデータベースだと一発で出すことができます。

    他にも別の足データが混ざって格納していたり、あるいは行が逆転してしまっていたとしても、"範囲を指定して日付順でください"というだけで並んで返ってくるので、表の扱いが非常に楽になります。

    また、この後のメインコンテンツになりますが、株式分割により株価を全て半分にしたい場合は行ごとに更新作業が必要ですが、データベースならたった数十文字打ち込んでエンターするだけでアップデートできます。

    こういった理由から、これから先はCSVファイルを直接扱うのではなく、データベースと連携する前提とします。

    DB事前準備

    MySQL導入が前提なので、まだの方は下記にてWindowsまたはLinuxに導入しましょう。

    Windowsの場合

    こちらを参考にしました。古い記事みたいですが、画面ほぼ同じなので問題なく進められました。

    ダウンロードはこちら
    https://dev.mysql.com/downloads/mysql/

    サーバーをダウンロードしたら、インストール先(例: C:\Program Files\MySQL\MySQL Server 9.3\bin)を環境変数PATHに追加してから、コマンドプロンプトでアクセスします。

    画像

    データベースは必ず作らないといけないので、2行目だけは実行してください。
    rootを使いたくない場合は以下のように追加でユーザーを作りましょう。
    ユーザーを作ったらアクセス権が必要なので付与してください。

    C:\Users\Rcat>mysql -u root -p
    Enter password: **************
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 13
    Server version: 9.3.0 MySQL Community Server - GPL
    
    Copyright (c) 2000, 2025, Oracle and/or its affiliates.
    
    mysql> CREATE USER "remote"@"localhost" IDENTIFIED BY "パスワード";
    mysql> create database StocksDB;
    mysql> GRANT ALL PRIVILEGES ON StocksDB.* TO 'remote'@"localhost";

    Linuxの場合

    ちなみに今回はリモートのLinuxを使います。
    リモートユーザーの作り方はこちら。
    Windowsと同じようにデータベースの作成も行います。

    $mysql -u root -p
    mysql>CREATE USER 'remote'@'192.168.0.%' IDENTIFIED BY 'ぱすわーど☆';
    mysql>create database StocksDB;
    mysql>GRANT ALL PRIVILEGES ON StocksDB.* TO 'remote'@'192.168.0.%';

    最後のIPアドレスは個々人の環境にあったローカルIPアドレスに対応させないとログインできないので注意。
    作ったらDBにアクセス権を付与します。今回は専用のを作りそのすべての権限を持たせます。

    アップロード用コード

    ※簡単な設定だけで移行できるツールを配布します。このセクションの説明はわからなければ見なくても大丈夫です。

    まず、DBのテーブルはこんな感じにします。
    こちら見てわかる通り、CSVファイルとほぼ同じということが分かるでしょう。
    なお、1つの表で1つの銘柄を表し、全ての足をまとめてテーブル(表)に入れてしまいます。
    これなぜかと言うと、取り出す時に一番左側の"kindを1Mで"と指定すればそれだけで1分足だけを出すといったことができるので、わざわざ表を分ける必要がなくなっているのです。

    画像

    ちなみにわかる人にだけになりますが、この表は種類と日付の複合主キーです。また、基本的には日付で管理するのでインデックスが日付になってます。
    中身を確認するにはMySQL Workbenchを使うと見やすいです。

    アップロードはこんな感じ
    DBテーブルの日付より新しいCSV探して、あればアップロード。
    データベースはひとつで、テーブルの名前を"Stock_証券コード"という名前にしています。

    画像

    アップロードするとこんな感じになります。

    画像

    使わない場合はこんな感じで直接SQLを打ち込みます。

    $ mysql -u root -p
    mysql> use StocksDB
    Database changed
    mysql> show tables;
    +--------------------+
    | Tables_in_StocksDB |
    +--------------------+
    | Stock_1XXX         |
    | Stock_1XXX         |
    | Stock_1XXX         |
    | Stock_1XXX         |
    | Stock_1XXX         |
    | Stock_1XXX         |
    ...

    株式分割を検知する

    データベース化が終わったら、次に分割を検知します。
    これは単純な仕組みで、古いものから見ていき、終値と開始値が一定以上の開きがある場合に分割や併合を疑います。

    ただし、ストップ安やストップ高でかなりの変動を起こすことがあるため、急な変動が分割なのかどうか確認する必要があります。

    いちいち自分で確認しますか?
    No! 今はAIの時代です。AIに検索させて何分割だったかの数値まで答えさせましょう!

    Google検索とAIで分割を自動取得

    株式分割らしき変動を見つけたら、それが何分割なのかを正確に取得する必要があるため、今回はGoogle GeminiとGoogle検索を組み合わせて自動検索を行います。

    前提として、GeminiのAPIをコールするためのAPIキーがいります。
    下記で取得方法を解説しているので参考にしてください。
    ※今回は下記で紹介している"Dify"は導入しません。

    ※この先のコードの部分は知りたい人のための情報なので気にしなくても大丈夫です。必要なのはキーだけです。

    GeminiでGoogle検索を組み合わせるコードは以下

    #ライブラリのインストール
    $pip install google-genai

    AIを呼び出すコードは以下

    from google import genai
    from google.genai.types import Tool, GenerateContentConfig, GoogleSearch
    client = genai.Client(api_key="GeminiのAPIキー")
    google_search_tool = Tool(google_search = GoogleSearch())
    response = client.models.generate_content(
    	model="gemini-2.0-flash",
    	contents="ここにプロンプトを書く",
    	config=GenerateContentConfig(
    		tools=[google_search_tool],
    		response_modalities=["TEXT"],
    	)
    )

    ・・・超簡単ですね。
    なお、過負荷等でエラーになることがあるので適宜リトライ必須。使用制限は一日1500回です。

    後はAIに対する指示を考えて投稿すればOK。
    ちなみに現状のプロンプトはこんな感じ。ほぼモザイクですがw。詳細はデータDLにて確認してください。

    画像

    自動で分割データを適用

    DBとAIの準備が出来たらいよいよ分割の最適化です。
    コード前半はこんな感じ。下から順次見ていって乖離が大きい行を検出したら、一番解像度の高いデータを代表でAIに投げる感じですね。

    画像

    AIがネット検索して、分割だと判断すると、何分割か等を返してくるので、それを使って最適化を行うのが後半。

    画像

    書き換えは簡単で、SQLに計算式と分割日以前という指示を渡すだけ。DB最高。

    適用される仕組みが分かりやすいように手続きで書きます。
    例えば4月から分割されたKDDIのデータがあったので試します。
    引数にTrueを付けると手動で確認できます。

    >>> from DataBase import StockDBCheck
    >>> s = StockDBCheck("remote","ぱすわーど☆","192.168.0.4")
    >>> s.Check(9433,True,True)
    2025-05-03 00:50:48,647 WARNING DataBase 株式分割と思われる大きな揺らぎを検知
    2025-05-03 00:50:51,669 INFO DataBase 株式分割を検出:2分割 理由:2025年3月31日を基準日として1株につき2株の割合で株式分割の情報有
    2025-05-03 00:50:51,669 INFO DataBase 前後のデータは4860.00 => 2430.00
    変更を適用しますか?(y/n)y
    2025-05-03 00:51:00,804 INFO DataBase 適用中:9433:1M
    2025-05-03 00:51:01,044 INFO DataBase 適用中:9433:5M
    2025-05-03 00:51:01,132 INFO DataBase 適用中:9433:10M
    
    >>> s.Check(9433,True,True)
    2025-05-03 00:52:28,254 INFO DataBase 株式分割と思われる揺らぎは見つかりませんでした
    False

    この例ではAIが2分割であると判断したようです。前後のデータを見てもそれらしい値になっています。※自分で見てもそうでした。

    以下の例では私が分割前最後に取得したタイミングが14日で、それ以降が分割の価格になっておりぱっと見急落に見えます。
    それを自動で処理すると右のようになります。

    画像

    DB化&分割最適化ツールの使い方

    さて、上ではプログラム的な話をしてしまいましたが、そういうのよくわからないという方もいると思いますので、ここからは配布ツールの使い方に絞って解説します。

    最下部からデータをDLすると、中身は以下のようになっています。
    Pythonの前提ですが、前提ツールでPythonはインストールしていただいてるのでそのまま実行できるはずです。

    画像

    ツールの設定を書き換える

    まずは配布ツール(DataBase.py)をテキストエディダ(メモ帳など)で開いて内部の設定を自分用に変更します。
    変更点は下記の通りで大体150行目くらいにあります。

    設定の内容に関しては、読み飛ばしてきた場合は適宜戻ってください。

    • SQL_XXX
      上で説明しているデータベース関連の設定です。

    • Gemini_Model
      Geminiの推論モデルです。現時点では最新なのでこのままでよいですが、今後アップデートでモデルが変わった場合は変更が必要です。
      ※APIに登録していればモデルのサービス終了などはメールが来ます

    • Gemini_APIKEY
      GeminiのAPIキーです。自分で取得する必要があります。詳しくは上で説明しています。

    • CSV_RootDir
      エクセルのツールで収集したCSVファイルがあるフォルダ。各個人の環境に合わせて書き換える。先頭の"r"を間違って消さないように注意。

    画像

    編集が完了したら、歯車のstartをダブルクリックして実行します。初回は環境構築が入るので少し時間がかかります。

    最初に全データのDB化が行われます。
    登録エントリが1行ずつなので、量によっては1銘柄1分以上かかる場合があります。100銘柄で1時間以上かかります…。

    登録が終わると、分割のチェックに入ります。デフォルトでは処理前に確認のメッセージが入りますので、y/nを入力して確定します。こちらはすぐ終わります。
    分割と値段から妥当性を検証しても良いですし、自分で調べなおしても良いです。もちろんAIを信じてノーチェックでも…。
    まぁ頻繁に起こることではないので手で確認してもいいのではないでしょうか。

    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした
    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした
    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした
    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした
    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした
    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした
    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした
    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした
    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした
    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした
    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした
    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした
    WARNING DataBase XXXX 株式分割と思われる大きな揺らぎを検知
    INFO DataBase 株式分割を検出:15分割 理由:XXXXは2025年1月23日を基準日として、1:15の株式分割を実施しました。
    INFO DataBase 前後のデータは20690.00 => 1378.33
    変更を適用しますか?(y/n)y
    INFO DataBase 適用中:XXXX:1M
    INFO DataBase 適用中:XXXX:5M
    INFO DataBase 適用中:XXXX:10M
    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした
    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした
    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした
    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした
    INFO DataBase XXXX: 株式分割と思われる揺らぎは見つかりませんでした

    高度な情報

    本ツールは引数で動作を指定することができます。
    start.batの中身も以下で起動しています。

    python "%SCRIPTNAME%" -m upload
    python "%SCRIPTNAME%" -m check -c

    引数の定義は以下の通りです

    画像
    • mode
      動作モードを指定します。
      uploadが従来のCSVをDBにアップロードする動作です
      checkが株式分割検出です。-cを付けると補正前に確認が可能です。
      singleが日、週、月足用の単体CSVアップロードです。

    メインツールと連携して日、週、月足をDB化する

    上でチラっと紹介しましたが、singleモードは日、週、月足で出力した中間CSVをDB化するためのオプションです。
    本ツールの登場に伴い、メインの取得ツールもバージョンアップし、日足以上に対応しました。ただし、CSVは追記しない仕様なので、1ファイル1行となってしまいます。そのためDB限定としました。

    本ツールをメインツールと同じフォルダに格納することで呼出しが可能になり、日足以上をデータベースに登録することができます。

    画像

    実行するとこのようにkindがD,W,Mで登録されます。

    画像

    データの読み出し方

    次回の内容の予定なので、ここでは軽く触れる程度にしておきます。
    データベースからデータを読み出すには、SQLという指示文を作成して実行する必要があります。

    SQL構文

    以下はコンソールからログインする例です

    #まずはデータベースにログイン
    $ mysql -u root -p
    
    #データベースを指定
    mysql> use StocksDB
    #1分足を日付範囲を指定してからソートして出力
    mysql> select * from Stock_9432 WHERE kind="1M" AND "2025-4-1 0:0:0"<=datetime AND datetime<="2025-4-30 23:59:59" ORDER BY datetime ASC;
    +------+---------------------+------------+-------------+------------+-----------+----------+-----------+---------+
    | kind | datetime            | price_open | price_close | price_high | price_low | volume   | chackflag | comment |
    +------+---------------------+------------+-------------+------------+-----------+----------+-----------+---------+
    | 1M   | 2025-04-01 09:00:00 |     145.20 |      145.60 |     145.70 |    145.20 | 17978200 |         0 | NULL    |
    | 1M   | 2025-04-01 09:01:00 |     145.60 |      145.20 |     145.70 |    145.10 |  2013100 |         0 | NULL    |
    | 1M   | 2025-04-01 09:02:00 |     145.20 |      145.10 |     145.20 |    144.90 |  4746300 |         0 | NULL    |
    | 1M   | 2025-04-01 09:03:00 |     145.10 |      145.20 |     145.30 |    145.00 |  1079700 |         0 | NULL    |
    | 1M   | 2025-04-01 09:04:00 |     145.20 |      145.20 |     145.30 |    145.10 |   316100 |         0 | NULL    |
    | 1M   | 2025-04-01 09:05:00 |     145.20 |      145.30 |     145.60 |    145.10 |  3386900 |         0 | NULL    |
    | 1M   | 2025-04-01 09:06:00 |     145.30 |      145.50 |     145.50 |    145.30 |   151000 |         0 | NULL    |

    取得にはSELECTを使います
    fromの後にテーブル名を指定します。

    WHEREの後に条件を書きます。今回は1分足なので、kind="1M"と、日付の範囲を指定したいので"2025-4-1 0:0:0"<=datetime AND datetime<="2025-4-30 23:59:59"を入れています。
    これでkindが1Mかつ、4/1より新しく、4/30より古いデータという条件で抽出ができます。

    また、テーブルの順番は保証されていないので必ずソートします。ORDER BYでdatetimeで並び替えを要求し、小さい順であるASCを指定します。
    kindやdatetimeはテーブルのカラム名の事です。

    必要なカラムだけ選んだり行数制限は以下

    mysql> select datetime,volume from Stock_9432 WHERE kind="1M" AND "2025-4-1 0:0:0"<=datetime AND datetime<="2025-4-30 23:59:59" ORDER BY datetime ASC limit 10;
    +---------------------+----------+
    | datetime            | volume   |
    +---------------------+----------+
    | 2025-04-01 09:00:00 | 17978200 |
    | 2025-04-01 09:01:00 |  2013100 |
    | 2025-04-01 09:02:00 |  4746300 |
    | 2025-04-01 09:03:00 |  1079700 |
    | 2025-04-01 09:04:00 |   316100 |
    | 2025-04-01 09:05:00 |  3386900 |
    | 2025-04-01 09:06:00 |   151000 |
    | 2025-04-01 09:07:00 |   637800 |
    | 2025-04-01 09:08:00 |   767400 |
    | 2025-04-01 09:09:00 |  1005900 |
    +---------------------+----------+

    まとめ

    今回は収集したデータをDBに移行し、株式分割を全自動で適用していきました。
    少し前はAIはあっても検索と組み合わせが簡単にはできず分割関連の補正最適化は難題でしたが、Geminiのおかげでいい感じに出来上がりました。
    これでデータ前提での整合性を担保できますね。
    次回はこれらのデータをPythonに再取得して、テクニカル指標の計算や再CSV化など、柔軟に使っていこうと思います。


    配布情報

    配布URL

    以下のURLより配布しています。
    利用規約に同意の上ご利用ください。

    https://script.google.com/macros/s/AKfycbxdcr8pnazR7RbjaSICTtaNWfN7h_rjQrKlZ3h9CZpPRFzRILk1OGc8mZqKbF-NXNO9/exec?name=自動分足ダウンロードツール_DB化オプション

    配布情報

    追加のキーワードについては下記より確認可能です


     
     
    モノづくりが趣味。 "売ってないなら自分で作ればいいじゃない"をコンセプトに、機械/電気/AI/プログラム/ネットワーク 全部やります。 記事執筆はAI不使用。 ご連絡や利用規約はプロフィール記事参照。

    あなたへのおすすめ