You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

228 lines
4.7 KiB
Markdown

# Phase 1 서비스 계약서
## 1. 목적
이 문서는 각 서비스와 adapter가 어떤 입력을 받고 어떤 출력을 내야 하는지 정의합니다.
AI 코딩 에이전트는 이 계약을 기준으로 인터페이스를 고정해야 합니다.
## 2. 공통 원칙
- 모든 서비스는 명시적 입력 객체를 받습니다.
- 모든 서비스는 typed result 또는 typed error를 반환합니다.
- 외부 API 호출 결과는 raw 저장 이후에만 정규화됩니다.
- 서비스는 가능하면 pure function 형태를 유지합니다.
- DB write는 application layer에서 수행하고, parser/adapter core는 side-effect를 최소화합니다.
## 3. 공통 타입
### 3.1 FetchRequest
```json
{
"source": "sec",
"entity": "issuer|symbol|series|date",
"key": "0000789019",
"start_date": "2026-01-01",
"end_date": "2026-03-31",
"run_mode": "backfill|daily|replay"
}
```
### 3.2 FetchResult
```json
{
"status": "success|partial|failed|skipped",
"raw_object_ids": ["RAW::..."],
"records_seen": 3,
"records_written": 3,
"warnings": [],
"errors": []
}
```
### 3.3 NormalizeResult
```json
{
"status": "success|failed",
"canonical_records": [{"...": "..."}],
"warnings": [],
"errors": []
}
```
## 4. SEC adapter 계약
### 4.1 입력
- CIK 또는 accession
- 기간 또는 개별 filing key
- run_mode
### 4.2 출력
- submissions raw object
- filing raw object
- exhibit raw object list
- canonical document metadata
### 4.3 함수 예시
```python
def fetch_submissions(cik: str) -> FetchResult: ...
def fetch_filing(accession_no: str, cik: str) -> FetchResult: ...
def normalize_filing(raw_object_id: str) -> NormalizeResult: ...
```
### 4.4 실패 규칙
- HTTP 실패 → retryable error
- 404 → non-retryable warning
- parsing 실패 → raw는 유지, normalize fail
## 5. Alpaca adapter 계약
### 5.1 입력
- symbol list
- timeframe
- start/end
### 5.2 출력
- canonical OHLCV record list
### 5.3 함수 예시
```python
def fetch_bars(symbols: list[str], timeframe: str, start: str, end: str) -> FetchResult: ...
def normalize_bars(raw_object_id: str) -> NormalizeResult: ...
```
## 6. FRED adapter 계약
```python
def fetch_series(series_id: str, start: str | None = None, end: str | None = None) -> FetchResult: ...
```
출력:
- series metadata
- observation records
## 7. FINRA adapter 계약
```python
def fetch_daily_short_volume(trade_date: str) -> FetchResult: ...
def normalize_daily_short_volume(raw_object_id: str) -> NormalizeResult: ...
```
주의:
- symbol mapping 실패 가능
- 원본 ticker_raw는 반드시 유지
## 8. Event Parser 계약
입력:
```json
{
"document_id": "DOC::...",
"source_name": "sec",
"form_type": "8-K",
"issuer_id": "ISSUER::...",
"filing_date": "2026-01-29",
"accepted_at_utc": "2026-01-29T21:05:00Z",
"text": "...document text...",
"metadata": {
"item_numbers": ["2.02", "7.01"],
"exhibits": ["EX-99.1"]
}
}
```
출력:
- `parser_event.schema.json`을 만족하는 JSON
실패:
- invalid schema → `validation_status=invalid`
- parser exception → error object 반환, event 생성 금지
## 9. Feature Builder 계약
입력:
- event row
- related market data
- optional macro/short volume rows
출력 예시:
```json
{
"event_id": "EVT::...",
"snapshot_name": "event_v1",
"snapshot_version": "1.0.0",
"feature_json": {
"guidance_direction": "raised",
"oneoff_penalty": 0,
"reaction_day_return": 0.042,
"volume_ratio_20d": 2.3
}
}
```
## 10. Job Runner 계약
입력:
- job_name
- source_name
- run_date
- mode
출력:
- `job_runs` 테이블 row 업데이트
- 로그 스트림
상태 전이:
- pending → running → succeeded
- pending → running → partial
- pending → running → failed
## 11. 에러 객체 표준
```json
{
"error_class": "RateLimitError",
"message": "HTTP 429 from source",
"retryable": true,
"source_name": "sec",
"entity_key": "0000789019",
"context": {"url": "..."}
}
```
## 12. 로그 포맷 표준
```json
{
"timestamp": "2026-03-12T10:00:00Z",
"level": "INFO",
"service": "sec_collector",
"job_run_id": "...",
"message": "fetched submissions",
"source": "sec",
"entity_id": "0000789019",
"records_seen": 1,
"records_written": 1
}
```
## 13. 재시도 계약
- source adapter의 네트워크 실패는 최대 3회 지수 백오프
- validation 실패는 재시도하지 않음
- DB deadlock/connection issue는 retryable
- schema mismatch는 raw 보존 후 failed 처리
## 14. 금지 규칙
- adapter가 임의로 심볼명을 정정하지 말 것
- parser가 raw text를 수정 저장하지 말 것
- feature builder가 원문 source를 재호출하지 말 것
- job runner가 실패를 성공으로 덮어쓰지 말 것