# Phase 1 아키텍처 및 저장소 구조 계획

## 1. 설계 원칙

이 프로젝트는 무료 데이터 기반의 미국 주식 이벤트 스윙 시스템입니다.
Phase 1의 핵심 원칙은 다음과 같습니다.

1. **원문(raw)을 절대 버리지 않는다.**
2. **운영 상태(PostgreSQL)와 연구용 시계열(DuckDB/Parquet)을 분리한다.**
3. **모든 adapter는 idempotent 해야 한다.**
4. **LLM은 규칙 기반 파서를 대체하지 않고 보강한다.**
5. **실패 시 no-trade/no-write가 기본값이다.**
6. **모든 서비스는 독립적으로 재실행 가능해야 한다.**
7. **표준화된 event/document identifier 없이는 downstream으로 보내지 않는다.**

## 2. 권장 저장소 구조

```text
repo/
  apps/
    collector/
      sec_collector/
      alpaca_collector/
      fred_collector/
      finra_collector/
    parser/
      filing_parser/
      xbrl_parser/
      event_parser/
    feature_builder/
      market_features/
      event_features/
    backtester/
    live_trader/
  libs/
    adapters/
      sec/
      alpaca/
      fred/
      finra/
    common/
      config.py
      logging.py
      time_utils.py
      ids.py
      retries.py
      file_store.py
    db/
      models.py
      migrations/
    schemas/
      parser_event.schema.json
      source_record.schema.json
    llm/
      prompts/
      validator.py
      cache.py
  tests/
    unit/
    integration/
    replay/
    fixtures/
  configs/
    app.yaml
    env.example
    symbols.yaml
  data/
    raw/
    staging/
    parquet/
  docs/
```

## 3. 실행 단위

초기에는 서비스별 독립 실행 파일로 둡니다.

- `python -m apps.collector.sec_collector.main`
- `python -m apps.collector.alpaca_collector.main`
- `python -m apps.parser.event_parser.main`
- `python -m apps.feature_builder.market_features.main`

초기에는 큐 시스템을 도입하지 않고, **명시적 스케줄 실행**을 사용합니다.
큐는 Phase 3 이후 필요 시 Redis/Celery 또는 경량 작업 큐를 검토합니다.

## 4. 저장 계층

### 4.1 Raw Zone

원문을 그대로 저장합니다.

경로 예시:

```text
data/raw/sec/2026-03-12/{cik}/{accession}/index.json
data/raw/sec/2026-03-12/{cik}/{accession}/filing.txt
data/raw/sec/2026-03-12/{cik}/{accession}/exhibit_99_1.html
data/raw/alpaca/bars/daily/2026-03-12/{symbol}.json
data/raw/fred/2026-03-12/{series_id}.json
data/raw/finra/2026-03-12/daily_short_sale_volume.txt
```

원칙:
- 원문은 수정하지 않습니다.
- 적재 시 수집 메타데이터를 sidecar JSON으로 함께 저장합니다.
- raw 저장 성공 전에는 structured write를 하지 않습니다.

### 4.2 Staging Zone

파싱 전 정규화 중간 결과를 저장합니다.

예:
- HTML → text 추출
- filing metadata
- extracted exhibit list
- temporary parsed items

### 4.3 Structured Zone

운영용 PostgreSQL + 연구용 Parquet로 저장합니다.

PostgreSQL:
- job 상태
- 문서 메타
- 이벤트 레코드
- parser 결과
- feature snapshot
- 주문/포지션 상태

Parquet/DuckDB:
- 바 시계열
- 대량 feature matrix
- 라벨링 데이터
- 실험/백테스트 산출물

## 5. 모듈 경계

### 5.1 Source Adapter

역할:
- 외부 원천에서 raw 데이터를 수집
- 최소 메타데이터 부착
- raw 저장
- source checksum 생성

금지:
- 전략 판단
- event scoring
- 트레이드 신호 생성

