こんにちは、フィンテック開発の勉強記録を綴っています。今回は貴金属相場のデータパイプライン制作実習で学んだ、過去ローソクとリアルタイムティックの連結手法についてまとめました。プログラミング初心者でも分かりやすいよう、実際に自分がハマった失敗談を交えながら書いていきます。
開発に必要な 2 つのデータと最初の失敗
貴金属の自動売買ツールや相場監視システムを作るとき、必要なデータは大きく 2 種類に分かれます。 1 つ目は REST API から取得する過去ローソクデータ。長期のトレンド分析や、自作戦略のバックテストに欠かせません。 2 つ目は WebSocket 経由で届くリアルタイム価格。リアルタイムで相場画面を更新し、瞬間的な値動きを捉えるために使います。
最初は単純に「過去データの後ろにリアルタイムデータを追加するだけで大丈夫」と考えて実装したのですが、動かしてみるとたくさんの不具合が出てきました。 同じ時間帯に重複したローソクが生成されたり、現在進行中の時間足の高値・安値が更新されなかったり、時系列データに空白の区間ができてしまったり…。 ログを一つずつ確認して原因を探った結果、REST の事前集計ローソクと生のティックデータは単純につなげてはいけないこと、タイムスタンプの統一やローソクの完了状態を分けた処理が必要だと分かりました。
REST と WebSocket、データの根本的な違い
2 つの API から出力されるデータは性質が全く異なるため、連結時にトラブルが起きやすいです。 REST API は 1 分足・5 分足・1 時間足といった単位ごとに事前集計された、完成済みのローソクを返します。時間の区切りが確定しており、始値・高値・安値・終値の数値は変動しないので、システム起動時の過去データ読み込みに最適です。
対して WebSocket は未加工のティックデータを次々配信します。1 件のデータは一瞬の価格だけを記録しているため、そのままでは 1 本のローソクとして保存できません。 例えば 10 時 30 分の 1 分足がすでに存在する状態で、10 時 30 分 45 秒の価格更新が届いた場合、新しいローソクを作成するのではなく、既存の 10 時 30 分足の高値・安値・終値を上書き更新するロジックが必要になります。
表格
| データ取得元 | 主な使用目的 | データの特徴 |
|---|---|---|
| REST API | 過去相場一括読み込み、バックテスト | 時間区間が閉じている、事前集計済み、数値が固定 |
| WebSocket | リアルタイム相場更新、動的チャート描画 | 常時配信、瞬間価格のみ、後から集計処理が必須 |
データ連結で失敗しない 3 つの統一ルール
REST と WebSocket の時間フォーマットやデータ粒度がバラバラなまま DB に登録すると、3 つの典型的なエラーが発生します。 ・タイムスタンプの形式が違うことで時間ズレが生じ、ローソクの区切りが崩れる ・完了済みローソクと更新中ローソクを同じ処理で登録し、同一時間足が重複する ・届いたティックをそのまま新規保存し、進行中のローソクの値が更新されない
これらを回避するため、自分の開発環境では以下の 3 つのルールを定めています。
- REST と WebSocket 両方のタイムスタンプを同じフォーマットに変換してから計算・DB 登録を行う
- リアルタイムティックの集計単位は、過去ローソクの時間単位と完全に統一する
- すべてのローソクに「完了済み」「更新中」の状態タグを付け、それぞれ書き込み・更新ロジックを分ける
具体的な例を挙げると、REST で取得した過去データが 10 時 30 分までの完了 1 分足だった場合、WebSocket から届く 10 時 30 分内のティックはすべて更新中の同じローソクに反映。時刻が 10 時 31 分に移行したタイミングで、新しいローソクを作成する流れです。
クラウド環境で使える標準的なデータ処理フロー
私が実際に運用している、過去データ初期化とリアルタイム増分更新を一貫して行う ETL フローを紹介します。
- REST API から貴金属の過去ローソクを一括取得
- 2 種類の API のタイムスタンプを統一フォーマットに変換
- 完了済みの過去ローソクを時系列 DB に登録し、最後のローソクの時間タグを一時保存
- WebSocket の長時間接続を確立し、次々とティックデータを受信
- 統一した時刻情報をもとに、各ティックが属する時間足を判定
- 時間足が更新中の場合は高値・安値・終値を更新、時間区間が終了したら新規ローソクを登録
この手順なら、ティックが届くたびに過去データを全て再読み込みする必要がなく、サーバーのリソース消費を抑えられます。長期の過去データから最新のリアルタイム価格まで、空白や重複のない連続した時系列データを作成できる点がメリットです。
リアルタイムストリームの実装
オフラインの過去データ洗浄とオンラインのリアルタイム配信で時刻変換や時間足判定のロジックを分けてしまうと、2 つのデータを結合した際にローソクに不自然な隙間が生まれます。 私の環境ではリアルタイムティックの取得に AllTick API の WebSocket 接続を採用し、過去データ処理とまったく同じ時刻正規化関数を共有することで、オンライン・オフラインのデータ基準を統一しています。
実装のポイントとして、ティックから生成したローソクを DB に登録する前に、必ず「完了済み / 更新中」の状態タグを付けましょう。後からバックテストやチャート描画を行う際、必要な時間帯のデータだけを簡単に抽出でき、重複した時刻計算を省いて処理速度を上げられます。
長期運用で見落としがちな安定化対策
貴金属の相場パイプラインを長く動かしている中で、時系列の連続性を損なう 3 つの細かいポイントをまとめました。開発時のデバッグに役立ててください。
-
WebSocket 切断時の欠損データ補完処理 接続が途切れて再接続したタイミングで、切断していた時間のギャップを計算し、REST API から欠けている相場データを補完する処理を入れます。これがないとチャートに空白ができてしまいます。
-
重複ティックのフィルタリング リアルタイム配信で同じ価格データが複数回送信されるケースがあるため、タイムスタンプをキーに重複データを削除するロジックを追加。ローソクの無駄な上書きを防ぎます。
-
更新中ローソクの分離保存 更新中の未完了ローソクを、完了済みの過去ローソクと同じ一括登録処理で扱うと、DB の主キー衝突エラーが発生します。書き込み先や処理フローを分けて管理しましょう。
最後にまとめ
REST 過去ローソクと WebSocket リアルタイムティックを連結する作業の本質は、随時更新可能な貴金属時系列データの基盤を作ることです。REST は確定した長期過去データを提供する静的な土台、WebSocket は最新の価格変動を補完する動的なレイヤーと役割が分かれています。
相場データパイプラインの信頼性は、単なる API 呼び出しの実装だけでは決まりません。全システムで統一した時刻ルール、2 種類のローソク状態の管理、2 つの API をまたぐ標準的な連結フローがカギとなります。 今回紹介した処理ルールに沿ってデータパイプラインを構築すれば、重複や空白のない綺麗な貴金属相場データセットが完成し、相場監視チャートの描画、定量戦略のバックテスト、ファクターモデルの学習といった後続作業に安定したデータを供給できます。