# A축 01~08편 — 기록된 산출물을 시험 주문에 **진짜로 POST 했다** (Part 1)

## 환경 고지

- **격리 임시 PostgreSQL 클러스터** (`weltiq_xfer1`, 포트 55541, 유닉스 소켓만) · **합성 호가만** ·
  **운영 배포 아님 · 운영 DB·운영 `.env` 아님 · 실계좌 아님 · 외부 거래소 주문 아님.**
- **도구를 새로 설치하지 않았다.** 검증 대상은 **이관(interface)** 이고 입력은 이미
  `docs/tutorials/a/0N-*.md` 와 `reports/a/*/RUN-LOG.md` 에 기록돼 있다. 이 문서에 쓴 원본 값은 전부
  그 두 곳의 인용이며, 문서에 없는 값은 **「사람이 더한 것」으로 표시**했다.
- 커밋 `ef529e4c9bc9d842329769abbd9f597d324b57e0` · 실행 **2026-09-28 01:27:34 ~ 01:29:15 KST** (101초) ·
  **33 케이스 전부 실제 HTTP POST**. 원문은 [`part1-evidence.json`](part1-evidence.json), 재현은
  [`run_part1.py`](run_part1.py). `initdb.txt`·`start.txt`·`schema.txt`·`migrate.txt`·`stop.txt` 는
  같은 디렉터리의 다른 Part 하네스와 **파일명이 겹친다** (마지막에 끝난 실행의 것이 남는다) —
  Part 1 의 증거는 `part1-evidence.json` 하나로 자족한다.
- 라이선스는 **운영 실측과 같게** 맞췄다 — `market.license` 에 `krx` **open** · `us-equity` **open** ·
  `cme` **`license_pending` 그대로**. 갓 만든 DB 의 기본값(셋 다 pending)을 쓰지 않았다.
- `market.listings` 에 넣은 것 4행 (전부 `tradable=true`): `BTCUSDT`(crypto, price_venue `binance-spot`,
  alt `binance-usdm`) · `ETHUSDT`(crypto, 같음) · `AAPL`(us_stock, `us-equity`) · `MSFT`(us_stock, `us-equity`).
- **합성 호가는 그 편의 기록 가격대에 맞췄다.** 두 번 바꿨고 두 번 다 `events` 에 남겼다:
  - P0 `binance-spot BTCUSDT 71610.33/71610.34` (06편 첫 매매 진입가) · `ETHUSDT 2728.80/2728.81` (04편) ·
    `binance-usdm BTCUSDT 85430.9/85431.0` (03편 체결가) · `AAPL 308.91/308.92` · `MSFT 464.72/464.73` (02편)
  - P1 `binance-spot BTCUSDT → 85350.00/85350.01` (03·04·05·08편 가격대)
  - P2 `binance-spot BTCUSDT → 83790.00` · `binance-usdm BTCUSDT → 82790.0` (등록된 손절을 실제로 발동시키려고)
- **실행일이 일요일이라 `us-equity` 4건은 접수 뒤 배치에서 거절됐다** (`rejected:market_closed`).
  거래소 성능이 아니라 세션 달력이고, 한도는 `delta=-1` 로 4회 복원됐다 (13 접수 − 4 = **9회 차감**).
- **본계좌 9개 표 전량 비교 완전 동일** (`account_unchanged: true`).

---

## 판정 표

판정: **PASS**(그대로) · **PASS-반올림**(틱/로트 보정 후) · **PASS-보강**(사람이 더해야) · **FAIL** · **N/A**

