# 34편 orallexa — 검증 기록

2026-09-24 10:28~10:55 KST. 모든 숫자는 실측.
트리 `/Users/unolee/dev/weltiq-launch` · 도구 `/Users/unolee/dev/weltiq-tools/orallexa`.
LLM 은 OpenRouter 경유 `claude-sonnet-4-6` 고정. 주문은 전부 페이퍼.

## 0. 고정된 것

| | |
|---|---|
| 저장소 | `alex-jb/orallexa-ai-trading-agent` |
| 커밋 | **`794a2ec0ce0b1271b468814eee47c2cd4edde147`** (2026-07-12 11:08:31 -0400) |
| 라이선스 | **MIT** |
| 별·포크 | ★67 · 21 (관측 2026-09-24) · 생성 2026-04-01 · 마지막 푸시 2026-07-12 |
| 코드 | 본체 51,130줄 · 테스트 18,112줄 / 83파일 (`wc -l`) |
| 파이썬 | 3.11.16 (`python3.11 -m venv .venv`) |
| 설치 | `pip install -r requirements.txt` — **163초** |
| UI | `npm install` 6초(캐시) · Next.js 16.2.1 `Ready in 129ms` · `localhost:3000` ← `api_server.py` `localhost:8002` |
| 브로커 | `paper-api.alpaca.markets` 하드코딩 (`bot/alpaca_executor.py:32,61`) |

**작업 위치 이동**: 이전 B축 검증(2026-09-22)은 `/private/tmp/tut-src/orallexa` 에서 돌았다.
일일 정리에 지워지므로 이번에 `~/dev/weltiq-tools/orallexa` 로 복사하고 venv 를 새로 만들었다.
`memory_data/` 와 `logs/` 는 `.gitignore` 대상이라 함께 옮겨졌다 — **2026-09-22 의 결정 로그
9행이 그래서 남아 있고**, §4 의 「1행만 채점됐다」는 그 9행 덕분이다. 출처를 밝혀 둔다.

---

## 1. 확신도 — 원값과 화면값

### 1.1 `scale_confidence` 는 상한이 아니라 곱셈이다

`models/confidence.py:32-43`. 독스트링은 *"Confidence is ALWAYS capped at MAX_CONFIDENCE
(82%)"* 인데 구현은 `min(raw * 0.82, 82.0)` 이다. `raw ≤ 100` 이면 `min` 이 안 걸리므로
**모든 값에 0.82가 곱해진다.** 함수 자신의 예시가 그렇게 적혀 있다 — `scale_confidence(50) → 41.0`.

도구 코드는 안 고쳤다. `scale_confidence` 를 기록형으로 감싸 raw→scaled 쌍만 남겼다
(`probe_confidence.py` · `probe_basket.py`).

### 1.2 NVDA 5회 반복 — `raw/probe-nvda.json`

| 회차 | 판단 | 화면 | LLM 원값 | overlay 표식 | 소요 |
|---|---|---|---|---|---|
| 1~5 | **WAIT** (5/5) | **42.6%** (5/5) | **52.0** (5/5) | True (5/5) | 4.0~4.7초 |

2026-09-22 검증에서 3회 모두 42.6% 였던 것의 답: **`scale_confidence` 가 눌러서가 아니라
LLM 이 매번 52.0 을 쓴다.** (선행 판정 「다음에 확인할 것」 2번 해소)

### 1.3 16종목 1회씩 — `raw/probe-basket.json`

LLM 원값 **세 개뿐**: `52.0`(10회) · `58.0`(1회) · `62.0`(5회).
화면값 **세 개뿐**: `42.6%` · `47.6%` · `50.8%`. 폭 **8.2포인트**.
반면 `probabilities.up` 은 **0.15 ~ 0.57** 로 벌어진다.

판단 분포: BUY 5 · SELL 1 · WAIT 10. 비용 16회 **$0.044817**.

### 1.4 「Claude overlay applied」 표식은 LLM 이 돌았다는 증거가 아니다 — 선행 판정 정정

선행 판정은 *"회차마다 `Claude overlay applied` 문자열을 확인하는 확인선을 걸어라"* 라고
적었다. **그 확인선은 작동하지 않는다.**

실측(`raw/probe-nvda-401-fallback.json`): 401 이 5/5 떨어진 회차에서도
`decision=WAIT · confidence=32.8 · "Claude overlay applied"` 가 그대로 나왔다.
`llm/ui_analysis.py:229` 가 예외 시 `_DEFAULT_PREDICTION`(WAIT·40) 을 **dict 로** 돌려주고,
`skills/prediction.py:260-267` 은 그것을 정상 응답으로 받아 표식을 찍는다.