### 5.2 Normalizer

역할:
- raw를 내부 공통 포맷으로 정규화
- source-specific field를 canonical field로 변환

예:
- SEC accession → internal document_id
- Alpaca bar payload → canonical OHLCV schema

### 5.3 Parser

역할:
- 문서 기반 구조화
- 규칙 기반 이벤트 탐지
- 선택적으로 LLM 보강

### 5.4 Feature Builder

역할:
- 이벤트 특징 생성
- 시장 특징 생성
- 레짐 특징 생성
- attention 특징 생성(Phase 1에서는 인터페이스만)

### 5.5 Ranker

Phase 1에서는 실제 점수 산출보다 **입력 포맷 정의**까지만 합니다.

### 5.6 Execution Layer

Phase 1에서는 주문 실행을 하지 않고, **order_plan schema**만 정의합니다.

## 6. 공통 식별자 규칙

### 6.1 symbol_master_id
- 내부 고유 종목 식별자
- v1에서는 `ticker + venue + start_date` 조합 허용

### 6.2 document_id
형식:

```text
DOC::{source}::{issuer_id}::{event_date}::{accession_or_hash}
```

예:

```text
DOC::SEC::0000789019::2026-01-28::0001193125-26-027198
```

### 6.3 event_id
형식:

```text
EVT::{issuer_id}::{event_type}::{primary_document_id}
```

### 6.4 job_run_id
UUID 사용

## 7. 시간/달력 정책

- 내부 표준 타임존은 **UTC 저장 + US/Eastern 파생 컬럼**입니다.
- 거래일 계산은 반드시 거래소 달력을 사용합니다.
- raw 수집 시각, source published 시각, parsed event 시각을 구분합니다.
- `filed_at`, `accepted_at`, `collected_at`, `normalized_at`, `parsed_at` 필드를 각각 유지합니다.

## 8. 환경 변수 정책

필수 환경 변수 예시:

```text
APP_ENV=dev
POSTGRES_DSN=postgresql://...
DUCKDB_PATH=/app/data/parquet/research.duckdb
DATA_ROOT=/app/data
ALPACA_API_KEY=...
ALPACA_SECRET_KEY=...
FRED_API_KEY=...
OPENAI_API_KEY=...
LOG_LEVEL=INFO
SEC_USER_AGENT=project-name contact-email
```

원칙:
- 민감정보는 코드/문서에 하드코딩 금지
- `.env`는 로컬 전용, 배포에는 secret 주입 사용
- example 파일에는 placeholder만 포함

## 9. Docker Compose 기본 구성

서비스:
- `postgres`
- `app` (개발용 Python image)
- 필요 시 `adminer` 또는 경량 DB UI

초기에는 메시지 큐/오브젝트 스토리지는 넣지 않습니다.

## 10. 로그와 메트릭 정책

모든 서비스는 JSON log를 기본으로 합니다.

필수 필드:
- timestamp
- level
- service
- job_run_id
- source
- entity_id
- message
- error_class
- retry_count

메트릭 예시:
- source fetch count
- source fetch latency
- normalized record count
- parser success/fail count
- schema validation fail count
- duplicate skip count

## 11. 장애 처리 원칙

- raw 수집 실패 → structured write 금지
- schema validation 실패 → parser 결과 폐기, 원문은 유지
- DB write 실패 → retry 후 stop
- 외부 API rate limit → backoff
- 알 수 없는 필드 추가 → warning + raw 보존

## 12. Phase 1 수용 기준

- 로컬에서 `make bootstrap` 수준 명령으로 개발 환경 구축 가능
- sample SEC filing을 1회 수집 후 raw/staging/structured에 적재 가능
- sample Alpaca bar 데이터를 canonical schema로 변환 가능
- sample FRED/FINRA 데이터를 일자별로 적재 가능
- parser가 schema-valid JSON을 생성 가능
- 모든 경로가 재실행 시 중복 없이 안정 동작
