feat: backtest multi-timeframe coverage - import timeframe contract & archive migration
This commit is contained in:
parent
e5bb46aaab
commit
dfabb9bfef
7 changed files with 112 additions and 30 deletions
|
|
@ -35,40 +35,40 @@ task=m-backtest-multi-timeframe-coverage/01_import_timeframe_contract, plan=0, t
|
|||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [API-1] ImportDailyBarsRequest Timeframe Field | [ ] |
|
||||
| [API-1] ImportDailyBarsRequest Timeframe Field | [x] |
|
||||
|
||||
## 구현 체크리스트
|
||||
|
||||
- [ ] `packages/contracts/proto/alt/v1/market.proto`의 `ImportDailyBarsRequest`에 additive `Timeframe timeframe = 9;`를 추가한다.
|
||||
- [ ] `bin/contracts-gen`으로 Go/Dart generated contracts를 갱신한다. generated 파일은 손으로 수정하지 않는다.
|
||||
- [ ] `bin/contracts-check`와 `go test ./packages/contracts/gen/go/...`를 실행해 generated drift와 compile을 확인한다.
|
||||
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
- [x] `packages/contracts/proto/alt/v1/market.proto`의 `ImportDailyBarsRequest`에 additive `Timeframe timeframe = 9;`를 추가한다.
|
||||
- [x] `bin/contracts-gen`으로 Go/Dart generated contracts를 갱신한다. generated 파일은 손으로 수정하지 않는다.
|
||||
- [x] `bin/contracts-check`와 `go test ./packages/contracts/gen/go/...`를 실행해 generated drift와 compile을 확인한다.
|
||||
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
|
||||
|
||||
## 코드리뷰 전용 체크리스트
|
||||
|
||||
> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
|
||||
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.
|
||||
|
||||
- [ ] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
|
||||
- [ ] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
|
||||
- [ ] active `CODE_REVIEW-*-G??.md`를 `code_review_local_G06_N.log`로 아카이브한다.
|
||||
- [ ] active `PLAN-*-G??.md`를 `plan_local_G06_M.log`로 아카이브한다.
|
||||
- [ ] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
|
||||
- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
|
||||
- [ ] PASS이면 active task 디렉터리 `agent-task/m-backtest-multi-timeframe-coverage/01_import_timeframe_contract/`를 `agent-task/archive/YYYY/MM/m-backtest-multi-timeframe-coverage/01_import_timeframe_contract/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
|
||||
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
|
||||
- [ ] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-backtest-multi-timeframe-coverage/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
|
||||
- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
|
||||
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
|
||||
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_local_G06_N.log`로 아카이브한다.
|
||||
- [x] active `PLAN-*-G??.md`를 `plan_local_G06_M.log`로 아카이브한다.
|
||||
- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다.
|
||||
- [x] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
|
||||
- [x] PASS이면 active task 디렉터리 `agent-task/m-backtest-multi-timeframe-coverage/01_import_timeframe_contract/`를 `agent-task/archive/YYYY/MM/m-backtest-multi-timeframe-coverage/01_import_timeframe_contract/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
|
||||
- [x] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
|
||||
- [x] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-backtest-multi-timeframe-coverage/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
|
||||
- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-local-G06.md`와 `CODE_REVIEW-local-G06.md`를 작성하고 `complete.log`를 작성하지 않는다.
|
||||
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.
|
||||
- [ ] USER_REVIEW가 연결된 SDD/Milestone 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다.
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._
|
||||
계획에 따라 정확히 구현했다. 추가 변경 사항 없음.
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
_구현 에이전트가 주요 설계 결정 사항을 기록한다._
|
||||
없음. 계획에 따라 additive 필드 하나만 추가하는 단순 변경이다.
|
||||
|
||||
## 사용자 리뷰 요청
|
||||
|
||||
|
|
@ -102,21 +102,22 @@ _구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후
|
|||
### API-1 중간 검증
|
||||
```bash
|
||||
$ bin/contracts-gen
|
||||
(output)
|
||||
$ bin/contracts-check
|
||||
(output)
|
||||
$ go test ./packages/contracts/gen/go/...
|
||||
(output)
|
||||
? git.toki-labs.com/toki/alt/packages/contracts/gen/go/alt/v1 [no test files]
|
||||
```
|
||||
|
||||
모든 명령이 exit code 0으로 성공했다.
|
||||
|
||||
### 최종 검증
|
||||
```bash
|
||||
$ bin/contracts-check
|
||||
(output)
|
||||
$ go test ./packages/contracts/gen/go/...
|
||||
(output)
|
||||
? git.toki-labs.com/toki/alt/packages/contracts/gen/go/alt/v1 [no test files]
|
||||
```
|
||||
|
||||
모든 명령이 exit code 0으로 성공했다. generated drift 없으며, Go contract package가 정상적으로 컴파일된다.
|
||||
|
||||
---
|
||||
|
||||
> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
|
||||
|
|
@ -135,3 +136,17 @@ $ go test ./packages/contracts/gen/go/...
|
|||
| 사용자 리뷰 요청 | Implementing agent | Keep `상태: 없음` unless selected SDD/Milestone lock decision blocks implementation |
|
||||
| 리뷰어를 위한 체크포인트 | Fixed at stub creation | Review focus |
|
||||
| 검증 결과 | Implementing agent | Paste actual stdout/stderr |
|
||||
|
||||
## 코드리뷰 결과
|
||||
|
||||
- 종합 판정: PASS
|
||||
- 차원별 평가:
|
||||
- correctness: Pass
|
||||
- completeness: Pass
|
||||
- test coverage: Pass
|
||||
- API contract: Pass
|
||||
- code quality: Pass
|
||||
- plan deviation: Pass
|
||||
- verification trust: Pass
|
||||
- 발견된 문제: 없음
|
||||
- 다음 단계: PASS 종결. `complete.log` 작성 후 task directory를 archive로 이동한다.
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# Complete - m-backtest-multi-timeframe-coverage/01_import_timeframe_contract
|
||||
|
||||
## 완료 일시
|
||||
|
||||
2026-06-18
|
||||
|
||||
## 요약
|
||||
|
||||
ImportDailyBarsRequest에 additive timeframe contract field를 추가하고 generated Go/Dart contracts를 갱신한 1회 루프를 PASS로 종결했다.
|
||||
|
||||
## 루프 이력
|
||||
|
||||
| Plan | Review | Verdict | 메모 |
|
||||
|------|--------|---------|------|
|
||||
| `plan_local_G06_0.log` | `code_review_local_G06_0.log` | PASS | Additive proto field와 generated output 검증 통과 |
|
||||
|
||||
## 구현/정리 내용
|
||||
|
||||
- `ImportDailyBarsRequest`에 `Timeframe timeframe = 9;`를 추가했다.
|
||||
- `bin/contracts-gen` 결과로 Go/Dart generated contract output을 갱신했다.
|
||||
- downstream worker/API behavior 변경은 의도적으로 후속 split task 범위로 남겼다.
|
||||
|
||||
## 최종 검증
|
||||
|
||||
- `bin/contracts-check` - PASS; output 없음, generated drift 없음.
|
||||
- `go test ./packages/contracts/gen/go/...` - PASS; `? git.toki-labs.com/toki/alt/packages/contracts/gen/go/alt/v1 [no test files]`.
|
||||
- `bin/lint` - PASS; exit code 0, 기존 `avoid_print` info 13건 출력.
|
||||
|
||||
## 잔여 Nit
|
||||
|
||||
- 없음
|
||||
|
||||
## 후속 작업
|
||||
|
||||
- 없음
|
||||
|
|
@ -730,6 +730,7 @@ class ImportDailyBarsRequest extends $pb.GeneratedMessage {
|
|||
$core.Iterable<$core.String>? symbols,
|
||||
$core.String? fromYyyymmdd,
|
||||
$core.String? toYyyymmdd,
|
||||
$0.Timeframe? timeframe,
|
||||
}) {
|
||||
final result = create();
|
||||
if (provider != null) result.provider = provider;
|
||||
|
|
@ -740,6 +741,7 @@ class ImportDailyBarsRequest extends $pb.GeneratedMessage {
|
|||
if (symbols != null) result.symbols.addAll(symbols);
|
||||
if (fromYyyymmdd != null) result.fromYyyymmdd = fromYyyymmdd;
|
||||
if (toYyyymmdd != null) result.toYyyymmdd = toYyyymmdd;
|
||||
if (timeframe != null) result.timeframe = timeframe;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -766,6 +768,8 @@ class ImportDailyBarsRequest extends $pb.GeneratedMessage {
|
|||
..pPS(6, _omitFieldNames ? '' : 'symbols')
|
||||
..aOS(7, _omitFieldNames ? '' : 'fromYyyymmdd')
|
||||
..aOS(8, _omitFieldNames ? '' : 'toYyyymmdd')
|
||||
..aE<$0.Timeframe>(9, _omitFieldNames ? '' : 'timeframe',
|
||||
enumValues: $0.Timeframe.values)
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
|
|
@ -853,6 +857,15 @@ class ImportDailyBarsRequest extends $pb.GeneratedMessage {
|
|||
$core.bool hasToYyyymmdd() => $_has(7);
|
||||
@$pb.TagNumber(8)
|
||||
void clearToYyyymmdd() => $_clearField(8);
|
||||
|
||||
@$pb.TagNumber(9)
|
||||
$0.Timeframe get timeframe => $_getN(8);
|
||||
@$pb.TagNumber(9)
|
||||
set timeframe($0.Timeframe value) => $_setField(9, value);
|
||||
@$pb.TagNumber(9)
|
||||
$core.bool hasTimeframe() => $_has(8);
|
||||
@$pb.TagNumber(9)
|
||||
void clearTimeframe() => $_clearField(9);
|
||||
}
|
||||
|
||||
class ImportDailyBarsResponse extends $pb.GeneratedMessage {
|
||||
|
|
|
|||
|
|
@ -302,6 +302,14 @@ const ImportDailyBarsRequest$json = {
|
|||
{'1': 'symbols', '3': 6, '4': 3, '5': 9, '10': 'symbols'},
|
||||
{'1': 'from_yyyymmdd', '3': 7, '4': 1, '5': 9, '10': 'fromYyyymmdd'},
|
||||
{'1': 'to_yyyymmdd', '3': 8, '4': 1, '5': 9, '10': 'toYyyymmdd'},
|
||||
{
|
||||
'1': 'timeframe',
|
||||
'3': 9,
|
||||
'4': 1,
|
||||
'5': 14,
|
||||
'6': '.alt.v1.Timeframe',
|
||||
'10': 'timeframe'
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
|
@ -312,7 +320,7 @@ final $typed_data.Uint8List importDailyBarsRequestDescriptor = $convert.base64De
|
|||
'LnYxLk1hcmtldFIGbWFya2V0EiMKBXZlbnVlGAQgASgOMg0uYWx0LnYxLlZlbnVlUgV2ZW51ZR'
|
||||
'ISCgRuYW1lGAUgASgJUgRuYW1lEhgKB3N5bWJvbHMYBiADKAlSB3N5bWJvbHMSIwoNZnJvbV95'
|
||||
'eXl5bW1kZBgHIAEoCVIMZnJvbVl5eXltbWRkEh8KC3RvX3l5eXltbWRkGAggASgJUgp0b1l5eX'
|
||||
'ltbWRk');
|
||||
'ltbWRkEi8KCXRpbWVmcmFtZRgJIAEoDjIRLmFsdC52MS5UaW1lZnJhbWVSCXRpbWVmcmFtZQ==');
|
||||
|
||||
@$core.Deprecated('Use importDailyBarsResponseDescriptor instead')
|
||||
const ImportDailyBarsResponse$json = {
|
||||
|
|
|
|||
|
|
@ -551,6 +551,7 @@ type ImportDailyBarsRequest struct {
|
|||
Symbols []string `protobuf:"bytes,6,rep,name=symbols,proto3" json:"symbols,omitempty"`
|
||||
FromYyyymmdd string `protobuf:"bytes,7,opt,name=from_yyyymmdd,json=fromYyyymmdd,proto3" json:"from_yyyymmdd,omitempty"`
|
||||
ToYyyymmdd string `protobuf:"bytes,8,opt,name=to_yyyymmdd,json=toYyyymmdd,proto3" json:"to_yyyymmdd,omitempty"`
|
||||
Timeframe Timeframe `protobuf:"varint,9,opt,name=timeframe,proto3,enum=alt.v1.Timeframe" json:"timeframe,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
|
@ -641,6 +642,13 @@ func (x *ImportDailyBarsRequest) GetToYyyymmdd() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func (x *ImportDailyBarsRequest) GetTimeframe() Timeframe {
|
||||
if x != nil {
|
||||
return x.Timeframe
|
||||
}
|
||||
return Timeframe_TIMEFRAME_UNSPECIFIED
|
||||
}
|
||||
|
||||
type ImportDailyBarsResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Provider string `protobuf:"bytes,1,opt,name=provider,proto3" json:"provider,omitempty"`
|
||||
|
|
@ -757,7 +765,7 @@ const file_alt_v1_market_proto_rawDesc = "" +
|
|||
"to_unix_ms\x18\x04 \x01(\x03R\btoUnixMs\"\\\n" +
|
||||
"\x10ListBarsResponse\x12\x1f\n" +
|
||||
"\x04bars\x18\x01 \x03(\v2\v.alt.v1.BarR\x04bars\x12'\n" +
|
||||
"\x05error\x18\x02 \x01(\v2\x11.alt.v1.ErrorInfoR\x05error\"\x9a\x02\n" +
|
||||
"\x05error\x18\x02 \x01(\v2\x11.alt.v1.ErrorInfoR\x05error\"\xcb\x02\n" +
|
||||
"\x16ImportDailyBarsRequest\x12\x1a\n" +
|
||||
"\bprovider\x18\x01 \x01(\tR\bprovider\x12#\n" +
|
||||
"\rselector_kind\x18\x02 \x01(\tR\fselectorKind\x12&\n" +
|
||||
|
|
@ -767,7 +775,8 @@ const file_alt_v1_market_proto_rawDesc = "" +
|
|||
"\asymbols\x18\x06 \x03(\tR\asymbols\x12#\n" +
|
||||
"\rfrom_yyyymmdd\x18\a \x01(\tR\ffromYyyymmdd\x12\x1f\n" +
|
||||
"\vto_yyyymmdd\x18\b \x01(\tR\n" +
|
||||
"toYyyymmdd\"\xa6\x01\n" +
|
||||
"toYyyymmdd\x12/\n" +
|
||||
"\ttimeframe\x18\t \x01(\x0e2\x11.alt.v1.TimeframeR\ttimeframe\"\xa6\x01\n" +
|
||||
"\x17ImportDailyBarsResponse\x12\x1a\n" +
|
||||
"\bprovider\x18\x01 \x01(\tR\bprovider\x12)\n" +
|
||||
"\x10instrument_count\x18\x02 \x01(\x05R\x0finstrumentCount\x12\x1b\n" +
|
||||
|
|
@ -830,12 +839,13 @@ var file_alt_v1_market_proto_depIdxs = []int32{
|
|||
17, // 19: alt.v1.ListBarsResponse.error:type_name -> alt.v1.ErrorInfo
|
||||
11, // 20: alt.v1.ImportDailyBarsRequest.market:type_name -> alt.v1.Market
|
||||
12, // 21: alt.v1.ImportDailyBarsRequest.venue:type_name -> alt.v1.Venue
|
||||
17, // 22: alt.v1.ImportDailyBarsResponse.error:type_name -> alt.v1.ErrorInfo
|
||||
23, // [23:23] is the sub-list for method output_type
|
||||
23, // [23:23] is the sub-list for method input_type
|
||||
23, // [23:23] is the sub-list for extension type_name
|
||||
23, // [23:23] is the sub-list for extension extendee
|
||||
0, // [0:23] is the sub-list for field type_name
|
||||
16, // 22: alt.v1.ImportDailyBarsRequest.timeframe:type_name -> alt.v1.Timeframe
|
||||
17, // 23: alt.v1.ImportDailyBarsResponse.error:type_name -> alt.v1.ErrorInfo
|
||||
24, // [24:24] is the sub-list for method output_type
|
||||
24, // [24:24] is the sub-list for method input_type
|
||||
24, // [24:24] is the sub-list for extension type_name
|
||||
24, // [24:24] is the sub-list for extension extendee
|
||||
0, // [0:24] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_alt_v1_market_proto_init() }
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ message ImportDailyBarsRequest {
|
|||
repeated string symbols = 6;
|
||||
string from_yyyymmdd = 7;
|
||||
string to_yyyymmdd = 8;
|
||||
Timeframe timeframe = 9;
|
||||
}
|
||||
|
||||
message ImportDailyBarsResponse {
|
||||
|
|
|
|||
Loading…
Reference in a new issue