**작동하는 확인선은 둘이다**: ① 소요 시간(LLM 이 돌면 ~4초, 폴백이면 ~0.5초)
② `logs/llm_calls.jsonl` 의 `error` 필드.

> 401 의 원인은 도구가 아니라 내 환경이었다. 셸에 `ANTHROPIC_BASE_URL=https://api.anthropic.com`
> 이 있었고 `load_dotenv` 기본값이 `override=False` 라 `.env` 가 안 먹혔다. **다만 도구 쪽
> 문제도 같이 드러났다** — `scripts/run_daily_pilot.py` 경로는 `load_dotenv` 를 아예 안 부른다
> (`load_dotenv` 를 부르는 파일은 `api_server.py` · `desktop_agent/main.py` 둘뿐). README 는
> `.env` 에 키를 넣으라고 한다.

---

## 2. 새로 찾은 것 — 의존성 하나로 LLM 경로 3분의 2가 죽어 있다

```
WARNING orallexa.api  Claude overlay failed: Messages.create() got an unexpected
                      keyword argument 'temperature'
```

- `requirements.txt:2` = `anthropic` (버전 없음) → 오늘 새로 깔면 **1.8.0**
- `inspect.signature(Anthropic().messages.create)` 에 **`temperature` 없음** (실측)
- `llm/call_logger.py:225-227` 이 `temperature` 를 그대로 SDK 에 넘긴다. 재시도 폴백은
  `output_config` 만 처리한다(`:238-244`)
- **`temperature` 를 넘기는 `logged_create` 호출: 33곳 중 22곳**

죽는 22곳: `llm/debate.py`(Bull·Bear·Judge 3) · `llm/debate_graph.py`(3) ·
`engine/multi_agent_analysis.py`(2) · `engine/daily_intel.py`(6) · `engine/scenario_sim.py` ·
`engine/strategy_evolver.py` · `llm/perspective_panel.py` · `llm/strategy_explainer.py`(2) ·
`llm/dspy_judge.py` · `llm/provider.py` · `api_server.py:125`(대시보드 오버레이).

**저장소 설명의 「8-source signal fusion, Bull/Bear/Judge debate on Claude Opus 4.7」이
전부 이 목록 안에 있다.** 자율 진입점이 쓰는 `prediction_decision_report` 는 살아 있는
11곳이라 파일럿은 돈다.

실측 대조 — `raw/api-analyze-doublescale.txt`:

| 호출 | 결과 |
|---|---|
| `POST /api/analyze use_claude=false` | BUY · conf **47.6** · probs up 0.73 |
| `POST /api/analyze use_claude=true` | BUY · conf **47.6** · probs up 0.73 — **한 글자도 안 바뀜**, 200 OK |
| `use_debate=true` | 근거에 `Step 3: Decision (technical only)` · `_call_bull` 이 같은 오류 |

**토론 경로는 강등을 근거 줄에 적는다(`technical only`). 파일럿 경로는 안 적는다** —
표식이 오히려 정반대로 붙는다.

테스트 83파일/18,112줄이 이걸 못 잡는 이유: 전부 클라이언트를 mock 으로 바꾼다.

### 2.1 화면의 48% 는 수식이다

`skills/prediction.py:317` — `confidence = scale_confidence(abs(score - 50) * 2)`.
UI 실측: 기술점수 79 → `|79−50|×2 = 58` → `58 × 0.82 = 47.6` → 화면 `48%`.
**「CLAUDE AI OVERLAY」가 켜진 상태에서 나온 값이다**(오버레이는 위 오류로 죽었다).
같은 카드의 `73% UPSIDE` 는 별개 숫자다 — 한 화면에 두 개, 25포인트 차.

> `api_server.py:99-138` 은 오버레이가 살아 있어도 **0.82를 두 번 곱한다.** 프롬프트에
> 이미 스케일된 confidence 를 넣고(`:112`), 돌아온 값에 `scale_confidence` 를 또 건다(`:138`).
> 그 경로의 실질 상한은 `82 × 0.82 = 67.2` 다. **오늘은 오버레이가 죽어 있어 관측되지 않았다 —
> 코드 판독이며 미확인.**

---

## 3. 자율 경로는 손절을 안 넘긴다 — 인자 원문