| 편 | 쓴 원본 값의 출처 | 손댄 것 | 판정 | 응답 코드·사유 |
|---|---|---|---|---|
| **01** alpaca-mcp-server | 4-2 브래킷 — 부모 `limit 300` · 익절 `limit 360` · 손절 `stop 285` · `tif gtc`. 4-1 첫 주문 `{"symbol":"AAPL","qty":"1","side":"buy","order_type":"market"}` | 360·285 는 틱 0.01 배수라 **그대로**. 수량 1 은 보낼 자리 없음. **시한을 사람이 더했다**(`close_after_seconds=259200`) | **PASS-보강** | 01a 시한 없이 `422 exit_plan_deadline_required` · 01b `max_duration_hours=72` 만 → **또 `422` 같은 코드** · 01c 시한 더하고 `201` qty `1` · 01d 시장가 진입 `201` · **01e `max_duration_hours=2160`(3개월) → `422 invalid_max_duration_hours` (1..168)** |
| **02** ai-hedge-fund | 5절 최종 주문 — `AAPL 공매도 80주 @ $308.91` · `MSFT 매수 32주 @ $464.72` (목표비중 −0.353 → 리스크 −0.25 / +0.153) | 방향만 옮김. **80주·32주 → 서버가 1주**. 목표가·손절가·시한이 **도구 기록에 아예 없다** → 시한을 사람이 더함 | **PASS-보강** | 02a `422 exit_plan_deadline_required` · 02b `max_duration_hours=168` 만 → **또 `422`** · 02c 시한 더해 `201` `side:"short"` qty `1` · 02d `201`. 넷 다 배치에서 `rejected:market_closed` (일요일) |
| **03** LLM-Auto-Trader | RUN-LOG:143 `[ASK] OPEN_LONG BTC/USDT:USDT size_pct=12.0 lev=3 sl=82800.0 tp=89400.0`. RUN-LOG:193 `ADJUST_SL sl=83900.0 tp=92000.0` | `BTC/USDT:USDT`→`binance-usdm BTCUSDT`. 82800.0·89400.0 은 틱 0.1 배수라 **그대로**. `size_pct`·`leverage 3` 은 보낼 자리 없음. 시한을 사람이 더함(`900s` = 봇의 `next_check=15` 분) | **PASS-보강** | 03a `422 exit_plan_deadline_required` · 03b `max_duration_hours=24` 만 → **또 `422`** · 03c `201` qty `0.001` → **왕복 완결**: `close_reason=stop_loss`, `exit_trigger_px=82790.0`, 체결 82781.670995 · 03d(2차 값) 동일 |
| **04** freqtrade | RUN-LOG:366~371 `open_rate 85198.18` · `stop_loss_abs 85155.59 (-0.05%)` · `close_rate 85145.81` · `exit_reason stop_loss`. `tight-stop.json {"stoploss": -0.0005}`. RUN-LOG:296~298 ETH/USDT `0.0366 @ 2728.80` → 34초 뒤 `2725.35` | **여기만 반올림이 필요했다** — freqtrade 가 내는 것은 **비율**이라 −0.0005 × 85198.18 = `85155.590909` 다. 목표가는 `minimal_roi {"0":100}` 라 낼 값 없음. 시한을 사람이 더함 | **PASS-반올림 + 보강** | 04a `422 exit_plan_deadline_required` · 04b 같은 코드(시한 검증이 가격 검증보다 **앞선다**) · **04b2 `422 invalid_stop_loss` — `"85155.590909 is not a multiple of tick 0.01"`** · 04c 반올림 후 `201` → `close_reason=stop_loss` `exit_trigger_px=83790.00` · 04d ETH `201` → `close_reason=close_after` |
| **05** claude-trading-skills | 3절 표 1차 규칙 `entry_level 85,350` · `stop_loss 83,800` · `take_profit 88,200` · `quantity_btc 0.116`. 2차 `86,050 / 84,600 / 88,800 / 0.10` | 네 레벨 전부 틱 0.01 배수라 **그대로**. **0.116 BTC → 서버가 0.00008 BTC** (1,450배 축소). 시한을 사람이 더함 — **이 편이 단점으로 직접 적은 그 빈칸이다** | **PASS-보강** | 05a `422 exit_plan_deadline_required` · 05b `max_duration_hours=24` 만 → **또 `422`** · 05c `201` → `close_reason=stop_loss` `exit_trigger_px=83790.00` · 05d(2차 규칙) 동일 |
| **06** jesse | 4절 첫 매매 `71610.33 BUY MARKET · Executed 0.14` → `72952.85 SELL MARKET`, 보유 71시간 +1.67%. 전략 = SMA 20/50 교차 · 스팟 롱 전용 · **ATR×2 손절(숫자 없음)** | **계획 레벨이 하나도 없다** — 기록된 가격은 전부 실현 체결가다. 수량 0.14 도 자리 없음. 사람이 기록된 보유 71h 를 `close_after_seconds=255600` 으로 옮김 | **PASS-보강** | 06a `422 exit_plan_deadline_required` · 06b `max_duration_hours=71` 만 → **또 `422`** · 06c `201` qty `0.00009` 진입 체결 71617.5060335 · 06d(실현 청산가를 목표가로) `201` → `take_profit` 발동 |
| **07** CloddsBot | 4-1 색인 `Polymarket 300 · Kalshi 300 · Manifold 94 = 694`. 4-2 ① `validateTrade(size=80, price=1.0) → {"allowed":true}`. **주문 0건** | 없다. 옮길 시장이 없고 옮길 레벨이 없다 | **N/A** (시장 불일치) | 07a `venue="polymarket"` → **`422 market_not_licensed` `status:"off"`** (모르는 venue 는 fail-closed) · 07b 유일한 주문 모양 숫자 `size=80` 을 `qty` 로 → `422 extra_forbidden` |
| **08** CoinRithm | 4절 견적 요청 원문 `{"coinId":"1","side":"buy","quantity":0.001}` (BTC = UCID `"1"`) | `coinId "1"`→`BTCUSDT`, `side buy`→`long`. **`quantity` 를 버려야 통과한다.** 손절 필드는 저쪽 현물 스키마에 **아예 없다**. 시한을 사람이 더함(60s) | **PASS-보강** (수량 버림) | 08a `qty` 그대로 → `422 extra_forbidden` · 08b qty 빼고 시한 없이 → `422 exit_plan_deadline_required` · 08c `201` → `close_reason=close_after` |

