analysis: reflect cost/execution in v2 backtest pipeline (#368) #387

Merged
jihoson merged 4 commits from feature/issue-368-backtest-cost-execution into feature/v3-session-policy-stream 2026-03-02 09:21:07 +09:00
Collaborator

Traceability

  • REQ-ID: REQ-V2-007
  • TASK-ID: TASK-V2-012
  • TEST-ID: TEST-ACC-014

Summary

  • BacktestCostModelpartial_fill_rate_by_session를 추가하고 필수 검증으로 강제했습니다.
  • run_v2_backtest_pipeline()에서 BacktestExecutionModel을 실제 연결해 fold 테스트 성과에 실행 반영 지표를 계산하도록 확장했습니다.
  • BacktestFoldResult에 실행 반영 지표(execution_adjusted_avg_return_bps, 체결/거절/부분체결 카운트)를 추가했습니다.
  • 비용 가정(낙관/보수) 차이에 따라 성과가 달라지는 회귀 테스트를 추가했습니다.
  • 구현 감사 문서에서 REQ-V2-007 상태를 코드 실체 기준으로 ✅ 완료로 동기화했습니다.

Validation

  • python3 scripts/session_handover_check.py --strict
  • pytest -q tests/test_backtest_cost_guard.py tests/test_backtest_execution_model.py tests/test_backtest_pipeline_integration.py
  • ruff check src/analysis/backtest_cost_guard.py src/analysis/backtest_pipeline.py tests/test_backtest_cost_guard.py tests/test_backtest_pipeline_integration.py
  • python3 scripts/validate_ouroboros_docs.py
  • python3 scripts/validate_governance_assets.py

Notes

  • 기존 baseline 정확도(B0/B1/M1)는 유지하고, 실행 가정 반영 성과 지표를 병행 추가해 기존 해석과 신규 해석을 동시에 제공합니다.
## Traceability - REQ-ID: `REQ-V2-007` - TASK-ID: `TASK-V2-012` - TEST-ID: `TEST-ACC-014` ## Summary - `BacktestCostModel`에 `partial_fill_rate_by_session`를 추가하고 필수 검증으로 강제했습니다. - `run_v2_backtest_pipeline()`에서 `BacktestExecutionModel`을 실제 연결해 fold 테스트 성과에 실행 반영 지표를 계산하도록 확장했습니다. - `BacktestFoldResult`에 실행 반영 지표(`execution_adjusted_avg_return_bps`, 체결/거절/부분체결 카운트)를 추가했습니다. - 비용 가정(낙관/보수) 차이에 따라 성과가 달라지는 회귀 테스트를 추가했습니다. - 구현 감사 문서에서 `REQ-V2-007` 상태를 코드 실체 기준으로 `✅ 완료`로 동기화했습니다. ## Validation - `python3 scripts/session_handover_check.py --strict` - `pytest -q tests/test_backtest_cost_guard.py tests/test_backtest_execution_model.py tests/test_backtest_pipeline_integration.py` - `ruff check src/analysis/backtest_cost_guard.py src/analysis/backtest_pipeline.py tests/test_backtest_cost_guard.py tests/test_backtest_pipeline_integration.py` - `python3 scripts/validate_ouroboros_docs.py` - `python3 scripts/validate_governance_assets.py` ## Notes - 기존 baseline 정확도(B0/B1/M1)는 유지하고, 실행 가정 반영 성과 지표를 병행 추가해 기존 해석과 신규 해석을 동시에 제공합니다.
agentson added 2 commits 2026-03-02 03:37:34 +09:00
analysis: apply execution-adjusted cost model in v2 backtest pipeline (#368)
Some checks failed
Gitea CI / test (push) Successful in 32s
Gitea CI / test (pull_request) Failing after 6s
200bc82a27
agentson force-pushed feature/issue-368-backtest-cost-execution from 200bc82a27 to 96d2c97fe7 2026-03-02 03:40:05 +09:00 Compare
agentson added 1 commit 2026-03-02 04:01:27 +09:00
docs: bump requirements registry version for policy change sync
Some checks failed
Gitea CI / test (push) Successful in 33s
Gitea CI / test (pull_request) Failing after 5s
7e9738d5df
agentson added 1 commit 2026-03-02 09:08:02 +09:00
ci: retrigger after PR traceability update
All checks were successful
Gitea CI / test (push) Successful in 32s
Gitea CI / test (pull_request) Successful in 34s
0fb56a4a1a
Author
Collaborator

PR #387 코드 리뷰 — analysis: reflect cost/execution in v2 backtest pipeline (#368)

범위: BacktestFoldResult에 execution-adjusted 지표 4개 추가 + _simulate_execution_adjusted_return_bps() 구현


통과 항목

1. 기능 구현

  • BacktestFoldResult에 execution_adjusted_avg_return_bps, execution_adjusted_trade_count, execution_rejected_count, execution_partial_count 4개 필드 추가
  • _simulate_execution_adjusted_return_bps(): entry/exit 각각 execution model을 통과시켜 slippage + fill ratio + commission 적용 후 순수익 bps 계산
  • label별 gross return bps 분기 (label=1: take_profit, label=-1: stop_loss, label=0: 0.0)

2. 테스트

  • happy path: 신규 필드 >= 0 타입 검증
  • test_pipeline_fold_scores_reflect_cost_and_execution_effects: conservative_avg_return < optimistic_avg_return 방향성 검증
  • 로컬 실행: 6 passed in 0.12s

3. ruff E501: All checks passed (이전 PR #382 E501 이슈 해소 확인)

4. 문서: REQ-V2-007 ⚠️, 버전 1.0.8


⚠️ 소견 1 — Dead code: 루프 상단 execution_model 초기화 불필요 (Non-blocking)

run_v2_backtest_pipeline() 함수 상단에 아래 코드가 추가됩니다:

execution_model = BacktestExecutionModel(
    ExecutionAssumptions(
        ...,
        seed=0,
    )
)

하지만 fold 루프 첫 번째 반복에서 즉시:

execution_model = _build_execution_model(cost_model=cost_model, fold_seed=fold_idx)

재할당됩니다. 상단의 seed=0 모델은 어느 경로에서도 사용되지 않는 dead code입니다.

권장: 상단 초기화 블록 제거 (validate_backtest_cost_model() 호출 직후 ~ highs = ... 직전 7줄).


⚠️ 소견 2 — 동일 시드 두 모델 (Non-blocking)

fold 루프 내에서 두 모델이 동일 파라미터로 생성됩니다:

execution_model        = _build_execution_model(cost_model=cost_model, fold_seed=fold_idx)
execution_return_model = _build_execution_model(cost_model=cost_model, fold_seed=fold_idx)

각 모델은 독립적인 Random(fold_idx) 인스턴스를 가지므로 동일한 난수 시퀀스를 생성합니다.
execution_model은 B0/B1/M1 score에, execution_return_model은 return 시뮬레이션에 사용됩니다.
두 시뮬레이션이 같은 시드에서 출발하면 결과에 상관관계가 생깁니다.

의도된 설계라면 주석으로 명시를 권장합니다.
독립 시뮬레이션이 목적이라면 fold_seed + offset(예: fold_seed + 1000)으로 시드를 분리하는 것이 더 명확합니다.


결론

LGTM — 기능 구현 및 테스트 통과. Dead code 제거(소견 1)를 반영해 주시면 코드 가독성이 향상됩니다.

## PR #387 코드 리뷰 — analysis: reflect cost/execution in v2 backtest pipeline (#368) **범위**: BacktestFoldResult에 execution-adjusted 지표 4개 추가 + _simulate_execution_adjusted_return_bps() 구현 --- ### ✅ 통과 항목 **1. 기능 구현** - BacktestFoldResult에 execution_adjusted_avg_return_bps, execution_adjusted_trade_count, execution_rejected_count, execution_partial_count 4개 필드 추가 - _simulate_execution_adjusted_return_bps(): entry/exit 각각 execution model을 통과시켜 slippage + fill ratio + commission 적용 후 순수익 bps 계산 - label별 gross return bps 분기 (label=1: take_profit, label=-1: stop_loss, label=0: 0.0) **2. 테스트** - happy path: 신규 필드 >= 0 타입 검증 - test_pipeline_fold_scores_reflect_cost_and_execution_effects: conservative_avg_return < optimistic_avg_return 방향성 검증 - 로컬 실행: 6 passed in 0.12s ✅ **3. ruff E501**: All checks passed ✅ (이전 PR #382 E501 이슈 해소 확인) **4. 문서**: REQ-V2-007 ⚠️ → ✅, 버전 1.0.8 --- ### ⚠️ 소견 1 — Dead code: 루프 상단 execution_model 초기화 불필요 (Non-blocking) run_v2_backtest_pipeline() 함수 상단에 아래 코드가 추가됩니다: execution_model = BacktestExecutionModel( ExecutionAssumptions( ..., seed=0, ) ) 하지만 fold 루프 첫 번째 반복에서 즉시: execution_model = _build_execution_model(cost_model=cost_model, fold_seed=fold_idx) 로 **재할당**됩니다. 상단의 seed=0 모델은 어느 경로에서도 사용되지 않는 dead code입니다. **권장**: 상단 초기화 블록 제거 (validate_backtest_cost_model() 호출 직후 ~ highs = ... 직전 7줄). --- ### ⚠️ 소견 2 — 동일 시드 두 모델 (Non-blocking) fold 루프 내에서 두 모델이 동일 파라미터로 생성됩니다: execution_model = _build_execution_model(cost_model=cost_model, fold_seed=fold_idx) execution_return_model = _build_execution_model(cost_model=cost_model, fold_seed=fold_idx) 각 모델은 독립적인 Random(fold_idx) 인스턴스를 가지므로 동일한 난수 시퀀스를 생성합니다. execution_model은 B0/B1/M1 score에, execution_return_model은 return 시뮬레이션에 사용됩니다. 두 시뮬레이션이 같은 시드에서 출발하면 결과에 상관관계가 생깁니다. 의도된 설계라면 주석으로 명시를 권장합니다. 독립 시뮬레이션이 목적이라면 fold_seed + offset(예: fold_seed + 1000)으로 시드를 분리하는 것이 더 명확합니다. --- ### 결론 **LGTM** — 기능 구현 및 테스트 통과. Dead code 제거(소견 1)를 반영해 주시면 코드 가독성이 향상됩니다.
agentson added 1 commit 2026-03-02 09:17:24 +09:00
analysis: remove dead init and split execution seeds in fold
All checks were successful
Gitea CI / test (push) Successful in 33s
Gitea CI / test (pull_request) Successful in 33s
2776a074b5
Author
Collaborator

리뷰 반영했습니다.

  • 소견 1 반영: run_v2_backtest_pipeline() 상단의 미사용 execution_model 초기화 블록(dead code) 제거
  • 소견 2 반영: fold 내 execution_return_model 시드를 fold_idx + 1000으로 분리해
    baseline score 시뮬레이션(fold_idx)과 return 시뮬레이션 간 난수 시퀀스 상관을 완화

검증:

  • ruff check src/analysis/backtest_pipeline.py tests/test_backtest_pipeline_integration.py
  • pytest -q tests/test_backtest_pipeline_integration.py tests/test_backtest_execution_model.py tests/test_backtest_cost_guard.py
    • 결과: 33 passed
리뷰 반영했습니다. - 소견 1 반영: `run_v2_backtest_pipeline()` 상단의 미사용 `execution_model` 초기화 블록(dead code) 제거 - 소견 2 반영: fold 내 `execution_return_model` 시드를 `fold_idx + 1000`으로 분리해 baseline score 시뮬레이션(`fold_idx`)과 return 시뮬레이션 간 난수 시퀀스 상관을 완화 검증: - `ruff check src/analysis/backtest_pipeline.py tests/test_backtest_pipeline_integration.py` - `pytest -q tests/test_backtest_pipeline_integration.py tests/test_backtest_execution_model.py tests/test_backtest_cost_guard.py` - 결과: `33 passed`
Author
Collaborator

추가 리뷰 — analysis: remove dead init and split execution seeds in fold

커밋: 2776a07

소견 반영 확인

소견 1 (Dead code 제거)
validate_backtest_cost_model() 직후 7줄(seed=0 execution_model 초기화) 삭제 완료.

소견 2 (시드 분리)
execution_return_model의 fold_seed를 fold_idx + 1000으로 분리:

  • execution_model: Random(fold_idx) — B0/B1/M1 score 시뮬레이션
  • execution_return_model: Random(fold_idx + 1000) — return 시뮬레이션

fold_idx 최대값이 walk-forward 설정에 따라 수십 단위이므로 +1000 오프셋은 충분한 분리를 보장합니다.

로컬 실행: 6 passed in 0.12s

LGTM — 추가 소견 없음. 머지 준비 완료.

## 추가 리뷰 — analysis: remove dead init and split execution seeds in fold **커밋**: 2776a07 ### ✅ 소견 반영 확인 **소견 1 (Dead code 제거)** validate_backtest_cost_model() 직후 7줄(seed=0 execution_model 초기화) 삭제 완료. **소견 2 (시드 분리)** execution_return_model의 fold_seed를 fold_idx + 1000으로 분리: - execution_model: Random(fold_idx) — B0/B1/M1 score 시뮬레이션 - execution_return_model: Random(fold_idx + 1000) — return 시뮬레이션 fold_idx 최대값이 walk-forward 설정에 따라 수십 단위이므로 +1000 오프셋은 충분한 분리를 보장합니다. 로컬 실행: 6 passed in 0.12s ✅ **LGTM** — 추가 소견 없음. 머지 준비 완료.
jihoson merged commit f6e4cc7ea9 into feature/v3-session-policy-stream 2026-03-02 09:21:07 +09:00
jihoson deleted branch feature/issue-368-backtest-cost-execution 2026-03-02 09:21:07 +09:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jihoson/The-Ouroboros#387