`probe_bracket.py` 로 `AlpacaExecutor._client.submit_order` 를 가로채고 **보내지 않았다.**
`raw/probe-bracket.json`.

| | A) 자율 경로 (`run_daily_pilot.py:134-139`) | B) 사람 경로 (`api_server.py:1397-1399`) |
|---|---|---|
| `order_class` | **null** | `"bracket"` |
| `stop_loss` | **null** | `{"stop_price": 475.38}` |
| `take_profit` | **null** | `{"limit_price": 550.44}` |
| 나머지 | `MSFT · qty 9 · buy · market · day` | 동일 |

`alpaca_executor.py:176` 의 `if stop_loss > 0 and take_profit > 0` 이 거짓 → else 분기.

### 3.1 실제 주문으로 확인 — `raw/pilot-gate45-msft.txt`

```
Order submitted: BUY 9 MSFT @ $500.40 (conf=51%, stop=$0.00, target=$0.00)
```

알파카 주문 `69e14508-31eb-43a3-8705-d65cad8c6a5f` — `order_class: "simple"`, `legs: 0`,
`status: accepted`. **확인 뒤 즉시 취소**(`raw/alpaca-orders.json`). 공용 페이퍼 계좌에는
다른 작업의 `BTCUSD 0.001143519` 만 남아 있고 이 글이 만든 포지션은 없다.

### 3.2 기본 설정으로는 주문이 아예 안 나간다

```
DECISION MSFT decision=BUY confidence=50.8% risk=MEDIUM
SKIP MSFT — confidence 50.8% below gate 60.0%
PILOT_DONE trades=0 decisions=1
```

파일럿 기본 게이트 60%, 관측된 최고 확신도 50.8%. **0.82 곱하기가 게이트 의미까지 바꾼다** —
화면 60% = LLM 원값 73.2, 화면 40%(`alpaca_executor.py:144`) = 원값 48.8.

### 3.3 실패한 주문이 성공으로 집계된다 — `raw/pilot-gate45-btc.txt`

```
Order failed for BTC-USD: {"message":"code=400, message=invalid symbol: BTC-USD"}
TRADE BTC-USD decision=BUY result=?
PILOT_DONE trades=1 decisions=1
```

`logs/pilot.log` 의 그 줄: `"status": "traded"`, `"trades": 1`, 그 안에
`"alpaca_result": {"error": "…invalid symbol…"}`. 원인은 `run_daily_pilot.py:141` 이
`execute_signal` 의 반환을 안 보고 `traded` 로 적는 것.

---

## 4. 보정 설비 — 있는데 주식 판단에 안 붙어 있다

### 4.1 무엇이 어디에 붙어 있나 (임포트 실측)

| 모듈 | 임포트하는 곳 | 자율 경로가 부르나 |
|---|---|---|
| `engine/platt_calibration.py` | `markets/auto/brier_audit.py` 1곳 + 자기 테스트 | **아니오** |
| `engine/decision_log.py` | `api_server.py` · `app_ui.py` · **`run_daily_pilot.py:64`** | **예 — 쓴다** |
| `engine/bias_tracker.py` | `api_server.py:1080` · `llm/debate.py:195` | **아니오** |
| `engine/source_accuracy.py` | `engine/signal_fusion.py` · `scripts/update_source_outcomes.py` | **아니오** |

`platt_calibration.fit()` 을 쓰는 유일한 자리는 `brier_audit.render_platt_whatif_section()`
이고, 그 함수 독스트링이 직접 적고 있다 — *"give Alex empirical evidence **before flipping
the live wire-up flag** on polymarket_daily.py / stock decision path"*. **아직 안 이었다.**

### 4.2 Brier 감사를 실제로 돌렸다

**받은 그대로** (`raw/brier-audit-asshipped.md`):

```
[brier] loaded 0 historical decisions
[brier] 0 candidates >= 1d old
[brier] wrote /Users/unolee/Desktop/Interview-Prep/Projects/alex-brain/research/
        brier-audit/2026-09-24.md (insufficient data placeholder)
```

`brier_audit.py:189-190` 이 결정 로그와 출력 경로를 **저자 맥의 바탕화면으로 하드코딩**한다.
**내 맥에 없던 `~/Desktop/Interview-Prep/…` 폴더 5단계를 만들었다.** 확인 후 삭제했다.

**경로 상수 둘만 바꿔 끼우고 다시** (`run_brier_audit.py`, 도구 코드는 안 고침):

