13 Commits (20816118848ad8f54bb43f989dd3045c8cb83c84)

Author SHA1 Message Date
I Luk Kim 0752b29a63 perf: API 성능 개선 Round 2 — 9개 항목 (P6-P14)
Tier 1:
- P6: 미들웨어 request_info 지연 추출 (성공 경로에서 body/headers 읽기 제거)
- P7: GZip 압축 미들웨어 (minimum_size=1000, ~4x 압축)
- P8: Redis maxmemory 512MB + allkeys-lru 퇴거 정책

Tier 2:
- P9: _store_ticker_data() batch upsert 전환 (ON CONFLICT DO NOTHING)
- P10: DB 커넥션 풀 증가 (pool_size=20, max_overflow=30, 환경변수 설정)
- P11: Attention 엔드포인트 Redis 캐시 추가 (@with_cache ttl=3600)

Tier 3:
- P12: Dockerfile 멀티 워커 (--workers 4, dev는 --reload 오버라이드)
- P13: aiohttp ClientSession 싱글턴 공유 (4개 파일 7곳 TCP/TLS 재사용)
- P14: Pydantic model_validate → model_construct (bulk 경로 validation 스킵)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5 months ago
I Luk Kim 6a98cb2d94 perf: API 성능 개선 — 로그 분석 기반 6개 항목 수정
P0 — 500 에러 대폭 감소 (1.1% → 0.11%)
- price.py / financial.py: except HTTPException: raise 추가 →
  HTTPException(404)이 except Exception에 잡혀 500으로 재포장되던 버그 수정
- real_sec_financial_service: _get_price_data_for_period에 try/except 추가 →
  yfinance 실패가 financial 엔드포인트 500으로 전파되지 않도록 방어
- price.py: TimeoutError 별도 핸들러 추가 → yfinance 타임아웃 시 503 반환

P1 — _store_price_data() N+1 → batch upsert
- price_data_service: 252회 개별 SELECT+INSERT 루프를
  pg_insert(PriceData).on_conflict_do_nothing('uq_price_data') 단일 쿼리로 교체

P2 — financial/data 캐시 TTL 1h → 24h
- financial.py: 재무 데이터는 분기 발표 주기 → _FIN_TTL = 86400

P3 — 과거 가격 데이터 TTL 연장
- price.py: end_date < today-1 이면 TTL=7일, 나머지 1h 유지

P4 — 요청 로그 비동기 배치 처리
- error_logger.py: asyncio.Queue(10_000) 추가, _log_request를 put_nowait으로
  변경 (논블로킹), 백그라운드 _request_log_flusher 코루틴 (1s/100건마다 flush)
- main.py: 앱 시작 시 start_request_log_flusher() 호출

P5 — 누락 DB 인덱스 추가
- financial.py: CalculatedMetrics에 calculation_date, period_date 단독 인덱스
- attention.py: AttentionFeaturesDaily에 ticker 단독 인덱스
- alembic b3c4d5e6f7a8: 위 3개 인덱스 생성 마이그레이션 (idempotent)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5 months ago
I Luk Kim 4a0aff9ad6 fix(overlay): 다중 버그 수정 및 OpenAPI 문서 개선
## Overlay 버그 수정

- **collect_all 동시성 오류**: asyncio.gather로 공유 DB 세션에 동시 접근 → SQLAlchemy 오류
  발생. 어댑터를 순차 실행으로 변경
- **feedparser/apscheduler/pytrends 미설치**: Docker 이미지 재빌드로 패키지 영구 포함
- **중복 job log 항목**: _log_job이 매번 새 행 삽입 → running+completed 중복 생성.
  기존 running 행을 업데이트하도록 수정
- **admin/health 잘못된 job_type**: yahoo_rss/wikimedia 등 존재하지 않는 타입 조회.
  실제 로깅되는 collect_all/feature_build만 조회하도록 수정
- **source_presence 항상 false**: z-score가 계산 불가능하면(2일 미만 데이터) source가
  false로 표시됨. 실제 데이터 존재 여부(headline_count_24h > 0 등)로 판단하도록 수정
- **top-movers 심볼 중복**: 파이프라인 실행 횟수만큼 같은 심볼 반복 출력.
  심볼별 최신 레코드만 조회하는 서브쿼리로 수정
- **YouTube None 곱셈 오류**: view_count * channel_weight에서 None이면 TypeError.
  (or 0) / (or 0.5) 가드 추가

## Trends 기능 수정

- **ThemeTopicMap 자동 시딩**: 파이프라인 최초 실행 시 TOP_50_SYMBOLS에 대한
  기본 topic 매핑 자동 생성
- **GOOGLE_TRENDS_ENABLED=true**: docker-compose.yml에 환경변수 추가
- **theme_heat_z 항상 null**: feature_builder에 build_trends_features() 메서드
  누락 → OverlayTrendObservation 데이터가 점수에 반영 안 됨. 메서드 추가 및 연결
- **POST /admin/seed-topics**: ThemeTopicMap 수동 시딩용 admin 엔드포인트 추가

## OpenAPI 문서 개선

- 모든 엔드포인트에 summary/description 추가 (filings, news, database, etf, stocks,
  screener, fred, attention, overlay)
- Pydantic 스키마에 json_schema_extra example 추가 (attention, filing)
- 누락된 태그 6개 추가 (attention, attention-admin, database, fred, error-logs,
  request-logs)
