FINRA 심볼(BRK/B, HPX/U, WARR/WS 등)을 Alpaca에 그대로 전송하면
URL에 %2F가 포함되어 400 Bad Request 발생.
alpaca_batch = [_finra_to_alpaca(s) for s in batch] 로 사전 변환.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
날짜별 전체 심볼의 공매도량 + 조정종가 조인 결과 반환.
pit_universe_membership ⋈ alpaca_price_data(interval='1d') 조인.
생존편향-0: 상폐 종목도 그날 거래됐으면 포함.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
직접 DB/서비스에 접근하는 스크립트 패턴을 REST API 패턴으로 교체:
- 삭제: scripts/backfill_finra_2020_gap.py (기존 POST /finra/admin/ingest으로 충분)
- 삭제: scripts/backfill_alpaca_daily_pit.py
- 삭제: scripts/export_pit_panel.py (외부 DB 연결으로 대체)
- 추가: POST /api/v1/alpaca/admin/backfill-pit
BackgroundTasks 패턴, FINRA 전체 PIT 심볼 백필, adjustment=all
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1. materialize_features identity-map 버그 수정
- upsert commit 후 populate_existing=True로 재SELECT
- resolve_entity와 동일 패턴 (SQLAlchemy async stale cache)
2. @with_cache 조건부 TTL — null 응답 캐시 단축
- wiki.views=null → TTL 300s (5분)
- 완전한 응답 → TTL 3600s (1시간)
- 기존: null 응답이 1시간 캐시되어 재수집 영구 차단
3. 재실체화 조건 확장: wiki_zscore_20d is None도 재트리거
- wiki_views는 있지만 lookback 부족으로 zscore만 null인 케이스 처리
4. POST /admin/entity/{ticker}/override 엔드포인트 추가
- wiki_title 수동 지정 + is_manual_override=True 설정
- CSCO→Cisco, DKNG→DraftKings 잘못된 매핑 수정용
5. entity_resolver: 소송 페이지 패턴 억제
- "X v. Y" 형식 제목 score=0.05 (예: FSF v. Cisco Systems)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3 months ago
14 changed files with 905 additions and 150 deletions
if"rate limit"inerror"too many requests"inerror"429"inerror"ratelimit"inerr:
raiseHTTPException(status_code=429,detail={"error_type":"RATE_LIMIT_ERROR","message":"Yahoo Finance rate limit. Retry after a short delay."},headers={"Retry-After":"30"})
if"rate limit"inerror"too many requests"inerror"429"inerror"ratelimit"inerr:
raiseHTTPException(status_code=429,detail={"error_type":"RATE_LIMIT_ERROR","message":"Yahoo Finance rate limit. Retry after a short delay."},headers={"Retry-After":"30"})
# eng = create_engine('postgresql+psycopg2://stockoracle:stockoracle2024@localhost:15433/stock_oracle')
# df = pd.read_sql('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 BETWEEN \'2018-08-01\' AND NOW()', eng)
# df.to_parquet('pit_panel.parquet', index=False)
# print(df.shape)
# "
```
# 2단계: 2026년 공백 구간
curl -X POST "http://localhost:18001/api/v1/finra/admin/ingest?start_date=2026-01-02&end_date=2026-02-09"
### PIT 뷰 (DB 직접 쿼리 시)
# 3단계 (선택): 2024년
curl -X POST "http://localhost:18001/api/v1/finra/admin/ingest?start_date=2024-01-02&end_date=2024-12-31"
```sql
-- 날짜별 PIT 유니버스 (상폐 종목 포함)
SELECT DISTINCT symbol FROM pit_universe_membership WHERE d = '2023-03-09';
-- 공매도비율 × 가격 패널 (생존편향-0, backfill_alpaca_daily_pit.py 실행 후)
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'