```
[brier] loaded 20 historical decisions
[brier] 1 candidates >= 1d old
[brier] wrote … (insufficient data placeholder)     ← MIN_DECISIONS_FOR_REPORT = 5
```

### 4.3 채점된 한 행 — `raw/brier-scored.json`

전체 20행 · BUY/SELL **9행** · WAIT **11행**(방향 주장이 없어 채점 대상 아님).
9행 중 1일 이상 지난 것 **1행**.

| | |
|---|---|
| 행 | 2026-09-22T17:38:34 `BTC-USD` BUY · 화면 확신도 50.8% |
| `forecast_p` | **0.52** ← `probabilities.up`. **`confidence` 가 아니다**(`brier_audit.py:301`) |
| 실제 | −2.2629% → `actual 0.0` |
| **Brier** | **0.2704** |

Platt what-if 를 그대로 호출한 결과:
`_Skipped: Need at least 30 observations, got 1. Platt fit is unreliable below this scale._`

신뢰도 다이어그램(n=1, 의미 없음이지만 장치는 돈다): `overall_ece 0.52`,
`middle_bin_ece 0.52`, `tail_bin_ece 0.0`. 10개 구간 중 9개가 비었다.
**신뢰도 구간 표의 최저 버킷이 `50-60%` 다**(`brier_audit.py:390`) — 관측된 `p_up`
0.52~0.57 은 전부 이 한 칸에 떨어진다.

### 4.4 로그가 자기 목적을 못 채운다

`run_daily_pilot.py` 독스트링(:21-25): *"blocked on memory_data/decision_log.json having
**100 eligible production debate rows**. Running this daily on 7 tickers produces ~7 rows/day"*.

실측: **20행 중 `extra.debate` 가 있는 행 0개.** 파일럿은
`run_prediction(use_claude=True, mode="swing")` 으로 부르고 `use_debate` 기본값은
`False` 다(`core/brain.py:222`). `entry_price` 도 20/20 이 `0.0`(`run_daily_pilot.py:100`
하드코딩).

---

## 5. 대시보드는 「연결 안 됨」인데 같은 키로 주문이 나간다

| 호출 | 결과 |
|---|---|
| `GET /api/alpaca/account` | **`null`** |
| `GET /api/alpaca/positions` | `[{"ticker":"BTCUSD","qty":0.001143519,…}]` — 정상 |

로그: `WARNING orallexa.alpaca Failed to get account: int() argument must be a string,
a bytes-like object or a real number, not 'NoneType'`.
원인 `bot/alpaca_executor.py:86` `int(account.daytrade_count)` — 알파카가 `None` 을 준다
(실측: `TradingClient.get_account().daytrade_count is None`).
UI 는 그 `null` 을 받아 **「PAPER TRADING · NOT CONNECTED · Set ALPACA_API_KEY and
ALPACA_SECRET_KEY in .env」** 를 띄운다. 키는 이미 들어 있고 주문은 나간다.

---

## 6. weltiq 연결 — 왕복 1회

### 6.1 옮긴 것

도구 판단(`raw/btc-decision.json`, 자율 경로 `brain.run_prediction`, 2026-09-24 10:47):

```
BTC-USD  BUY  화면 50.8%  (LLM 원값 62.0)  risk MEDIUM  기술점수 55/100
probabilities up 0.55 / neutral 0.25 / down 0.20
"BTC is trading well above both MA20 and MA50 with strong ADX trend strength and
 positive MACD momentum, though an RSI near 64 and BB% near 0.86 suggest price is
 approaching overbought territory, warranting moderate conviction on the upside
 continuation."
```

레벨·수량은 **도구 자신의 `skills/risk_management.py`** 에 도구 자신의 판단을 넣어 받았다.
자율 진입점이 안 부르는 모듈이다. 파라미터는 `app.py:237-239` 사이드바 기본값 그대로
(계좌 $10,000 · 트레이드당 위험 1.0% · swing 이라 ATR 미사용).

| | 값 | 출처 |
|---|---|---|
| 손절 | 기준가 −**2.5%** | `_STOP_PCT["MEDIUM"]` |
| 목표 | 기준가 +**5.0%** | `_TARGET_PCT["MEDIUM"]` |
| 수량 | **0.02 BTC** | 위험 $100 ÷ 손절거리 = 0.04754 → 계좌 20% 상한에 걸려 0.02377 → 반올림 0.02 |
| R:R | 2.0 | `approved: true` |

