データ形式
概要
すべてのアーカイブデータはApache Parquet形式で保存されます。
なぜParquetか?
- 列指向: 特定カラムのみの読み込みが高速
- 圧縮効率: zstd圧縮で70-80%のサイズ削減
- スキーマ強制: データ型の一貫性を保証
- エコシステム: pandas, PyArrow, DuckDBなど多くのツールで読み込み可能
UW Flow (Unusual Whales フロー)
スキーマ
| フィールド |
型 |
説明 |
例 |
timestamp |
timestamp[us, tz=UTC] |
取得時刻 |
2025-11-28T14:30:00Z |
symbol |
string |
ティッカー |
NVDA |
strike |
float64 |
ストライク価格 |
140.0 |
expiration |
date32 |
満期日 |
2025-12-20 |
option_type |
string |
オプションタイプ |
CALL / PUT |
sentiment |
string |
センチメント |
BULLISH / BEARISH / NEUTRAL |
premium |
float64 |
プレミアム総額 ($) |
125000.0 |
volume |
int64 |
出来高 |
500 |
size |
int64 |
取引サイズ |
100 |
iv |
float64 |
IV (%) |
0.45 |
delta |
float64 |
デルタ |
0.65 |
is_unusual |
bool |
異常フラグ |
true |
et_offset |
int8 |
ETオフセット (時間) |
-5 |
サンプルデータ
import pandas as pd
df = pd.read_parquet("data/archive/uw_flow/date=2025-11-28/uw_flow_20251128.parquet")
print(df.head())
timestamp symbol strike expiration option_type sentiment premium volume size iv delta is_unusual et_offset
0 2025-11-28 14:30:00+00:00 NVDA 140.0 2025-12-20 CALL BULLISH 125000.0 500 100 0.45 0.65 True -5
1 2025-11-28 14:32:15+00:00 AAPL 185.0 2025-12-06 PUT BEARISH 85000.0 300 50 0.32 -0.40 False -5
Options (オプションチェーン)
スキーマ
| フィールド |
型 |
説明 |
例 |
timestamp |
timestamp[us, tz=UTC] |
スナップショット時刻 |
2025-11-28T14:30:00Z |
symbol |
string |
原資産ティッカー |
NVDA |
underlying_price |
float64 |
原資産価格 |
142.50 |
strike |
float64 |
ストライク価格 |
140.0 |
expiration |
date32 |
満期日 |
2025-12-20 |
option_type |
string |
オプションタイプ |
CALL / PUT |
bid |
float64 |
ビッド価格 |
5.20 |
ask |
float64 |
アスク価格 |
5.40 |
last |
float64 |
直近約定価格 |
5.30 |
volume |
int64 |
当日出来高 |
1500 |
open_interest |
int64 |
建玉 |
25000 |
iv |
float64 |
IV (%) |
0.42 |
delta |
float64 |
デルタ |
0.55 |
gamma |
float64 |
ガンマ |
0.025 |
theta |
float64 |
セータ |
-0.08 |
vega |
float64 |
ベガ |
0.15 |
et_offset |
int8 |
ETオフセット (時間) |
-5 |
読み込み例
# 特定銘柄のオプションチェーンを取得
df = pd.read_parquet(
"data/archive/options/",
filters=[
("symbol", "==", "NVDA"),
("expiration", ">=", "2025-12-01"),
]
)
# ATMオプションを抽出
atm = df[abs(df["strike"] - df["underlying_price"]) < 5]
GEX Profile (Gamma Exposure)
スキーマ
| フィールド |
型 |
説明 |
例 |
timestamp |
timestamp[us, tz=UTC] |
計算時刻 |
2025-11-28T14:30:00Z |
symbol |
string |
ティッカー |
NVDA |
gex_value |
float64 |
GEX値 ($ billions) |
2.5 |
flip_point |
float64 |
フリップポイント価格 |
138.0 |
call_wall |
float64 |
コールウォール価格 |
150.0 |
put_wall |
float64 |
プットウォール価格 |
130.0 |
regime |
string |
GEXレジーム |
POS_GAMMA_SAFE / NEG_GAMMA_RISKY |
ratio |
float64 |
GEXレシオ (当日) |
1.25 |
ratio_98d |
float64 |
98D GEXレシオ |
1.15 |
et_offset |
int8 |
ETオフセット (時間) |
-5 |
GEXレジーム判定
def classify_regime(gex_value: float, ratio_98d: float) -> str:
"""GEXレジームを判定"""
if gex_value > 0:
if ratio_98d > 1.2:
return "POS_GAMMA_SAFE"
else:
return "POS_GAMMA_NEUTRAL"
else:
if ratio_98d < 0.8:
return "NEG_GAMMA_RISKY"
else:
return "NEG_GAMMA_NEUTRAL"
Stocks 1m (1分足株価)
スキーマ
| フィールド |
型 |
説明 |
例 |
timestamp |
timestamp[us, tz=UTC] |
バー開始時刻 |
2025-11-28T14:30:00Z |
symbol |
string |
ティッカー |
NVDA |
open |
float64 |
始値 |
142.50 |
high |
float64 |
高値 |
142.80 |
low |
float64 |
安値 |
142.30 |
close |
float64 |
終値 |
142.65 |
volume |
int64 |
出来高 |
125000 |
vwap |
float64 |
VWAP |
142.55 |
et_offset |
int8 |
ETオフセット (時間) |
-5 |
取得元
- リアルタイム: Polygon WebSocket (場中)
- EOD補填: Polygon REST API
/v2/aggs/ticker/{symbol}/range/1/minute/{from}/{to}
使用例
# 1日分の1分足データを読み込み
df = pd.read_parquet("data/archive/stocks/date=2025-11-28/stocks_1m_20251128.parquet")
# VWAPを使った分析
df["vwap_deviation"] = (df["close"] - df["vwap"]) / df["vwap"] * 100
IV Rank
スキーマ
| フィールド |
型 |
説明 |
例 |
timestamp |
timestamp[us, tz=UTC] |
取得時刻 |
2025-11-28T14:00:00Z |
symbol |
string |
ティッカー |
NVDA |
iv_rank |
float64 |
IV Rank (0-100) |
45.2 |
iv_percentile |
float64 |
IV Percentile (0-100) |
52.1 |
current_iv |
float64 |
現在のIV (%) |
0.42 |
iv_high_52w |
float64 |
52週高値IV |
0.85 |
iv_low_52w |
float64 |
52週安値IV |
0.25 |
et_offset |
int8 |
ETオフセット (時間) |
-5 |
取得元
Barchart.com からスクレイピング(1日2回: JST 09:00, 21:00)
Trades (トレード履歴)
スキーマ
| フィールド |
型 |
説明 |
例 |
trade_id |
string |
トレードID |
TR-20251128-001 |
entry_time |
timestamp[us, tz=UTC] |
エントリー時刻 |
2025-11-28T14:30:00Z |
exit_time |
timestamp[us, tz=UTC] |
イグジット時刻 |
2025-11-28T18:45:00Z |
symbol |
string |
ティッカー |
NVDA |
strategy |
string |
戦略名 |
SUNACCHAN_SPEAR |
direction |
string |
方向 |
LONG / SHORT |
quantity |
int32 |
数量 |
1 |
entry_price |
float64 |
エントリー価格 |
2.50 |
exit_price |
float64 |
イグジット価格 |
4.50 |
pnl |
float64 |
損益 ($) |
200.0 |
pnl_percent |
float64 |
損益率 (%) |
80.0 |
hold_days |
int32 |
保有日数 |
0 |
exit_reason |
string |
イグジット理由 |
PROFIT_TARGET |
et_offset |
int8 |
ETオフセット (時間) |
-5 |
データ読み込みユーティリティ
日付範囲でのデータ取得
from pathlib import Path
import pandas as pd
def load_archive_data(
archive_type: str,
start_date: str,
end_date: str,
symbols: list[str] = None
) -> pd.DataFrame:
"""
アーカイブデータを日付範囲で読み込み
Args:
archive_type: "uw_flow", "options", "gex", "stocks", "iv_rank", "trades"
start_date: 開始日 (YYYY-MM-DD)
end_date: 終了日 (YYYY-MM-DD)
symbols: フィルタする銘柄リスト (Noneで全銘柄)
Returns:
pd.DataFrame: 結合されたデータ
"""
base_path = Path("data/archive") / archive_type
filters = []
if symbols:
filters.append(("symbol", "in", symbols))
df = pd.read_parquet(
base_path,
filters=filters
)
# 日付でフィルタ
df = df[
(df["timestamp"].dt.date >= pd.to_datetime(start_date).date()) &
(df["timestamp"].dt.date <= pd.to_datetime(end_date).date())
]
return df.sort_values("timestamp")
DuckDBでのクエリ
import duckdb
# 高速なSQLクエリ
result = duckdb.query("""
SELECT
symbol,
DATE_TRUNC('hour', timestamp) as hour,
AVG(premium) as avg_premium,
SUM(volume) as total_volume
FROM 'data/archive/uw_flow/**/*.parquet'
WHERE symbol = 'NVDA'
AND sentiment = 'BULLISH'
GROUP BY symbol, hour
ORDER BY hour
""").df()