- 루트(/) 랜딩 페이지를 Swagger UI로 리다이렉트로 교체

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5 months ago
I Luk Kim afd133e027 refactor(main): 루트 문서 페이지 OpenAPI 스키마에서 자동 생성
하드코딩된 330줄 HTML을 제거하고 request.app.openapi()에서
동적으로 엔드포인트 목록을 렌더링하도록 변경.
새 라우터 추가 시 / 페이지를 별도로 수정할 필요 없음.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5 months ago
I Luk Kim af88f89f69 docs: 앱 내부 문서(루트 HTML, OpenAPI)에 index 엔드포인트 추가
- main.py 루트 HTML: Stock Market Data 섹션에 /stocks/index/{index_name} 항목 및 예시 추가
- stocks 태그 설명 업데이트 (index constituents 포함)
- get_index_constituents: summary/response_description/docstring 상세화

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5 months ago
I Luk Kim b88835cded feat(screener): add stock screener API with yfinance EquityQuery
Implements GET /api/v1/screener/stocks and GET /api/v1/screener/fields
for condition-based stock filtering without manual web searches.

- app/schemas/screener.py: ScreenerStockItem + ScreenerResponse Pydantic models
- app/services/screener_service.py: ScreenerService wrapping yfinance screen()
  via run_in_executor; exchange mapping (NYSE→NYQ, NASDAQ→NMS/NGM/NCM, etc.);
  btwn/gt/lt/is-in/eq EquityQuery builder; post-filter for ETF/FUND exclusion
- app/api/v1/endpoints/screener.py: /stocks (with_cache TTL=300) + /fields metadata
- app/api/v1/api.py: register screener router at prefix /screener
- app/main.py: add screener OpenAPI tag and HTML doc section with examples

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5 months ago
I Luk Kim 9085151af8 chore(main): remove SQLite ALTER TABLE migration shim
PostgreSQL is the actual DB; create_all handles schema creation.
The SQLite workaround added in the previous commit is not needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5 months ago
I Luk Kim 76e154eccd feat(filings): add accepted_at field to filing search response
Expose SEC ACCEPTANCE-DATETIME so downstream consumers (filing_poller)
can populate Document.accepted_at_utc and Event.filed_at_utc.

- SECFiling model: add nullable accepted_at TIMESTAMP column
- main.py startup: ALTER TABLE migration for existing SQLite DBs
- sec_filings_service: extract acceptanceDateTime from SEC JSON, store on
  INSERT and force_refresh UPDATE
- FilingSummary schema: add Optional[str] accepted_at field
- filings endpoint: map accepted_at as ISO 8601 string in response
- CHANGELOG: v3.0.1 entry

Existing rows have accepted_at=NULL; backfill with force_refresh=true.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5 months ago
I Luk Kim 29fc870b37 Add Phase 5 Attention Overlay API and fix Redis port mismatch
- 12 REST endpoints: overlay score, bulk, top-movers, headlines, youtube, wiki, crowding, trends, history, admin (health/trigger/job-log)
- 10 services: entity_resolver, yahoo_rss_adapter, wikimedia_adapter, youtube_adapter, google_trends_adapter, finra_overlay_loader, feature_builder, overlay_scorer, overlay_pipeline, scheduler
- 10 DB tables across overlay_registry, overlay_raw_event, overlay_feature models
- APScheduler: collect @ 23:30 UTC + feature build @ 01:30 UTC weekdays
- Fix Redis port mismatch: config default 16379 → 16380 to match docker-compose external port
- 64 overlay tests covering cache utils, Redis config, all 12 endpoints, route ordering

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5 months ago
I Luk Kim bf6932ca2f Add Alpaca-specific DB table and Redis caching for Alpaca/FINRA endpoints
Separate Alpaca price data into dedicated AlpacaPriceData table to avoid
UniqueConstraint('ticker', 'date') conflicts with Yahoo Finance PriceData.
Add Redis caching (build_cache_key/get_cached_response/set_cached_response)
to 3 Alpaca endpoints and 2 FINRA query endpoints with appropriate TTLs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5 months ago
I Luk Kim 93d8018746 Update API documentation with SEC filings endpoints
Add SEC Filings section to root HTML docs, example requests, key features,
and OpenAPI tags for Swagger UI / ReDoc visibility.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5 months ago
I Luk Kim d0f1a9a7d0 Add SEC filings indexing, search, and exhibit extraction (8-K, 6-K, 20-F, 40-F)
Extract shared SECHttpClient from ETF fetcher (retry, backoff, cache, throttle)
and apply it to both ETF and core SEC services, fixing missing rate limiting.
Add SECFiling DB model, Pydantic schemas, SECFilingsService with auto-indexing,
and REST endpoints at /filings/search, /filings/documents, /filings/exhibit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5 months ago
I Luk Kim 355aeb19d3 Initial commit with full project improvements
Security: config-based CORS, default secret warnings, sort_by validation
Error handling: debug logging in cache silent failures
Architecture: shared resolve_time_parameters, deduplicated logger init, unified route structure
Database: conditional SQLite/PostgreSQL engine, in-memory test DB, dialect-aware date formatting, optimized stats query
Docker: .dockerignore, pinned yfinance_plus commit
Dependencies: removed duplicates, added version upper bounds, removed unused axios
Frontend: custom _document/_error pages, adminApi client, Layout standardization, ESLint version update

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5 months ago