|
|
"""add pit_universe_membership view
|
|
|
|
|
|
Revision ID: q8h9i0j1k2l3
|
|
|
Revises: p7g8h9i0j1k2
|
|
|
Create Date: 2026-05-30
|
|
|
|
|
|
PIT(Point-in-Time) 유니버스 멤버십 뷰.
|
|
|
|
|
|
finra_short_volume에서 (date, symbol)을 그대로 노출하는 뷰.
|
|
|
각 날짜에 실제 거래되던 종목 집합 = PIT 멤버십.
|
|
|
|
|
|
생존편향-0 달성 근거:
|
|
|
- finra_short_volume은 2018-08-01 ~ 현재, 22,722개 심볼 보유
|
|
|
- 그 중 16,143개는 현 활성 유니버스(9,635)에 없는 상폐/합병/과거 종목
|
|
|
- SIVB(2023-03-09), SBNY(2023-03-10), FRC(2023-04-28), TWTR(2022-10-27) 등
|
|
|
실제 상폐일에 정확히 끊김 → 생존편향 없이 PIT 멤버십 표현
|
|
|
|
|
|
사용 예:
|
|
|
-- 특정 날짜에 거래된 종목 집합 (PIT 유니버스)
|
|
|
SELECT DISTINCT symbol
|
|
|
FROM pit_universe_membership
|
|
|
WHERE d = '2023-03-09'
|
|
|
ORDER BY symbol;
|
|
|
|
|
|
-- 공매도비율 × PIT 멤버십 (생존편향-0 횡단면)
|
|
|
SELECT p.d, p.symbol, p.short_ratio, a.close
|
|
|
FROM pit_universe_membership p
|
|
|
LEFT JOIN alpaca_price_data a
|
|
|
ON a.ticker = p.symbol AND a.date::date = p.d AND a.interval = '1d'
|
|
|
WHERE p.d = '2023-03-09'
|
|
|
ORDER BY p.short_ratio;
|
|
|
|
|
|
한계:
|
|
|
- 티커 재활용: BBBY(2023-05 파산 → 2025-08 다른 엔티티 재사용) 등
|
|
|
심볼 기준 PIT는 상폐 경계에서 두 회사를 혼동할 수 있음.
|
|
|
엄밀 해결은 CUSIP/PERMNO(유료) 매핑 필요.
|
|
|
- 2020-04-01 ~ 2020-10-31 데이터 결손 (COVID 갭).
|
|
|
backfill_finra_2020_gap.py 실행 후 해소 가능.
|
|
|
- NMS 슈퍼셋: ETF/ADR/워런트(/U, /WS) 포함.
|
|
|
분석단에서 심볼 패턴 필터 권장.
|
|
|
"""
|
|
|
from typing import Sequence, Union
|
|
|
|
|
|
from alembic import op
|
|
|
|
|
|
revision: str = "q8h9i0j1k2l3"
|
|
|
down_revision: Union[str, Sequence[str], None] = "p7g8h9i0j1k2"
|
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
|
|
|
def upgrade() -> None:
|
|
|
# CREATE OR REPLACE VIEW: idempotent, safe to re-run
|
|
|
# 성능: idx_finra_date (date), idx_finra_symbol_date (symbol, date) 인덱스를
|
|
|
# Postgres가 베이스 테이블에서 자동 활용하므로 별도 뷰 인덱스 불필요
|
|
|
op.execute("""
|
|
|
CREATE OR REPLACE VIEW pit_universe_membership AS
|
|
|
SELECT
|
|
|
date::date AS d,
|
|
|
symbol,
|
|
|
total_volume,
|
|
|
short_volume,
|
|
|
short_exempt_volume,
|
|
|
short_ratio,
|
|
|
market
|
|
|
FROM finra_short_volume
|
|
|
""")
|
|
|
|
|
|
|
|
|
def downgrade() -> None:
|
|
|
op.execute("DROP VIEW IF EXISTS pit_universe_membership")
|