**서버가 정한 기준 수량 (실측)**: `binance-spot BTCUSDT` ref 85350.005 → **0.00008** (lot 0.00001 · min_notional 5 ·
notional 6.83) / ref 71610.335 → **0.00009** · `binance-spot ETHUSDT` ref 2728.805 → **0.0023** (lot 0.0001) ·
`binance-usdm BTCUSDT` ref 85430.95 → **0.001** (min_notional 50 · notional 85.4) · `us-equity` → **1주**
(`one_share_or_contract`).

---

## 편별

### 01편 alpaca-mcp-server — PASS-보강, 그리고 **수명을 못 옮긴다**
브래킷 3다리가 시험 주문 한 건으로 1:1 접힌다: 진입 `type="limit"`/`limit_price="300"`, `take_profit="360"`,
`stop_loss="285"`. 세 숫자 전부 us-equity 틱 0.01 의 배수라 **손댄 것이 없다**.
막힌 것은 **시간**이다 — 알파카 브래킷은 `time_in_force: gtc` 로 「취소할 때까지」이고 기사가 「3개월 감시」라고
적었는데, 그 수명을 `max_duration_hours=2160` 으로 표현하면 **`422 invalid_max_duration_hours` (1..168)** 다.
이 편의 간판 장점(기계를 꺼도 서버가 3개월 지킨다)은 **시험 주문으로 7일까지만 옮겨진다.**
그리고 진입 지정가 300 이 ask 308.92 에서 미체결로 남는지는 **못 쟀다** — 일요일이라 배치가 먼저 거절됐다.

### 02편 ai-hedge-fund — PASS-보강, 숏은 통과했고 비중은 사라졌다
`AAPL side="short"` 가 `201` 로 접수됐다 (`qty "1"`). 방향이 안 버려진다는 것은 실측이다.
대가는 표에 적은 대로다 — 80주가 1주, 32주가 1주가 되어 **AAPL:MSFT 비중 비가 완전히 사라진다.**
그리고 이 도구는 **목표가·손절가·시한을 하나도 내지 않는다.** 시한을 사람이 넣는 순간 「도구가 하지 않은 판단」이
생기므로, 02편의 이관은 **방향 이관**이고 계획 이관이 아니다.

### 03편 LLM-Auto-Trader — PASS-보강, 01~08 중 **가장 깨끗하게** 옮겨진다
`sl=82800.0 tp=89400.0` 이 그대로 `exit_plan` 에 앉고(틱 0.1 배수), 왕복이 끝까지 돌았다:
진입 85439.593095 → 손절 발동 `exit_trigger_px=82790.0` (01:27:44.540851) → 청산 체결 **82781.670995**
(01:27:45.574518, 1.03초 뒤) · 수수료 0.08411064 · `net_pnl −2.742032740`.
**조건 성립가와 체결가가 다르다**는 계약이 이 편의 실제 값으로 확인된다.
손절 이동 판단(`ADJUST_SL sl=83900.0 tp=92000.0`)도 별 회차로 그대로 들어간다 — 이 편 최대 결함
「손절이 프로세스를 못 떠난다」가 계약으로 닫힌다. 남는 것은 `size_pct 12→4.51%` 라는 이 도구의 본체가
이 경로에 자리가 없다는 것뿐이다.