모듈 원출력: `stop_loss_price 82034.9994 · take_profit_price 88345.384 ·
position_value 2000.0 · risk_amount 100.0` (도구 기준가 yfinance `BTC-USD` 84138.4609375).

**확신도는 이 계산에 한 번도 안 들어간다.** 입력은 `risk_level` 과 `entry_price` 뿐이다.

**가격 기준만 우리 것을 썼다.** 도구는 yfinance `BTC-USD`, 우리는 binance-spot `BTCUSDT`
(84120.005 · 베이시스 18.46 = 21.9bp). 절대가를 옮기면 베이시스가 같이 넘어오므로
**도구의 비율을 우리 호가에 적용**했다 → stop `82015.05` · limit `88323.91`.
진입 조건은 도구가 진입가를 안 내므로 `True`(첫 확정 봉).

### 6.2 슬롯

| | |
|---|---|
| `doc_hash` | `128ed65df6313b8b6deda067b3b6ba1ef7d2c36d53cfa65faa0c7632f359a6b5` |
| 컨테이너 | `ct_f18946d765cb685d` · `orallexa-34-btc` · `source: ai` |
| venue·tf·잔고 | `binance-spot` · `BTCUSDT` · `1m` · 10000 |
| 중지 조건 | `max_loss 150` · `after_hours 2` · `on_worker_failure: liquidate` |
| 생성 | 10:48:24.547933 |

### 6.3 체결 — `raw/86-export-final.json`

| | 진입 | 청산 |
|---|---|---|
| 시각 | 10:49:00.068401 (+09:00) | 10:51:00.052882 |
| 방향·수량 | buy OPEN 0.02 | sell CLOSE 0.02 |
| 체결가 | **84094.41860050** | **84056.09354950** |
| `expected_px` | 84086.01 | 84064.50 |
| 미끄러짐 | +8.4086 = **1.00bp** 불리 | −8.4065 = **1.00bp** 불리 |
| 수수료 | 1.68188837 USDT | 1.68112187 USDT |
| 성격 | `taker` · `market` · `quote_source: binance` | 동일 |

**보호 손절이 진입과 함께 걸렸다** — `sell (close) stop_market 0.02 @ 82015.05`,
상태 `acked`, `reduce_only: true`, 생성 10:49:00.073615 (진입 체결 5ms 뒤).
§3 에서 도구가 자율 경로에 못 붙인 바로 그것이다.

성과: `realized_pnl −0.7665010200` · `fees 3.36301024` · `equity 9995.87048874` ·
`return_pct_mark −0.0413` · `max_drawdown_pct 0.0413`.
대사: `fills_fee == ledger_fee` (`matched: true`) · `orphan_intents 0` ·
`journal_complete: true`. `stop_fidelity`: 손절이 안 터졌으므로 `checked 0 · violations 0`.

### 6.4 정리 — 삭제는 안 됐다

1. `POST …/stop` → `stopping`. 응답이 먼저 알려 준다 — *"정지는 신규 진입만 멈춥니다"*
2. `POST …/stop {"liquidate": true}` → 청산 체결 10:51:00.052882, 이어서 `stopped`.
   체결 2건, `positions: null`, member `cash 9995.87048874` (8초 간격 폴링으로 확인)
3. `DELETE /v1/containers/ct_f18946d765cb685d` → **409 `positions_open`**
   *"…(남은 것: BTCUSDT 0.02)"*. 포지션이 비었는데도 그렇다. **3회 시도, 전부 409**

**알려진 결함(`FIX_BACKLOG` 75)이라 억지로 지우지 않았다.** 슬롯은 `stopped` · 포지션 0 ·
원장 대사 완료 상태로 남아 있다. 컨테이너 id `ct_f18946d765cb685d`.

---

## 7. 비용 — `logs/llm_calls.jsonl`

| | |
|---|---|
| 오늘 호출 | **41** (성공 33 · 실패 8) |
| 총액 | **$0.093519** |
| 성공 호출 평균 | **$0.002834** · 평균 지연 **4,096ms** |
| 모델 | `claude-sonnet-4-6` 38 · `claude-haiku-4-5-20251001` 3 |
| 실패 | 401 (내 환경, §1.4) 5 · `temperature` (도구, §2) 3 |

키가 공용이라 잔액 차이는 못 믿는다. 위 숫자는 **호출별 기록**이고 `_estimate_cost` 의
추정가다. 자료 구독료 0원(yfinance).

