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.
329 lines
10 KiB
Markdown
329 lines
10 KiB
Markdown
# Experiment Management — `fithia2 exp`
|
|
|
|
전략 실험(experiment) 생성, 검색, 계보 추적, 비교를 위한 관리 시스템.
|
|
|
|
## 개요
|
|
|
|
실험 설정 파일(`configs/experiments/*.json`)에 **메타데이터 필드**를 추가하고, `fithia2 exp` CLI를 통해 체계적으로 관리한다.
|
|
|
|
- **파일 기반 워크플로우 유지** — AI 에이전트가 JSON을 직접 읽고/쓰는 기존 방식과 100% 호환
|
|
- **숫자 ID** — 각 실험에 고유 정수 ID 부여. 모든 커맨드에서 이름 대신 ID 사용 가능
|
|
- **계보(lineage) 추적** — `parent` 필드로 실험 간 ancestor 관계 명시
|
|
- **자동 인덱스** — `.index.json` 캐시로 빠른 검색
|
|
- **journal/registry와 독립** — 결과/스코어는 기존 journal이 source of truth; 메타데이터는 실험 JSON이 source of truth
|
|
|
|
---
|
|
|
|
## 식별자
|
|
|
|
각 실험은 두 가지 식별자를 가진다.
|
|
|
|
| 식별자 | 예시 | 설명 |
|
|
|--------|------|------|
|
|
| **`id`** (숫자) | `228` | 고유 정수 ID. 모든 커맨드에서 이름 대신 사용 가능 |
|
|
| **`experiment_name`** (문자열) | `return_max_long_v6new.362` | 파일명과 동일한 전통적 식별자 |
|
|
|
|
리더보드와 `fithia2 exp search` 출력에는 ID 컬럼이 표시된다. ID는 `fithia2 exp info`, `diff`, `tree`, `promote`, `retire`, `create --parent`, `fithia2 paper start/backtest --config` 등 모든 곳에서 이름 대신 쓸 수 있다.
|
|
|
|
```bash
|
|
# 이름으로
|
|
fithia2 exp info return_max_long_v6new.362
|
|
fithia2 exp diff return_max_long_v6new.362 return_max_long_v6new.376
|
|
fithia2 paper start --config return_max_long_v6new.362 --name my_session
|
|
|
|
# ID로 (동일한 결과)
|
|
fithia2 exp info 228
|
|
fithia2 exp diff 228 242
|
|
fithia2 paper start --config 228 --name my_session
|
|
```
|
|
|
|
---
|
|
|
|
## 실험 JSON 스키마
|
|
|
|
### 기존 필드 (변경 없음)
|
|
```json
|
|
{
|
|
"experiment_name": "return_max_long_v6new.380",
|
|
"dataset_snapshot_id": "midlarge-liquid-long-v1_bucketfix_full_audit_canonical",
|
|
"description": "v362 + tighter entropy cap",
|
|
"base_config": "configs/backtest/return_max_long_v1.json",
|
|
"overrides": { ... },
|
|
"strategy_engines": [ ... ],
|
|
"splits": [ ... ],
|
|
"tags": ["return-max", "v6new"],
|
|
"notes": "..."
|
|
}
|
|
```
|
|
|
|
### 새로 추가된 메타데이터 필드
|
|
```json
|
|
{
|
|
"id": 318,
|
|
"parent": "return_max_long_v6new.362",
|
|
"created_at": "2026-03-27T10:00:00+00:00",
|
|
"created_by": "ai_agent",
|
|
"status": "draft",
|
|
"generation": 6,
|
|
"version_family": "v6new",
|
|
"changelog": "tighter entropy cap on OME",
|
|
"aliases": ["entropy_safe"],
|
|
"performance_summary": {
|
|
"sqs_score": 74.1,
|
|
"public_sqs": 71.3,
|
|
"trade_count_test": 180
|
|
}
|
|
}
|
|
```
|
|
|
|
| 필드 | 타입 | 기본값 | 설명 |
|
|
|------|------|--------|------|
|
|
| `id` | `int \| null` | `null` | **고유 정수 ID** — 새 실험 생성 시 자동 할당 |
|
|
| `parent` | `str \| null` | `null` | 부모 실험 이름 |
|
|
| `created_at` | `str \| null` | `null` | ISO-8601 생성 시각 |
|
|
| `created_by` | `str \| null` | `null` | `"human"` \| `"ai_agent"` \| agent 이름 |
|
|
| `status` | `str` | `"active"` | `draft` \| `active` \| `promoted` \| `retired` |
|
|
| `generation` | `int \| null` | `null` | parent chain 깊이 (root=0) |
|
|
| `version_family` | `str \| null` | `null` | `"v6new"`, `"v8"`, `"v1"` 등 |
|
|
| `changelog` | `str \| null` | `null` | parent 대비 변경 요약 |
|
|
| `aliases` | `list[str]` | `[]` | 사람이 읽기 쉬운 별칭 |
|
|
| `performance_summary` | `dict \| null` | `null` | auto-sync 후 캐시된 SQS 등 |
|
|
|
|
모든 필드가 optional이므로 **기존 파일은 그대로 로딩**된다.
|
|
|
|
### Snapshot 규칙
|
|
|
|
- snapshot registry source of truth는
|
|
[`configs/snapshots/registry.json`](/Users/yirugi/mycloud/personal/workspace/fithia2/configs/snapshots/registry.json)
|
|
이다.
|
|
- canonical physical snapshot은 두 개만 관리한다.
|
|
- `midlarge-liquid-long-v1_bucketfix_full_audit_canonical`
|
|
- `midlarge-liquid-long-v1-oot-2020-2021_canonical`
|
|
- 기존 `..._tier3`, `..._tier3tech`, `..._mom`, `..._tech` 같은 값은 legacy alias로는 계속 허용되지만,
|
|
runtime에서는 canonical snapshot id로 resolve된다.
|
|
- **새 실험은 canonical snapshot id를 직접 쓰는 것이 기본값**이다.
|
|
- phase 1에서는 old manifest bulk rewrite는 하지 않는다.
|
|
즉, 기존 manifest가 legacy alias를 들고 있어도 loader/tracker가 canonical lineage로 흡수한다.
|
|
|
|
---
|
|
|
|
## CLI 커맨드
|
|
|
|
> **모든 커맨드에서 실험 이름 자리에 숫자 ID를 쓸 수 있다.**
|
|
|
|
### `fithia2 exp create` — 새 실험 생성
|
|
|
|
부모 실험을 복사하고 메타데이터를 설정한다. status는 `draft`, ID는 자동 할당.
|
|
|
|
```bash
|
|
fithia2 exp create \
|
|
--parent 228 \
|
|
--name return_max_long_v6new.381 \
|
|
--changelog "entropy cap 0.15→0.10으로 강화"
|
|
```
|
|
|
|
옵션:
|
|
- `--parent` / `-p` (필수) — 부모 실험 이름 또는 ID
|
|
- `--name` / `-n` (필수) — 새 실험 이름
|
|
- `--changelog` / `-c` — 변경 내용 설명
|
|
- `--created-by` — 생성자 (기본값: `"ai_agent"`)
|
|
|
|
생성 후 `configs/experiments/{name}.json`을 열어서 `overrides`와 `strategy_engines`를 수정한다.
|
|
|
|
---
|
|
|
|
### `fithia2 exp search` — 실험 검색
|
|
|
|
```bash
|
|
# 패밀리로 검색
|
|
fithia2 exp search --family v6new
|
|
|
|
# 태그 + 상태로 필터
|
|
fithia2 exp search --tag entropy --status active
|
|
|
|
# 부모로 검색 (직접 자식만)
|
|
fithia2 exp search --parent 228
|
|
|
|
# 이름 패턴 (regex)
|
|
fithia2 exp search --pattern "v6new\.3[5-9]\d$"
|
|
```
|
|
|
|
출력: **ID** / 이름 / 상태 / 패밀리 / generation / parent / SQS / aliases / tags
|
|
|
|
---
|
|
|
|
### `fithia2 exp tree` — 계보 트리
|
|
|
|
```bash
|
|
fithia2 exp tree 228
|
|
```
|
|
|
|
출력 예시:
|
|
```
|
|
return_max_long_v6new.362 [active] SQS=74.7
|
|
├── return_max_long_v6new.363
|
|
├── return_max_long_v6new.373
|
|
│ └── return_max_long_v6new.374
|
|
└── return_max_long_v6new.380
|
|
```
|
|
|
|
---
|
|
|
|
### `fithia2 exp info` — 상세 조회
|
|
|
|
```bash
|
|
fithia2 exp info 228
|
|
```
|
|
|
|
실험 ID, 메타데이터, journal 교차참조 결과(entry_id, sqs_score, rqs_score 등)를 한 화면에 표시한다.
|
|
|
|
---
|
|
|
|
### `fithia2 exp diff` — 두 실험 비교
|
|
|
|
```bash
|
|
fithia2 exp diff 228 242
|
|
```
|
|
|
|
`overrides`의 파라미터 변경, engine별 on/off 및 파라미터 변경을 표시한다.
|
|
메타데이터 필드(parent, created_at 등)는 diff에서 제외된다.
|
|
|
|
---
|
|
|
|
### `fithia2 exp promote` — 실험 승격
|
|
|
|
```bash
|
|
fithia2 exp promote 228 --alias my_best
|
|
```
|
|
|
|
status를 `promoted`로 변경. `--alias`로 별칭 추가 가능.
|
|
|
|
---
|
|
|
|
### `fithia2 exp retire` — 실험 은퇴
|
|
|
|
```bash
|
|
fithia2 exp retire 228
|
|
```
|
|
|
|
status를 `retired`로 변경.
|
|
|
|
---
|
|
|
|
### `fithia2 exp validate` — 스키마 검증
|
|
|
|
```bash
|
|
fithia2 exp validate
|
|
```
|
|
|
|
검사 항목:
|
|
- Pydantic 스키마 유효성
|
|
- `base_config` 파일 존재 여부
|
|
- `parent` 참조가 실제 존재하는지
|
|
- `experiment_name`이 파일명과 일치하는지
|
|
- `status` 값이 유효한지
|
|
|
|
---
|
|
|
|
### `fithia2 exp migrate` — 기존 파일 메타데이터 백필
|
|
|
|
기존 실험 파일에 메타데이터를 자동으로 추가한다. ID도 이 커맨드로 일괄 부여된다.
|
|
|
|
```bash
|
|
# 먼저 dry-run으로 확인
|
|
fithia2 exp migrate --dry-run
|
|
|
|
# 실제 적용
|
|
fithia2 exp migrate
|
|
```
|
|
|
|
자동 추론/처리 내용:
|
|
- `id` — 파일명 알파벳 순 기준으로 순차 정수 할당
|
|
- `version_family` — 파일명 regex에서 추출
|
|
- `parent` — description 텍스트 패턴 분석
|
|
- `[v312+] ...` 또는 `v288 + ...` 형태에서 부모 버전 번호 추출
|
|
- `Derivative of NAME` 형태에서 직접 추출
|
|
- `created_at` — git log에서 파일의 최초 커밋 시각 (없으면 파일 mtime)
|
|
- `generation` — parent chain에서 계산
|
|
- `changelog` — description에서 부모 참조 이후 텍스트 추출
|
|
- `created_by` — `"human"` (기존 파일 보수적 기본값)
|
|
- `status` — `"active"` (기존 파일 기본값)
|
|
|
|
---
|
|
|
|
### `fithia2 exp rebuild-index` — 인덱스 재생성
|
|
|
|
```bash
|
|
fithia2 exp rebuild-index
|
|
```
|
|
|
|
`configs/experiments/.index.json`을 강제 재생성한다. 일반적으로 자동 처리되지만, 파일을 직접 수정한 후 검색 결과가 stale하다면 수동으로 실행.
|
|
|
|
---
|
|
|
|
## `fithia2 paper`에서 ID 사용
|
|
|
|
`--config` 옵션에 숫자 ID, 실험 이름, 파일 경로 모두 사용할 수 있다.
|
|
|
|
```bash
|
|
# 세 가지 형태 모두 동일
|
|
fithia2 paper start --config 228 --name my_session
|
|
fithia2 paper start --config return_max_long_v6new.362 --name my_session
|
|
fithia2 paper start --config configs/experiments/return_max_long_v6new.362.json --name my_session
|
|
|
|
# backtest도 동일
|
|
fithia2 paper backtest --config 228 --year 2025
|
|
fithia2 paper backtest --config 228 --config 242 --year 2025
|
|
```
|
|
|
|
---
|
|
|
|
## AI 에이전트 워크플로우
|
|
|
|
### 새 실험 만들 때
|
|
|
|
```bash
|
|
# 1. 부모에서 스캐폴딩 (ID 또는 이름)
|
|
fithia2 exp create --parent 228 --name return_max_long_v6new.381 \
|
|
--changelog "broad_oneoff engine risk 0.008→0.012"
|
|
# → ID 자동 할당, status=draft로 생성
|
|
|
|
# 2. JSON 수정 (overrides / strategy_engines 조정)
|
|
# configs/experiments/return_max_long_v6new.381.json 편집
|
|
|
|
# 3. 백테스트 실행 (기존과 동일)
|
|
python -m apps.backtester.run --manifest configs/experiments/return_max_long_v6new.381.json --split train
|
|
python -m apps.backtester.run --manifest configs/experiments/return_max_long_v6new.381.json --split valid
|
|
python -m apps.backtester.run --manifest configs/experiments/return_max_long_v6new.381.json --split test
|
|
|
|
# 4. 결과 등록 — auto-sync가 draft→active로 자동 전환 + performance_summary 캐시
|
|
fithia2 record -e return_max_long_v6new.381 -H "..." -v better
|
|
```
|
|
|
|
### 기존 방식 유지 (JSON 직접 작성)
|
|
|
|
`fithia2 exp create` 없이 JSON을 직접 만들어도 된다. `id` 필드를 넣지 않으면 `fithia2 exp migrate`로 나중에 일괄 부여할 수 있다.
|
|
|
|
---
|
|
|
|
## status 전환 흐름
|
|
|
|
```
|
|
draft → active (백테스트 완료 후 auto-sync가 자동 전환)
|
|
→ promoted (fithia2 exp promote)
|
|
active → retired (fithia2 exp retire)
|
|
```
|
|
|
|
---
|
|
|
|
## 구현 파일
|
|
|
|
| 파일 | 역할 |
|
|
|------|------|
|
|
| `libs/backtest/experiments.py` | 핵심 라이브러리 (create, search, tree, diff, migrate, validate, index, resolve_experiment_name) |
|
|
| `apps/experiment/cli.py` | `fithia2 exp` CLI |
|
|
| `apps/paper_trader/cli.py` | `_resolve_config_path`: `--config`에서 ID/이름/경로 모두 지원 |
|
|
| `libs/backtest/domain.py` | `ExperimentManifest` 스키마 (메타데이터 필드 포함) |
|
|
| `libs/backtest/tracker.py` | `sync_official_manifests`: auto-sync 후 `performance_summary` 자동 업데이트, 리더보드에 ID 컬럼 추가 |
|
|
| `configs/experiments/.index.json` | 메타데이터 인덱스 캐시 (자동 관리) |
|