はじめに
こんにちは。
GadgetStreemでは現在、ガジェット価格の上昇圧力を一つの数字で確認できる独自指数、
GPI(Gadget Pressure Index/ガジェット価格圧力指数)

を開発しています。
GPI開発日誌 Vol.1では、Docker、PostgreSQL、FastAPI、GitHub Actionsなど、GPIを継続的に開発するための基盤を構築しました。
Vol.2では、GPIへ最初に取り込む実データとしてドル円を選びました。
さらに、データ取得元としてFederal Reserve Boardが公開する
H.10 Foreign Exchange Rates
を採用し、
- どの値を取得するのか
- 欠損値をどう扱うのか
- 同じデータの重複をどう防ぐのか
- 訂正された値をどう保存するのか
といったCollectorの設計を行いました。
そして今回、設計だけだったUSD/JPY Collectorを実際に実装しました。
GadgetStreem Intelligenceのデータベースへ、初めて本物の市場データが入ります。
USD/JPY Collectorが完成
今回実装したUSD/JPY Collectorは、Federal Reserve Boardが公開しているH.10の為替データから、日本円の系列を取得するプログラムです。
H.10では、日本円の為替レートを
1米ドル当たりの日本円
として掲載しています。
二国間為替レートの履歴データは、通常、前営業週の金曜日までの値が米国東部時間の月曜日16時15分に更新されます。
例えば、
162.43
という値なら、
1米ドル=162.43円
という意味です。
H.10の最新リリースでも、為替レートは原則として「1米ドル当たりの各国通貨単位」という形式で掲載されています。
Collectorの処理フロー
USD/JPY Collectorは、次の順番で動作します。
Federal Reserve H.10
↓
公式データを取得
↓
日本円の系列を抽出
↓
日付・単位・値を検証
↓
欠損値を除外
↓
重複・訂正の有無を確認
↓
PostgreSQLへ保存
数字をそのままコピーするのではなく、
GPIで継続利用できる正しい観測データか
を確認してから保存します。
日本円の系列だけを抽出する
H.10には日本円だけでなく、
- ユーロ
- 英ポンド
- カナダドル
- スイスフラン
- オーストラリアドル
など、複数の通貨データが含まれます。
GPI Ver.0.1で必要なのはUSD/JPYだけなので、Collectorでは日本円を表す系列だけを抽出します。
この処理を入れることで、別通貨の値を誤ってドル円として保存することを防ぎます。
XMLやデータ形式の違いを吸収
外部データは、GadgetStreem Intelligenceのデータベースと同じ形式で提供されるわけではありません。
そのためCollectorでは、
- 提供元独自の系列ID
- 日付形式
- XML内の階層構造
- 数値を示す属性
- 欠損値の表記
などを読み取り、GSI内部の共通形式へ変換します。
例えば、外部データが次のような構造だった場合、
観測日:2026-07-17
観測値:162.43
系列:日本円
内部では、
indicator:usd_jpy
observed_at:2026-07-17
value:162.43000000
unit:JPY_PER_USD
source:Federal Reserve H.10
という共通形式で扱います。
この共通形式があることで、将来追加するDRAM、NAND、GPU、海上運賃も、同じ仕組みで保存できるようになります。
欠損値は保存しない
為替市場が休場している日や、提供元側で値を確定できない場合、観測値が存在しないことがあります。
H.10では、利用可能なデータがない場合に、数値ではない欠損表現が含まれる場合があります。
Collectorは、これを無理に
0円
として保存しません。
0円として保存してしまうと、
- 為替が突然0円になった
- 前日比がほぼマイナス100%
- GPIのドル円スコアが急落
といった、あり得ない計算結果につながるからです。
そのため、
- 欠損値
- 空欄
- 数値へ変換できない文字列
- 必須情報が不足している観測値
は、DBへ保存せず安全にスキップします。
なぜ小数をFloatで保存しないのか
為替データには小数が含まれます。
一般的なプログラミング言語のfloatは高速ですが、内部では2進数として近似されるため、十進数を完全に表現できない場合があります。
GadgetStreem Intelligenceでは、市場データを扱うため、USD/JPYの値を
Decimal
として処理します。
データベース側でも、
NUMERIC
型を使い、小数を正確に保存します。
GPIの計算を何度実行しても、環境によって微妙に数値が変わることを防ぐためです。
初めてPostgreSQLへ市場データを保存
Collectorによって取得・検証されたUSD/JPYは、Sprint 1で構築したPostgreSQLへ保存されます。
主に使用するテーブルは次の3つです。
data_sources
どの提供元から取得したデータなのかを管理します。
今回であれば、
Federal Reserve Board
H.10 Foreign Exchange Rates
などの情報が登録されます。
indicators
どの指標に属する観測値なのかを管理します。
今回追加されるのは、
usd_jpy
です。
observations
実際の観測値を保存します。
主な内容は、
- 観測日
- 公表日時
- 取得日時
- 数値
- 単位
- Revision
- データ品質
- 取得元
- Methodologyバージョン
です。
つまり、単に
162.43円
だけを保存するのではありません。
いつの値なのか
どこから取得したのか
いつ取得したのか
何回目のRevisionなのか
まで一緒に記録します。
同じ処理を何度実行しても重複しない
Collectorは将来的に、自動で繰り返し実行されます。
もし実行するたびに同じ観測値を追加してしまうと、
2026-07-17 162.43
2026-07-17 162.43
2026-07-17 162.43
と、同じデータが無限に増えてしまいます。
そこでCollectorでは、
- 同じ提供元
- 同じ指標
- 同じ観測日
- 同じ値
がすでに保存されている場合、新しい行を追加しません。
実行結果は、例えば次のような区分で集計できます。
inserted
unchanged
revised
skipped
failed
inserted:新しく保存したデータunchanged:すでに同じ値が存在revised:提供元で値が変更されたskipped:欠損などで保存対象外failed:通信・解析・DB処理に失敗
同じコマンドを繰り返しても同じ結果になる性質を、
冪等性(べきとうせい)
と呼びます。
データ収集を自動化するうえで欠かせない仕組みです。
訂正値は上書きせずRevisionとして保存
Federal Reserveなどの公式データ提供元が、後日、過去の値を訂正する可能性もあります。
例えば、最初に保存された値が
Revision 0:162.43
だったものの、後日公式データが
162.41
へ変更されたとします。
この場合、以前の値を削除したり、無言で書き換えたりはしません。
Revision 0:162.43
Revision 1:162.41
として、両方を保存します。
現在のGPI計算では最新Revisionを使いながら、
- 当初どの値が公表されていたのか
- いつ訂正されたのか
- 過去のGPIにどの程度影響したのか
を後から確認できるようにします。
元データを無制限に保存しない
GadgetStreem Intelligenceでは、データの再現性を重視しています。
しかし、外部データを取得できたからといって、そのデータファイル全体を自由に保存・再配布できるとは限りません。
そこで今回のCollectorでは、原則として元データそのものを無制限に保管せず、
- 取得元
- 取得日時
- 系列ID
- 観測値
- SHA-256ハッシュ
- 解析バージョン
などの来歴情報を保存します。
このハッシュ値を使えば、
取得したデータが以前と同じ内容だったか
を確認できます。
データの透明性と、提供元の利用条件の両方を考慮した設計です。
コマンドから手動実行できるようにした
開発初期では、いきなり定期実行を始めません。
まずはCLIコマンドから、開発者が手動で実行できる形にしています。
概念的には、次のようなコマンドです。
gsi collect-usd-jpy
実行すると、
- H.10へアクセス
- データを取得
- 日本円系列を解析
- 検証
- PostgreSQLへ保存
- 処理結果を表示
という一連の処理が動きます。
手動実行で安定性を確認した後、スケジューラーによる自動取得へ移行する予定です。
APIアクセス時には外部データを取りに行かない
GadgetStreem Intelligenceでは、Webサイトへ読者がアクセスするたびにFederal Reserveへ接続する設計にはしていません。
処理は明確に分離します。
Collector
↓
事前にデータを取得
↓
PostgreSQLへ保存
↓
APIはDB内の検証済みデータを返す
この方式なら、
- 外部データ提供元の障害
- 通信の遅延
- アクセス集中
- API制限
- XML形式の変更
が発生しても、公開ページ全体がすぐ表示不能になることを防げます。
テストで確認すること
USD/JPY Collectorでは、正常に取得できるケースだけでなく、失敗するケースもテストします。
Unit Test
- 正しい日本円系列を抽出できる
- 欠損値を除外できる
- 不正な日付を拒否できる
- 数値をDecimalへ変換できる
- 別通貨を誤って取得しない
- 同じデータを重複させない
Integration Test
- PostgreSQLへ観測値を保存できる
- 再実行時に重複しない
- 訂正値を新Revisionとして保存できる
- 最新Revisionを取得できる
- トランザクション失敗時に中途半端なデータを残さない
さらにGitHub Actionsでテストを自動実行し、すべて成功しなければmainへマージできない運用を続けます。
GPI全体では、まだ30%が完成したわけではない
ドル円には暫定30%の重みを設定しています。
しかし、USD/JPY Collectorが完成したからといって、
GPIの30%が完成した
と単純には言えません。
まだ必要なものは、
- どの期間のドル円を使うのか
- 現在値と変化率のどちらを見るのか
- 0~100へどう変換するのか
- 欠損時にどうするのか
- 他の指標とどの時点で揃えるのか
といった計算ルールです。
今回完成したのは、
信頼できるドル円データを、継続的に蓄積する入口
です。
GPIの数値へ変換する処理は、すべての構成要素が揃った後にCalculation Engineで実装します。
今回の開発で得られたこと
USD/JPY Collectorの実装によって、GadgetStreem Intelligenceは初めて、
外部の公式データ
↓
Collector
↓
検証
↓
PostgreSQL
という一連のデータパイプラインを持つことになります。
この流れは、今後追加する
- DRAM
- NAND
- GPU需給
- 海上運賃
でも共通して使用できます。
つまり今回作ったのは、単なるドル円専用プログラムではありません。
今後すべての市場データを取り込むための最初の実装モデル
でもあります。
次のVol.4で紹介すること
次回のGPI開発日誌 Vol.4では、Collectorを「一度動くプログラム」から「継続運用できるシステム」へ進化させます。
主なテーマは、
- データ取得履歴
- 最終成功日時
- エラー内容
- データ鮮度
- 欠損の検知
- 自動実行
- 障害時の通知
- 再試行ルール
です。
数字を一度取得できるだけでは、指数を毎週公開し続けることはできません。
Collectorをどう止めずに運用するのか
を取り上げる予定です。
まとめ
GPI開発日誌 Vol.2では、ドル円の取得元とCollectorの設計を決定しました。
今回のVol.3では、その設計を実装し、
Federal Reserve H.10のUSD/JPYをPostgreSQLへ保存する仕組み
を作りました。
これによりGadgetStreem Intelligenceは、
- 公式データを取得する
- 正しい系列を抽出する
- 欠損を除外する
- 数値を正確に保存する
- 重複を防ぐ
- 訂正履歴を残す
- データの出どころを追跡する
という、指数開発に欠かせないデータパイプラインを持ち始めます。
まだGPIの数値そのものは完成していません。
しかし、今回からGPIは、
設計図だけのプロジェクトではなく、本物の市場データを蓄積するシステム
へ変わりました。
次は、継続的なデータ収集と品質監視の仕組みを整えます。
GadgetStreem Intelligenceが実際の指数として動き出すまで、引き続き開発過程を公開していきます。
※GPIは現在開発中の実験的な市場分析指標です。
個別製品の将来価格、値上げ、値下げ、在庫状況、購入利益を保証するものではありません。
また、投資判断を目的とした金融指標ではありません。




コメント