<!-- task=m-us-market-expansion/04+02,03_us_backtest_smoke plan=0 tag=US_BACKTEST -->

# Implementation Plan - US_BACKTEST

## 이 파일을 읽는 구현 에이전트에게

구현 완료의 마지막 단계는 active `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채우는 것이다. `02+01_kis_us_daily_bars`와 `03+01_shared_query_surface` 완료 전에는 구현하지 않는다. 사용자-only 차단은 review stub의 `사용자 리뷰 요청` 섹션에만 기록한다. finalization은 code-review 전용이다.

## 배경

US daily data가 저장되고 query surface가 열려도 backtest가 실제 USD/NASDAQ data로 smoke되지 않으면 milestone의 마지막 기능을 닫을 수 없다. Engine은 `MarketUS`면 USD starting cash를 쓰지만, tests는 KR fixture 중심이다. 이 작업은 US bars를 backtest source와 engine fixture에 넣어 compatibility를 잠근다.

## 사용자 리뷰 요청 흐름

구현 중 차단은 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. 직접 사용자에게 질문하지 않는다. code-review가 user-review stop 여부를 판단한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/trading-expansion/milestones/us-market-expansion.md`
- Task ids:
  - `us-backtest`: 미국장 daily data로 backtest fixture 또는 smoke 동작
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `agent-test/local/rules.md`
- `agent-test/local/worker-smoke.md`
- `agent-test/local/operations-smoke.md`
- `services/worker/internal/backtest/bar_source.go`
- `services/worker/internal/backtest/bar_source_test.go`
- `services/worker/internal/backtest/engine.go`
- `services/worker/internal/backtest/fixture_test.go`
- `services/worker/internal/jobs/backtest_jobs.go`
- `services/worker/internal/jobs/backtest_jobs_test.go`
- `apps/cli/internal/operator/runner.go`
- `apps/cli/internal/operator/runner_backtest_test.go`
- `apps/cli/testdata/operator/backtest_result_summary.yaml`
- `apps/cli/testdata/operator/expected/backtest_result_summary.jsonl`

### 테스트 환경 규칙

`test_env=local`. worker-smoke와 operations-smoke를 적용한다. worker backtest 변경은 `go test ./services/worker/...`, CLI/headless fixture 변경은 `go test -count=1 ./apps/cli/internal/operator`, milestone verification은 `bin/test`다.

### 테스트 커버리지 공백

- `StorageBarSource` test는 US instrument를 seed하지만 KR query 결과만 assert한다.
- Engine tests는 `MarketKR` starting cash/ending equity만 assert한다. `MarketUS` USD cash path는 code에 있으나 direct fixture test가 없다.
- Operator backtest scenario fixtures are KR-centered.

### 심볼 참조

Renamed/removed symbol: none. New tests/fixtures only unless source behavior gap is found.

### 분할 판단

Shared task group: `m-us-market-expansion`. This subtask is `04+02,03_us_backtest_smoke` and depends on `02+01_kis_us_daily_bars` plus `03+01_shared_query_surface`. Predecessor status at plan creation: both missing complete.log. The transitive foundation dependency is carried by 02/03; no hidden dependency is added.

### 범위 결정 근거

이 작업은 deterministic fixture/smoke only. Strategy architecture, live provider smoke, paper trading, Flutter UI는 제외한다. If implementation finds a real engine bug, fix only the US compatibility bug needed for this smoke.

### 빌드 등급

`local-G06`: deterministic worker/CLI tests with bounded source impact; no schema or external runtime required if predecessors are complete.

## 구현 체크리스트

- [ ] [US_BACKTEST-1] `StorageBarSource`가 US market selector로 USD/NASDAQ bars만 반환하는 test를 추가한다. 검증: `bin/test`와 관련 worker 검증이 통과한다.
- [ ] [US_BACKTEST-2] Engine fixture가 `MarketUS` daily bars로 USD starting/ending equity를 계산하는 smoke를 추가한다.
- [ ] [US_BACKTEST-3] headless/operator backtest smoke가 US market fixture를 실행하거나, worker-only fixture로 충분한 경우 범위 근거를 review에 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 의존 관계 및 구현 순서

