未分類
Koyfin Chrome拡張機能とSQLiteインポート - 実装サマリー
実装日: 2025-12-12
概要
KoyfinからダウンロードしたTSVデータをGemini APIを経由せずにSQLiteデータベースに直接保存できるようにした。これによりデータ処理の高速化・コスト削減・データの一元管理を実現。
変更前 vs 変更後
アーキテクチャ比較
【変更前】
┌─────────┐ ┌─────────┐ ┌─────────────┐ ┌────────────┐ ┌─────────┐
│ Koyfin │ → │ TSV │ → │ Gemini API │ → │ TypeScript │ → │ アプリ │
│ (手動) │ │ (2ファイル)│ │ (毎回処理) │ │ (変換後) │ │ │
└─────────┘ └─────────┘ └─────────────┘ └────────────┘ └─────────┘
↓
Annual.tsv
Quarterly.tsv
(日付ディレクトリで管理)
問題点:
- 毎回Gemini APIを呼ぶ必要がある(コスト・時間)
- Annual/Quarterlyが別ファイルで管理が煩雑
- TSV→TypeScript変換が非決定論的
【変更後】
┌─────────┐ ┌─────────┐ ┌──────────┐ ┌─────────┐
│ Koyfin │ → │ TSV │ → │ SQLite │ → │ アプリ │
│ (自動) │ │ (統合) │ │ (DB) │ │ │
└─────────┘ └─────────┘ └──────────┘ └─────────┘
↓
{TICKER}_{DATE}.tsv
(koyfin-data/に自動保存)
メリット:
- Gemini API不要(高速・無料)
- 1企業1ファイルで管理が簡単
- 決定論的なパース(再現性あり)
- SQLクエリで柔軟なデータ取得
ファイル出力の比較
| 項目 | 変更前 | 変更後 |
|---|---|---|
| ファイル数/企業 | 2ファイル | 1ファイル |
| ファイル名 | {TICKER}_{DATE}_Annual.tsv{TICKER}_{DATE}_Quarterly.tsv | {TICKER}_{DATE}.tsv |
| 保存先 | ダウンロードフォルダ直下 | ダウンロード/koyfin-data/ |
| データ形式 | Annual/Quarterly別々 | Annual + Quarterly 統合 |
データ処理の比較
| 項目 | 変更前 | 変更後 |
|---|---|---|
| 変換処理 | Gemini API | Pythonパーサー |
| 処理時間 | 数秒〜数十秒/企業 | ミリ秒/企業 |
| コスト | API課金あり | 無料 |
| 再現性 | AIの解釈による | 決定論的 |
| 出力形式 | TypeScript | SQLite |
実装内容
1. 新規ファイル
| ファイル | 説明 |
|---|---|
scraper/schema.sql | SQLiteスキーマ定義(4テーブル + 2ビュー) |
scraper/tsv_to_sqlite.py | TSV→SQLiteパーサー(単一ファイル) |
scraper/import_tsv_dir.py | ディレクトリ一括インポート |
background.js | Chrome拡張のバックグラウンドスクリプト |
scraper/data/tsv/ | TSV保存用ディレクトリ |
scraper/data/koyfin.db | SQLiteデータベース |
2. 変更ファイル
| ファイル | 変更内容 |
|---|---|
manifest.json | v1.2.0→v1.3.0、background service worker追加 |
content.js | Annual/Quarterly統合、カスタムフォルダ保存対応 |
3. SQLiteスキーマ
-- 企業マスタ
companies (id, ticker, name, exchange, sector, industry, ...)
-- 株価スナップショット
quotebox (id, company_id, market_cap, forward_pe, ...)
-- 期間マスタ
financial_periods (id, period_type, period_label, fiscal_year, fiscal_quarter)
-- 財務データ本体(全セクション)
financial_data (id, company_id, period_id, data_type, section, metric_name, metric_value, fetched_at)
保存されるセクション(全9種):
- highlights
- income_statement
- balance_sheet
- cash_flow
- multiples
- enterprise_value
- profitability
- roic
- solvency
4. content.js の主要変更
// 変更前: Annual/Quarterly別々にダウンロード
startBatchDownload() {
...
this.downloadAsFile(data.annual, `${ticker}_${date}_Annual.tsv`);
this.downloadAsFile(data.quarterly, `${ticker}_${date}_Quarterly.tsv`);
}
// 変更後: 統合TSVをカスタムフォルダにダウンロード
startBatchDownload() {
...
const data = await this.collectAllTablesDataUnified();
this.downloadAsFile(data, `${ticker}_${date}.tsv`);
}
// 変更前: aタグでダウンロード(保存先指定不可)
downloadAsFile(content, filename) {
const a = document.createElement('a');
a.download = filename;
...
}
// 変更後: background script経由(カスタムフォルダに保存)
downloadAsFile(content, filename) {
chrome.runtime.sendMessage({
action: 'downloadTSV',
content: content,
filename: filename,
subfolder: 'koyfin-data'
}, ...);
}
使い方
Step 1: Chrome拡張機能で一括ダウンロード
- Koyfinでポップアップを開く
- ティッカーリストを入力
- 「一括ダウンロード」ボタンをクリック
- TSVが
ダウンロード/koyfin-data/に自動保存される
Step 2: SQLiteにインポート
cd scraper
# ディレクトリ一括インポート
uv run python import_tsv_dir.py ~/Downloads/koyfin-data
# または単一ファイル
uv run python tsv_to_sqlite.py ~/Downloads/koyfin-data/AAPL_20251212.tsv
Step 3: データ取得(SQLクエリ例)
-- 企業の最新売上を取得
SELECT c.ticker, fp.period_label, fd.metric_value as revenue
FROM financial_data fd
JOIN companies c ON fd.company_id = c.id
JOIN financial_periods fp ON fd.period_id = fp.id
WHERE fd.metric_name = 'Total Revenues'
AND fd.section = 'income_statement'
AND fd.data_type = 'annual'
ORDER BY c.ticker, fp.fiscal_year;
-- 複数企業のP/E比較
SELECT c.ticker, fd.metric_value as pe_ratio
FROM latest_financial_data fd
JOIN companies c ON fd.company_id = c.id
JOIN financial_periods fp ON fd.period_id = fp.id
WHERE fd.metric_name = 'Price / Earnings (LTM)'
AND fp.period_label = 'Current/LTM';
テスト結果
REGNのTSVファイルでテスト実行:
Company: REGN - Regeneron Pharmaceuticals, Inc.
Inserted 3817 financial data records
Records by section:
balance_sheet: 583
cash_flow: 528
enterprise_value: 187
highlights: 198
income_statement: 594
multiples: 132
profitability: 275
roic: 605
solvency: 715
ディレクトリ構成
chrome-extension-kofyin/
├── manifest.json # v1.3.0 (background追加)
├── background.js # [NEW] ダウンロードAPI
├── content.js # 統合TSV対応
├── popup.html
├── popup.js
├── content.css
├── scraper/
│ ├── schema.sql # [NEW] SQLiteスキーマ
│ ├── tsv_to_sqlite.py # [NEW] パーサー
│ ├── import_tsv_dir.py # [NEW] 一括インポート
│ ├── koyfin_scraper.py
│ └── data/
│ ├── koyfin.db # [NEW] SQLiteデータベース
│ └── tsv/ # [NEW] TSV保存先
└── memo/
└── 2025-12-12/
├── sqlite-design.md
└── implementation-summary.md # このファイル
今後の拡張
- クエリヘルパー: アプリから簡単にデータ取得できるPython/JSモジュール
- 差分更新: 既存データとの差分のみインポート
- データ検証: インポート時の整合性チェック
- 可視化: SQLiteデータをダッシュボードで表示