### 04편 freqtrade — **PASS-반올림.** 01~08 에서 §6④를 실제로 만난 유일한 편
freqtrade 의 손절은 **비율**(`{"stoploss": -0.0005}`)이고, 비율 × 기록된 진입가 85198.18 = `85155.590909` 는
틱 0.01 의 배수가 아니다 → **`422 invalid_stop_loss` `"85155.590909 is not a multiple of tick 0.01"`**.
반올림해 `85155.59` 로 보내면 `201` 이고 손절까지 발동했다. **비율로 사이징·손절하는 모든 도구가 이걸 만난다.**
부수 실측 하나: **시한 검증이 가격 검증보다 앞선다** — 04b(시한 없음 + 비틱 레벨)는 `invalid_stop_loss` 가
아니라 `exit_plan_deadline_required` 를 받는다. 레벨 오류를 보려면 시한을 먼저 채워야 한다.

### 05편 claude-trading-skills — PASS-보강, 빈칸이 계약으로 메워지지만 **사람이 메운다**
이 편이 자기 단점으로 적은 「시간 청산 칸이 없다」가 정확히 그대로 나왔다: 네 레벨(83,800·88,200·84,600·88,800)은
숫자 하나 안 바꾸고 통과하는데 **시한이 없어서 두 번 거절됐다**. 세 번째에 사람이 `close_after_seconds=600` 을
넣고서야 `201` 이다. 그리고 `0.116 BTC → 0.00008 BTC` — 기사가 사람 손으로 0.10 으로 내렸던 그 보정이
없어지는 대신 **규모가 1,450배 줄어** 손익 크기는 못 잰다.

### 06편 jesse — PASS-보강, 옮길 **계획 레벨이 하나도 없다**
전략이 「ATR×2 손절」인데 **그 숫자가 기록에 없다.** 기록된 가격 `71610.33`·`72952.85` 는 실현 체결가다.
그래서 06c 는 가격 조건이 **빈 채로** 접수됐다 (시한만, 사람이 기록된 보유 71h 에서 옮김). 06d 는 실현
청산가를 목표가 칸에 넣어 본 것이고 `201` 이지만 **그것도 계획이 아니라 결과다.**
06d 의 `take_profit` 발동(`exit_trigger_px=85350.00`)은 **내가 P0→P1 로 호가를 올린 결과이고 시장 사건이 아니다.**

### 07편 CloddsBot — N/A. 죽어서가 아니라 **시장이 없어서**
`venue="polymarket"` 은 `422 market_not_licensed` `status:"off"` 다 — 모르는 venue 는 fail-closed 로 막힌다
(`license_pending` 도 아니다). 이 편이 낸 유일한 주문 모양 숫자는 안전장치 단위 시험의 **수량 80** 하나이고,
수량은 시험 주문이 받지 않는다(`422 extra_forbidden`). **옮길 것이 없다는 것을 두 코드로 확인했다.**

### 08편 CoinRithm — PASS-보강, 두 계약이 정확히 뒤집혀 있다
저쪽 견적 원문 `{"coinId":"1","side":"buy","quantity":0.001}` 에서 **`quantity` 를 버리고 시한을 더하면**
그대로 통과한다. 저쪽은 `quantity` **필수** + 현물 손절 필드 **없음**, 우리는 `quantity` **거절**(`extra_forbidden`)
+ 시한 **필수**. 설계 대조표의 그 행이 양방향 실측으로 확인됐다.

---

## 종전 등급과 대조 — **어긋나는 것만**