`04+02,03_us_backtest_smoke`는 디렉터리명 기준으로 `02+01_kis_us_daily_bars`와 `03+01_shared_query_surface`의 `complete.log`가 필요하다. 추가 dependency를 만들지 않는다.

### [US_BACKTEST-1] Storage Bar Source US Selector

문제: [services/worker/internal/backtest/bar_source.go](/config/workspace/alt/services/worker/internal/backtest/bar_source.go:24)는 market filter로 instruments를 골라 bars를 읽는다. [bar_source_test.go](/config/workspace/alt/services/worker/internal/backtest/bar_source_test.go:60)는 US instrument를 seed하지만 KR query만 assert한다.

해결 방법: 같은 test 또는 새 test에서 `source.GetBars(..., market.MarketUS, ...)`를 호출하고 `NASDAQ:AAPL`만 반환되는지, USD close currency가 유지되는지 검증한다.

수정 파일 및 체크리스트:

- [ ] `services/worker/internal/backtest/bar_source_test.go`: US selector assertion 추가.

테스트 작성: 작성한다. 기존 in-memory store를 재사용한다.

중간 검증:

```bash
go test -count=1 ./services/worker/internal/backtest
```

### [US_BACKTEST-2] Engine USD Fixture

문제: [services/worker/internal/backtest/engine.go](/config/workspace/alt/services/worker/internal/backtest/engine.go:57)는 `MarketUS`면 USD starting cash를 사용하지만 [fixture_test.go](/config/workspace/alt/services/worker/internal/backtest/fixture_test.go:92)는 KR-only bars와 KRW expected result를 검증한다.

해결 방법: `NASDAQ:AAPL` USD bars와 deterministic strategy를 사용해 `MarketUS` run을 실행하고 starting cash `10000` USD, trades/positions USD price, final equity/summary를 assert한다.

수정 파일 및 체크리스트:

- [ ] `services/worker/internal/backtest/fixture_test.go`: US fixture test 추가.
- [ ] 필요 시 helper 함수로 KR/US fixture 중복만 최소화한다.

테스트 작성: 작성한다. Numeric expectation은 KR test처럼 명시한다.

중간 검증:

```bash
go test -count=1 ./services/worker/internal/backtest
```

### [US_BACKTEST-3] Operator Or Worker Smoke Closure

문제: [apps/cli/testdata/operator/backtest_result_summary.yaml](/config/workspace/alt/apps/cli/testdata/operator/backtest_result_summary.yaml:1)는 KR scenario다. milestone은 US daily data로 backtest fixture 또는 smoke가 동작해야 한다.

해결 방법: predecessors가 US import/query fixture를 제공하면 `us_backtest_result_summary.yaml`과 expected JSONL을 추가한다. If the runtime cannot seed US bars without live KIS credentials, keep worker deterministic fixture as completion evidence and record why operator fixture is deferred.

수정 파일 및 체크리스트:

- [ ] `apps/cli/testdata/operator/us_backtest_result_summary.yaml`: 가능한 경우 추가.
- [ ] `apps/cli/testdata/operator/expected/us_backtest_result_summary.jsonl`: 가능한 경우 추가.
- [ ] `apps/cli/internal/operator/runner_backtest_test.go`: US backtest scenario test 추가 또는 worker-only closure 근거 기록.

테스트 작성: 작성한다. Operator fixture가 live provider를 요구하면 작성하지 않고 worker deterministic smoke를 completion evidence로 남긴다.

중간 검증:

```bash
go test -count=1 ./apps/cli/internal/operator
```

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| `services/worker/internal/backtest/bar_source_test.go` | US_BACKTEST-1 |
| `services/worker/internal/backtest/fixture_test.go` | US_BACKTEST-2 |
| `apps/cli/testdata/operator/us_backtest_result_summary.yaml` | US_BACKTEST-3 |
| `apps/cli/testdata/operator/expected/us_backtest_result_summary.jsonl` | US_BACKTEST-3 |
| `apps/cli/internal/operator/runner_backtest_test.go` | US_BACKTEST-3 |

## 최종 검증

```bash
go test -count=1 ./services/worker/internal/backtest ./apps/cli/internal/operator
go test -count=1 ./services/worker/...
bin/test
git diff --check
```

`go test` cache는 허용하지 않는다.

모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