---

## 8. B축 판정 (§4.1 · §4.1a)

**참가 가능** — 선행 판정(2026-09-22) 유지. 계정 벽 없음, MIT.

| 칸 | 결과 |
|---|---|
| 판단 산출 형태 | **방향 + 확신도 + 상·중·하 확률.** 진입가·손절·목표·크기는 `DecisionOutput` 에 칸이 없다 |
| 시장 태그 | `stock` — 분석은 `BTC-USD` 를 읽지만 주문 계층이 알파카 주식 전용(400 `invalid symbol`) |
| **확신도가 크기를 실제로 깎나** | **아니오.** 어느 경로에도 없다. 자율 = 상수 `DEFAULT_POSITION_PCT = 5.0`; 사람 = `risk_management.py` 가 `risk_level` 로 결정. 확신도는 **게이트 전용**(`<40` · `--confidence`) |
| 주문 의도를 혼자 완성하나 | **아니다** — 방향 ✅ 근거 ✅ 무효화 ❌ 크기 ❌. **A-2 조합 후보** 확정 |
| 주문을 스스로 내나 | **예, 경로는 진짜다.** 이번에 실제 제출까지 확인(주문 `69e14508…`) |
| 포지션을 관리하나 | **아니다.** 자율 경로에 브래킷이 안 붙고 진입 뒤 루프가 0건 |

**어느 회차**: **B6(M12 확신도) 1순위 유지. 다만 설계를 바꿔야 한다.**

1. **확신도로는 변별이 안 된다.** 16종목에서 세 값(42.6/47.6/50.8), 폭 8.2포인트.
   **B6 는 `confidence` 가 아니라 `probabilities.up` 으로 재야 한다**(0.15~0.57). 도구 자신의
   감사도 그 필드를 본다
2. **모델 고정이 전제**(§4.11 표의 「모델 고정」)인데, 이 도구는 모델 ID 가 코드 하드코딩이다
   (`llm/claude_client.py:9-11`). 회차 전에 그 줄을 못 박고 기록할 것
3. **진입점을 `run_daily_pilot.py` 로 못 박을 것.** 같은 MSFT 가 CLI 50.8%, UI 48% 였다
4. **게이트를 명시적으로 낮추고 그 사실을 기록할 것.** 기본 60%로는 주문이 0건이다
5. **의존성 상한을 박고 시작할 것**(§2). 토론·멀티에이전트를 쓸 회차라면 필수

**B18(M12 재방문·선물)** 에는 부적합 — 크립토 선물 주문 경로가 없다.
**B16(A-2 조합 vs 단독)** 후보로는 적합 — 빈칸 둘(무효화·크기)이 또렷하다.

---

## 9. 안전

- 도구 쪽 알파카 주문 1건은 확인 즉시 취소. 계좌에 이 글이 만든 포지션 없음
- `POST /api/alpaca/close-all` 은 열지 않았다 (다른 작업의 `BTCUSD` 포지션이 같은 계좌)
- weltiq 슬롯은 정지·청산 완료. 삭제만 409 로 남음(§6.4)
- 키는 어느 파일·로그·기사에도 평문으로 없다. `.env` 는 `cut`/`sed` 대신 이름만 읽었다
- 실자금 경로 없음. 알파카는 `paper=True` 하드코딩, weltiq 는 페이퍼

## 10. 남긴 스크립트

| 파일 | 하는 일 |
|---|---|
| `probe_confidence.py` | 한 종목 N회 — raw/scaled 확신도 쌍 + 호출별 비용 |
| `probe_basket.py` | 여러 종목 1회씩 — 확신도 분포 |
| `probe_bracket.py` | `submit_order` 가로채기 — 자율/사람 경로 인자 대조 (보내지 않음) |
| `run_brier_audit.py` | 도구의 Brier 감사를 실제 로그에 대고 실행 (도구 코드 무수정) |
| `probe_brier_one.py` | 채점 가능한 행 세기 + Platt what-if 직접 호출 |
| `decide_btc.py` | BTC 판단 + 도구 자신의 리스크 모듈로 레벨·수량 산출 |
| `to_weltiq.py` | 규칙 문서·근거·슬롯 생성 |
| `run_pilot.sh` | `.env` 를 export 하고 파일럿을 돌리는 한 줄 (§2.1 우회) |
| `shots.py` · `shot_ui.py` · `shots_base.py` | 캡처 |