| 어긋난 것 | 종전 문서 | 이번 실측 |
|---|---|---|
| **01~08 중 도구 기록만으로 PASS 한 편 = 0** | 05·06 = **S**, 01·02·03 = **A** (「이 도구 방법론이 요구하던 것을 처음 공급」·「그대로 이관된다」) | **8편 전부 PASS-보강**이다. 8편 모두 `close_at`·`close_after_seconds` 를 내지 않아 **첫 POST 가 8편 다 `422 exit_plan_deadline_required`** 였다. 시한을 사람이 넣는 순간 「도구가 하지 않은 판단」이 생기므로, S·A 는 **「도구 + 사람 한 칸」의 등급**으로 읽어야 한다 |
| **`max_duration_hours` 가 시한을 대신하지 못한다** | 문서에 없는 사실. §3.4 는 「접수 시각부터의 전체 수명 상한」이라고만 적는다 | `max_duration_hours` 만 준 5케이스(01b·02b·03b·05b·06b) **전부 같은 `422 exit_plan_deadline_required`**. `forward_test.py:315` 가 `close_at`·`close_after_seconds` 둘만 본다. **26·30 편처럼 「시한을 못 내는 도구」에 최대 기간으로 우회하는 길이 없다** |
| **04편 = C 「시험주문과 실질적으로 무관」** | §2 · 04편 「이 편을 막은 것은 `/v1/bars` 720시간(G3)과 저쪽 크립토 전용. 시험주문은 둘 중 아무것도 건드리지 않는다」 | **이관된다.** 기록된 절대 손절선 85155.59 + 방향 + 종목이 그대로 들어가 손절이 실제로 발동했다. 그리고 **01~08 중 §6④(실수 레벨 422)를 실제로 만난 유일한 편**이다 — freqtrade 가 비율을 내기 때문이다. C 의 근거는 자료 경로 이야기이고 **이관 경로에는 해당하지 않는다** |
| **04편 「둘이 만나는 자리가 없다 — 대조표에만 적는다」** | 04편 「기준 주문량」 | 만난다. `stake_amount: 100` USDT 대 서버 기준량 `0.00008 BTC`(6.83 USDT)가 같은 회차에서 나란히 잰다 |
| **07편 = X 「도구가 죽어서 못 붙인다」** | §2 · 07편 | 결과는 같지만 **이 경로의 사유는 하나다** — `venue` 가 없다(`market_not_licensed status=off`). MCP 미기동·페이퍼 부재는 이관 판정에 쓰이지 않았다 (도구를 돌리지 않았으므로) |
| **08편 「우리 시장에 주문을 내지 않으므로 대체되는 사이징이 없다」** | 08편 「기준 주문량」 | 낸다. 기록된 견적 원문이 `coinId "1"` = BTCUSDT · `side buy` · `quantity 0.001` 이고, 그 `quantity 0.001` 이 서버 판정 `0.00008` 로 **실제로 대체됐다** |
| **`us-equity` 프로필이 `v4`** | §4 기준 주문량 표 「`us-equity` \| AAPL \| **v4** \| 1주」 | 접수 응답은 **`execution_model {"profile_id":"us-equity","version":1}`** 이다. `forward_test.py:364` `profile_for()` 가 `PROFILES.get((venue, 1))` 로 **버전 1 을 하드코딩**한다 — 틱·lot·min_notional 판정과 기록되는 프로필 버전이 전부 v1 이다. (방향 게이트 `clean_side` → `shorts_allowed(venue)` 는 `latest(venue)` = **v4** 를 본다. 즉 **한 접수 안에서 방향은 v4, 수량·틱·기록은 v1** 이다.) us-equity 는 v1~v4 의 틱·lot·min_notional 이 같아 이번 수량 판정에는 차이가 없었지만, **응답에 적히는 버전이 틀렸다.** 종전 문서의 `02-trial-order/evidence.json` 도 같은 값(`version: 1`)을 갖고 있었는데 §4 표에 v4 로 적혔다 |
| **「숏이 열린 근거가 `US_EQUITY_V4`」** | §1 · §6① | 방향 게이트는 v4 를 읽으므로 결론은 맞다. 다만 **`US_EQUITY_V1` 도 `shortable` 이 기본 `True`** 라(v1 은 그 필드를 덮어쓰지 않는다) 「v4 가 열었다」는 문장은 **v3(`shortable=False`) 대비**로만 참이다 |

**어긋나지 않은 것** (확인만): 계좌 9개 표 불변 · `qty` 거절 · 시한 발동에는 `exit_trigger_px` 가 `null` ·
조건 성립가 ≠ 체결가 · `us-equity` 일요일 `rejected:market_closed` 와 `delta=-1` 한도 복원 ·
`us-equity` 숏 접수 통과 · `cme` 는 `license_pending` 그대로 두었다(이 8편에 CME 를 쓰는 도구가 없어 호출은 없다).

---

## 정리 뒤 상태

자식 프로세스 SIGINT → `pg_ctl -m fast stop` → 임시 디렉터리 삭제. 남은 프로세스·포트 확인 결과는
이 문서 아래 한 줄로 적는다: **포트 8901·55541 리슨 0건**, `weltiq-xfer1-*` 임시 디렉터리 0건.
이미 돌고 있던 로컬 엔진(8722·8723·8724)과 DB `weltiq_r1_claude` 는 건드리지 않았다.
