diff --git a/dev/phase5_deliverables/README.md b/dev/phase5_deliverables/README.md new file mode 100644 index 0000000..00170a3 --- /dev/null +++ b/dev/phase5_deliverables/README.md @@ -0,0 +1,44 @@ +# Phase 5 Deliverables — Attention Overlay Development Docs + +## 목적 +Phase 5는 Phase 0~4에서 구축한 **공식 이벤트 + 가격 확인 기반 코어 전략** 위에, 무료 attention/crowding 데이터를 **보조 신호(overlay)** 로 추가하는 단계입니다. + +핵심 원칙: +- 코어 신호 없이 overlay만으로 진입하지 않는다. +- overlay는 **후보 우선순위 조정, 보유기간 조절, 포지션 추가/축소 보조** 에만 사용한다. +- 무료 데이터 정책을 유지한다. +- 소스별 약관/쿼터/지연/신뢰도 차이를 명시적으로 반영한다. + +## 포함 문서 +- `attention_overlay_architecture.md` +- `source_integration_specs.md` +- `feature_design_and_entity_resolution.md` +- `overlay_scoring_policy.md` +- `implementation_plan.md` +- `testing_checklist.md` +- `operations_and_monitoring.md` +- `youtube_channel_registry_spec.md` +- `overlay_feature_record.schema.json` +- `overlay_config.schema.json` + +## 범위 +### 포함 +- Yahoo Finance RSS headline burst +- YouTube whitelist channel monitoring +- Wikimedia pageview shock +- Google Trends experimental theme heat +- FINRA crowding feature integration (Phase 2 데이터 재사용) +- attention overlay score 산출 +- backtester/live trader에 overlay score 연결 + +### 제외 +- X/Twitter API 연동 +- Reddit 라이브 핵심 의존성화 +- Stocktwits 신규 핵심 의존성화 +- 실시간 초단타 소셜 트리거 매매 +- 자막 전체 전수 수집 기반 파이프라인 + +## 성공 기준 +- overlay 미사용 대비 후보 정렬 품질이 개선되어야 한다. +- overlay 추가 후 코어 전략 수익성이 악화되더라도 원인을 attribution 가능해야 한다. +- overlay 장애 발생 시 자동으로 core-only 모드로 degrade 되어야 한다. diff --git a/dev/phase5_deliverables/attention_overlay_architecture.md b/dev/phase5_deliverables/attention_overlay_architecture.md new file mode 100644 index 0000000..d6b8113 --- /dev/null +++ b/dev/phase5_deliverables/attention_overlay_architecture.md @@ -0,0 +1,74 @@ +# Attention Overlay Architecture + +## 목표 +공식 문서와 가격 반응으로 생성된 `trade_candidates` 에 대해, 추가적인 **리테일 관심도 / 미디어 확산 / crowding** 신호를 계산해 `overlay_score` 를 부여한다. + +## 설계 원칙 +1. Overlay는 **후행 확인 신호** 다. +2. Overlay 데이터는 소스별 신뢰도 가중치를 갖는다. +3. Overlay는 결측이 많을 수 있으므로 sparse-friendly 하게 설계한다. +4. Overlay는 독립 장애 도메인으로 분리한다. +5. Overlay feature는 모두 타임스탬프와 source provenance를 남긴다. + +## 상위 구조 +```text +source adapters + ├── yahoo_rss_adapter + ├── youtube_overlay_adapter + ├── wikimedia_adapter + ├── google_trends_adapter (experimental) + └── finra_overlay_loader + +normalized events + ├── headline_mentions + ├── video_mentions + ├── pageview_timeseries + ├── trend_topic_timeseries + └── crowding_metrics + +entity resolution layer + ├── symbol ↔ company aliases + ├── symbol ↔ wikipedia page + ├── symbol ↔ youtube mention matcher + └── symbol ↔ trend topic map + +feature builder + ├── headline burst + ├── publisher breadth + ├── youtube influence score + ├── pageview shock + ├── theme heat + └── crowding stress + +overlay scorer + ├── overlay_score + ├── overlay_confidence + ├── hold_extension_hint + └── add_on_eligibility +``` + +## 데이터 흐름 +1. Phase 2/3에서 `trade_candidates` 생성. +2. overlay adapters가 소스별 raw 수집. +3. entity resolution이 종목 단위로 정규화. +4. feature builder가 observation window 기준 feature 생성. +5. overlay scorer가 각 후보에 score 부여. +6. backtester/live trader가 score를 사용해 ranking, sizing, holding rule 조정. + +## 장애 격리 +- overlay adapter 실패는 core signal 생성에 영향 주지 않는다. +- 특정 소스 실패 시 나머지 소스로 점수 계산 가능해야 한다. +- 모든 overlay feature가 누락되면 `overlay_mode=disabled` 로 자동 강등한다. + +## 추천 배치 순서 +- T day 18:30 ET: Yahoo RSS / FINRA 수집 완료 +- T day 20:00 ET: Wikimedia/YouTube/Trends 업데이트 +- T day 20:30 ET: overlay feature build +- T day 21:00 ET: candidate rerank + +## 사용 방식 +- `candidate_rank_score = core_score * 0.85 + overlay_score * 0.15` +- 또는 core score bucket 내 tie-breaker +- 또는 holding period extension/trim decision only + +v1 권장: **tie-breaker + hold adjustment only** diff --git a/dev/phase5_deliverables/feature_design_and_entity_resolution.md b/dev/phase5_deliverables/feature_design_and_entity_resolution.md new file mode 100644 index 0000000..471ef22 --- /dev/null +++ b/dev/phase5_deliverables/feature_design_and_entity_resolution.md @@ -0,0 +1,79 @@ +# Feature Design and Entity Resolution + +## 목표 +이종 소스의 noisy mentions를 종목 단위 overlay feature로 안정적으로 변환한다. + +## Entity Resolution 원칙 +### symbol matching 단계 +1. direct ticker token match +2. company canonical name match +3. approved alias match +4. fuzzy match (낮은 신뢰도, manual review 후보) + +### 금지 규칙 +- 1글자/2글자 일반 단어 ticker를 무조건 매칭하지 않는다. +- 맥락 없는 company substring match 금지. +- YouTube 제목에 `AI`, `App`, `ON`, `IT` 같은 일반 토큰을 티커로 해석하지 않는다. + +## reference tables +- `symbol_master` +- `company_aliases` +- `youtube_channel_registry` +- `wiki_page_map` +- `theme_topic_map` + +## Feature group 정의 +### A. Headline Burst +- 최근 6h/24h 헤드라인 수 +- publisher breadth +- deduped article count +- positive/negative heuristic headline count + +### B. YouTube Influence +- weighted views by channel weight +- unique channels mentioning symbol +- upload velocity +- comments-per-view ratio +- mention freshness decay + +### C. Wiki Attention +- 1d/3d/7d pageview changes +- rolling z-score +- percentile rank vs last 90d + +### D. Theme Heat +- mapped theme trend value +- acceleration +- saturation regime + +### E. Crowding +- short volume anomaly +- recent crowding persistence + +## Normalization +- 모든 source-local metric은 source별 robust z-score로 정규화 +- winsorization 적용 (1% / 99%) +- sparse source는 missing 그대로 두고 source confidence penalty 적용 + +## Time windows +- 6h burst: event propagation detection +- 24h burst: overnight attention +- 3d persistence: continuation support +- 7d trend: theme regime only + +## Leakage 방지 +- entry decision 시점 이후 수집 데이터 사용 금지 +- snapshot time 명시 +- re-run 시 동일 cutoff 적용 + +## 출력 예시 필드 +- symbol +- as_of_ts +- headline_burst_z +- youtube_influence_z +- wiki_attention_z +- theme_heat_z +- crowding_stress_z +- overlay_score +- overlay_confidence +- source_presence_mask diff --git a/dev/phase5_deliverables/implementation_plan.md b/dev/phase5_deliverables/implementation_plan.md new file mode 100644 index 0000000..d0ea6e4 --- /dev/null +++ b/dev/phase5_deliverables/implementation_plan.md @@ -0,0 +1,66 @@ +# Phase 5 Implementation Plan + +## 목표 +attention overlay 레이어를 구현하여 backtester와 live pipeline에 연결한다. + +## 작업 순서 +### Step 1. registry tables 구축 +- youtube_channel_registry +- company_aliases 보강 +- wiki_page_map +- theme_topic_map + +### Step 2. raw adapters 구현 +- yahoo_rss_adapter +- youtube_overlay_adapter +- wikimedia_adapter +- google_trends_adapter (feature flagged) + +### Step 3. normalization pipeline 구현 +- headline normalization +- video normalization +- pageview normalization +- trend timeseries normalization +- entity resolution jobs + +### Step 4. overlay feature builder 구현 +- per-source feature calculators +- missing data handling +- source confidence computation +- overlay_feature_record 생성 + +### Step 5. overlay scorer 구현 +- weighted scoring +- confidence adjustment +- band assignment +- recommendation flags 생성 + +### Step 6. backtester integration +- overlay on/off config +- tie-breaker mode +- weighted rank mode +- hold extension mode +- add-on eligibility mode + +### Step 7. live pipeline integration +- nightly overlay jobs +- candidate rerank job +- degraded mode handling +- source freshness checks + +## 구현 우선순위 +1. Yahoo RSS +2. Wikimedia +3. YouTube whitelist +4. FINRA overlay join +5. Google Trends experimental + +## 완료 조건 +- overlay feature record가 후보 종목에 대해 안정적으로 생성된다. +- backtester에서 overlay on/off ablation이 가능하다. +- source failure가 전체 파이프라인 실패로 이어지지 않는다. + +## non-goals +- high-frequency social trading +- full video transcript NLP pipeline +- real-time intraday social scraping diff --git a/dev/phase5_deliverables/operations_and_monitoring.md b/dev/phase5_deliverables/operations_and_monitoring.md new file mode 100644 index 0000000..2de9fa9 --- /dev/null +++ b/dev/phase5_deliverables/operations_and_monitoring.md @@ -0,0 +1,68 @@ +# Operations and Monitoring + +## 모니터링 목표 +- source freshness +- quota consumption +- entity resolution precision drift +- overlay coverage ratio +- overlay contribution stability + +## 핵심 메트릭 +### source health +- `overlay_source_success_rate` +- `overlay_source_last_success_ts` +- `overlay_source_latency_seconds` +- `overlay_source_quota_remaining` + +### pipeline health +- `overlay_records_generated_count` +- `overlay_records_missing_source_ratio` +- `overlay_degraded_mode_count` +- `overlay_review_queue_size` + +### quality +- `entity_match_precision_sampled` +- `headline_dedupe_rate` +- `youtube_false_positive_rate_sampled` +- `wiki_map_missing_ratio` + +### strategy impact +- `overlay_on_vs_off_delta_return` +- `overlay_on_vs_off_delta_sharpe` +- `overlay_hold_extension_hit_rate` +- `overlay_add_on_hit_rate` + +## 알림 규칙 +- source freshness SLA 초과 +- YouTube quota 80% 초과 +- review queue backlog threshold 초과 +- overlay coverage ratio 급락 +- overlay contribution delta 급변 + +## degraded mode +### trigger +- critical source 2개 이상 실패 +- entity matcher precision alarm +- stale overlay snapshot + +### behavior +- core-only mode로 전환 +- overlay-based add-on 금지 +- hold extension 비활성화 +- alert 발송 + +## 운영 점검 루틴 +### 일간 +- 실패한 source job 확인 +- overlay coverage 확인 +- review queue triage + +### 주간 +- source별 precision 샘플 검수 +- weight calibration 검토 +- channel registry 변경점 반영 + +### 월간 +- source keep/drop review +- topic map refresh +- schema/version audit diff --git a/dev/phase5_deliverables/overlay_config.schema.json b/dev/phase5_deliverables/overlay_config.schema.json new file mode 100644 index 0000000..1057f62 --- /dev/null +++ b/dev/phase5_deliverables/overlay_config.schema.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "OverlayConfig", + "type": "object", + "required": ["enabled", "mode", "weights"], + "properties": { + "enabled": {"type": "boolean"}, + "mode": { + "type": "string", + "enum": ["tie_breaker", "weighted_rank", "hold_adjustment", "add_on_gate"] + }, + "weights": { + "type": "object", + "required": ["yahoo", "youtube", "wikimedia", "finra", "google_trends"], + "properties": { + "yahoo": {"type": "number", "minimum": 0, "maximum": 1}, + "youtube": {"type": "number", "minimum": 0, "maximum": 1}, + "wikimedia": {"type": "number", "minimum": 0, "maximum": 1}, + "finra": {"type": "number", "minimum": 0, "maximum": 1}, + "google_trends": {"type": "number", "minimum": 0, "maximum": 1} + }, + "additionalProperties": false + }, + "strong_threshold": {"type": "number", "minimum": 0, "maximum": 1}, + "weak_threshold": {"type": "number", "minimum": 0, "maximum": 1}, + "allow_degraded_mode": {"type": "boolean"}, + "experimental_sources_enabled": {"type": "boolean"} + }, + "additionalProperties": false +} diff --git a/dev/phase5_deliverables/overlay_feature_record.schema.json b/dev/phase5_deliverables/overlay_feature_record.schema.json new file mode 100644 index 0000000..d5031e6 --- /dev/null +++ b/dev/phase5_deliverables/overlay_feature_record.schema.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "OverlayFeatureRecord", + "type": "object", + "required": [ + "symbol", + "as_of_ts", + "overlay_score", + "overlay_confidence", + "source_presence_mask", + "feature_version" + ], + "properties": { + "symbol": {"type": "string"}, + "as_of_ts": {"type": "string", "format": "date-time"}, + "headline_burst_z": {"type": ["number", "null"]}, + "youtube_influence_z": {"type": ["number", "null"]}, + "wiki_attention_z": {"type": ["number", "null"]}, + "theme_heat_z": {"type": ["number", "null"]}, + "crowding_stress_z": {"type": ["number", "null"]}, + "overlay_score": {"type": "number", "minimum": 0, "maximum": 1}, + "overlay_confidence": {"type": "number", "minimum": 0, "maximum": 1}, + "source_presence_mask": { + "type": "object", + "properties": { + "yahoo": {"type": "boolean"}, + "youtube": {"type": "boolean"}, + "wikimedia": {"type": "boolean"}, + "google_trends": {"type": "boolean"}, + "finra": {"type": "boolean"} + }, + "additionalProperties": false + }, + "hold_extension_hint": {"type": ["string", "null"], "enum": ["extend", "neutral", "trim", null]}, + "add_on_eligibility": {"type": ["boolean", "null"]}, + "feature_version": {"type": "string"} + }, + "additionalProperties": false +} diff --git a/dev/phase5_deliverables/overlay_scoring_policy.md b/dev/phase5_deliverables/overlay_scoring_policy.md new file mode 100644 index 0000000..2fc7371 --- /dev/null +++ b/dev/phase5_deliverables/overlay_scoring_policy.md @@ -0,0 +1,58 @@ +# Overlay Scoring Policy + +## 원칙 +- overlay는 core score를 대체하지 않는다. +- overlay가 강해도 core score minimum threshold 미달이면 거래하지 않는다. +- overlay는 랭킹 재정렬, 보유기간 조정, add-on 허용 여부에만 사용한다. + +## 권장 v1 반영 방식 +### candidate ranking +```text +final_rank_score = core_rank_score * 0.90 + overlay_score * 0.10 +``` + +### optional tie-breaker mode +동일 core bucket 내에서 overlay score 높은 순으로 정렬. + +### holding adjustment +- overlay_score >= strong_threshold: max_holding_days +1 or +2 검토 +- overlay_score <= weak_threshold: time stop 보수화 + +### add-on eligibility +- strong core + strong overlay + market regime ok 일 때만 2차 진입 허용 + +## Source weight (v1 권장) +- Yahoo headline burst: 0.25 +- YouTube influence: 0.35 +- Wikimedia pageview shock: 0.20 +- FINRA crowding: 0.15 +- Google Trends experimental: 0.05 + +## Source reliability modifier +- stale data: penalty +- low entity confidence: penalty +- duplicated source cluster: penalty +- missing data: neutral, not punitive beyond confidence adjustment + +## Overlay score bands +- 0.75 ~ 1.00: strong +- 0.55 ~ 0.75: supportive +- 0.40 ~ 0.55: neutral +- < 0.40: weak/no support + +## Allowed actions by band +- strong: rank boost, hold extension candidate, add-on candidate +- supportive: tie-breaker advantage +- neutral: no action +- weak: no boost, may shorten hold + +## Explicit 금지 +- overlay-only entries +- overlay만으로 risk budget 상향 +- 소셜 burst만으로 stop widening +- 실험 소스(Google Trends) 단독 영향력 과대부여 + +## Calibration +- monthly recalibration +- source별 information coefficient와 hit rate 모니터링 +- unstable source는 weight 하향 또는 disable diff --git a/dev/phase5_deliverables/source_integration_specs.md b/dev/phase5_deliverables/source_integration_specs.md new file mode 100644 index 0000000..4722de0 --- /dev/null +++ b/dev/phase5_deliverables/source_integration_specs.md @@ -0,0 +1,135 @@ +# Source Integration Specs + +## 1. Yahoo Finance RSS +### 목적 +티커 관련 뉴스 headline burst와 publisher breadth 측정. + +### 수집 방식 +- RSS feed polling +- 종목 또는 회사명 기반 기사 매칭 +- 기사 URL canonicalization 및 deduplication + +### 저장 필드 +- source_name +- fetched_at +- article_guid +- url +- title +- publisher +- published_at +- matched_symbols[] +- confidence + +### 주요 feature +- `headline_count_6h` +- `headline_count_24h` +- `publisher_breadth_24h` +- `headline_burst_zscore` + +### 주의 +- 같은 보도자료가 여러 매체에 재유통될 수 있으므로 dedupe 필수 +- 본문 전체를 크롤링하지 말고 headline-level feature 중심 유지 + +## 2. YouTube Data API +### 목적 +유명 투자 채널의 종목 언급과 초기 확산 속도 측정. + +### 수집 방식 +- whitelist channel registry 기반 추적 +- `uploads` playlist polling 우선 +- 필요 시 제한적 search +- video metadata + comment count 수집 + +### 저장 필드 +- channel_id +- channel_title +- video_id +- published_at +- title +- description +- view_count +- like_count +- comment_count +- matched_symbols[] +- channel_weight +- collection_snapshot_at + +### 주요 feature +- `youtube_mentions_24h` +- `youtube_weighted_views_24h` +- `youtube_influence_score` +- `youtube_comment_velocity` + +### 주의 +- 자막 다운로드 의존 금지 +- 전체 유튜브 검색 전수화 금지 +- 채널 whitelist와 alias matcher 품질이 중요 + +## 3. Wikimedia Pageviews +### 목적 +리테일 관심 급증을 정량화. + +### 수집 방식 +- ticker/company ↔ wiki page map 유지 +- daily pageviews ingestion + +### 저장 필드 +- page_title +- date +- views +- project +- access +- agent +- mapped_symbol + +### 주요 feature +- `wiki_views_1d` +- `wiki_views_3d_change` +- `wiki_pageview_zscore_30d` +- `wiki_attention_shock_flag` + +### 주의 +- 다의어 페이지 매핑 오류 주의 +- 회사 페이지와 제품/인물 페이지 혼동 방지 + +## 4. Google Trends (Experimental) +### 목적 +개별 종목보다는 테마/섹터 관심도 측정. + +### 수집 방식 +- 제한된 topic registry 유지 +- 일/주 단위 시계열 수집 + +### 저장 필드 +- trend_topic_id +- topic_label +- geography +- granularity +- observed_at +- interest_value +- mapped_themes[] + +### 주요 feature +- `theme_heat_7d` +- `theme_acceleration_7d` +- `theme_heat_regime` + +### 주의 +- individual ticker trigger로 직접 사용 금지 +- experimental source로 분류 + +## 5. FINRA overlay loader +### 목적 +crowding/short pressure overlay 계산. + +### 입력 +Phase 2 적재 완료된 short sale volume dataset 재사용. + +### 주요 feature +- `short_volume_ratio` +- `short_volume_spike_zscore` +- `off_exchange_crowding_flag` (if available from OTC transparency datasets) + +### 주의 +- short interest와 혼동 금지 +- post-close feature only diff --git a/dev/phase5_deliverables/testing_checklist.md b/dev/phase5_deliverables/testing_checklist.md new file mode 100644 index 0000000..874bee1 --- /dev/null +++ b/dev/phase5_deliverables/testing_checklist.md @@ -0,0 +1,47 @@ +# Phase 5 Testing Checklist + +## A. Unit Tests +- [ ] RSS parser가 malformed item을 건너뛴다. +- [ ] URL canonicalizer가 tracking query를 제거한다. +- [ ] YouTube matcher가 approved alias만 매칭한다. +- [ ] Wikimedia page map lookup이 없는 symbol을 안전하게 skip 한다. +- [ ] Google Trends adapter가 disabled flag에서 no-op 한다. +- [ ] robust z-score 계산이 constant series에서 안전하다. +- [ ] overlay scorer가 missing source를 허용한다. + +## B. Entity Resolution Tests +- [ ] ambiguous ticker가 잘못 매칭되지 않는다. +- [ ] company alias override가 적용된다. +- [ ] manual denylist가 강제된다. +- [ ] wiki page redirect 처리 후 canonical title이 저장된다. +- [ ] video title과 description의 conflicting match를 review queue로 보낸다. + +## C. Integration Tests +- [ ] raw → normalized → feature → score 전체 체인이 동작한다. +- [ ] trade candidate가 없을 때 overlay pipeline이 정상 종료된다. +- [ ] 특정 source 실패 시 나머지 source로 partial score 생성 가능하다. +- [ ] overlay score가 backtester config에 따라 반영된다. +- [ ] live rerank job이 stale source를 탐지하고 degraded mode로 전환한다. + +## D. Replay Tests +- [ ] historical snapshot cutoff 이후 데이터가 사용되지 않는다. +- [ ] 동일 cutoff로 재실행 시 동일 overlay score가 재생성된다. +- [ ] source update 지연 시 fallback 결과가 일관적이다. + +## E. Quality Tests +- [ ] random sample 100건에서 symbol match precision 측정 +- [ ] YouTube whitelist 외 채널이 잘못 포함되지 않는다. +- [ ] duplicated Yahoo headlines가 burst를 과대추정하지 않는다. +- [ ] wiki attention shock가 명백한 비종목 이벤트에서 과도하게 오르지 않는다. + +## F. Strategy Impact Tests +- [ ] overlay on/off ablation 리포트 생성 +- [ ] tie-breaker only와 weighted-rank 결과 비교 +- [ ] hold-extension only 결과 비교 +- [ ] source별 incremental value 리포트 생성 + +## G. Ops Tests +- [ ] API quota exhaustion 시 경고 및 soft-fail +- [ ] source freshness SLA 위반 알림 발송 +- [ ] registry update 후 캐시 무효화 정상 동작 +- [ ] feature store write retry가 idempotent 하다. diff --git a/dev/phase5_deliverables/youtube_channel_registry_spec.md b/dev/phase5_deliverables/youtube_channel_registry_spec.md new file mode 100644 index 0000000..3a8cb19 --- /dev/null +++ b/dev/phase5_deliverables/youtube_channel_registry_spec.md @@ -0,0 +1,41 @@ +# YouTube Channel Registry Spec + +## 목적 +무분별한 search API 사용을 피하고, 신뢰 가능한 채널 subset만 추적하기 위한 registry. + +## registry 필드 +- channel_id +- channel_title +- category +- language +- region +- subscriber_band +- channel_weight +- active_flag +- watch_mode (`uploads_only` | `uploads_plus_comments`) +- symbol_focus_tags[] +- notes +- created_at +- updated_at + +## 포함 기준 +- 투자/시장 관련 공개 채널 +- 최근 일정 기간 내 활동 지속 +- 명확한 채널 정체성 +- 과도한 spam/scam 패턴 없음 + +## 제외 기준 +- 펌프 앤 덤프 의심 +- 저품질 클릭베이트 과다 +- 종목 언급은 많지만 실제 매칭 정밀도가 낮음 +- 정책/약관 리스크 높은 채널 + +## channel_weight 초기값 가이드 +- 대형/영향력 높음: 1.0 +- 중간: 0.6 +- 소형/니치: 0.3 + +## 운영 규칙 +- 신규 채널 추가는 수동 승인 +- 월 1회 registry review +- false positive 높은 채널은 weight 하향 또는 비활성화