#!/usr/bin/env bash
# 29A MAHORAGA 의 `WAIT`·`SKIP` 을 반사실 시험 주문으로 바꿔 채점하는 레시피.
#
#   ┌─ 설계 원칙 ────────────────────────────────────────────────────────────┐
#   │ **의도는 도구가 갖는다.** weltiq 는 집행 기록(주문·체결·수수료·청산 사유)을 갖고,   │
#   │ 무엇을 판정했는지·얼마나 확신했는지는 **저장하지 않는다.** 아래 심기 루프를 보라 — │
#   │ 서버로 가는 것은 client_order_id · client_tracking_id · tags 뿐이고,           │
#   │ verdict·confidence·source 는 tool_log.csv 에만 쓴다.                        │
#   │ 나중에 둘을 잇는 것은 **추적 ID 하나**다.                                      │
#   └───────────────────────────────────────────────────────────────────────┘
#
# 기준 뼈대: ../roundtrip/roundtrip.sh (추적 ID 왕복). 달라진 곳 둘 —
#   (1) 회수 CSV 를 계정 전체 엔드포인트 `GET /v1/forward-tests/orders?format=csv` 한 번으로 받는다
#       (2026-09-28 신설. 종전엔 「목록 1 + 시험마다 1」이었다).
#   (2) PLAN 이 이 도구가 실제로 기록한 관망 네 건이다.
#
# 쓰는 법:
#   export WELTIQ_API_KEY='wk_...'            # scope: run-forward-tests, read-data
#   export RUN_ID='mahoraga-wait-1'           # 이번 런의 추적 ID
#   ./03-trial-order-mahoraga-wait.sh
#
# 주의: 진입 접수 1건 = 월 한도 1회. 아래 PLAN 은 4건이다 (pro 월 1,000회).
set -euo pipefail

: "${WELTIQ_BASE_URL:=https://weltiq.ai}"
: "${WELTIQ_API_KEY:?WELTIQ_API_KEY 를 설정하세요 (pro 계정 API 키, scope: run-forward-tests read-data)}"
: "${RUN_ID:=mahoraga-wait-$(date +%Y%m%d-%H%M%S)}"
: "${VENUE:=binance-spot}"
: "${SYMBOL:=BTCUSDT}"
: "${CLOSE_S:=600}"                 # 10분 창. 관망의 「지금」을 재는 길이다
WORK="${WORK_DIR:-./run-$RUN_ID}"

command -v jq >/dev/null || { echo 'jq 가 필요합니다 (brew install jq)'; exit 2; }
mkdir -p "$WORK"
api() { curl -sS -H "Authorization: Bearer $WELTIQ_API_KEY" \
        -H 'Content-Type: application/json' "$@"; }

# ── ① 심기 — 주문은 서버로, 판정은 tool_log.csv 로 ───────────────────────────
#
# 이 도구는 **레벨을 내지 않는다.** 손절 5% · 익절 10% 는 설정 상수이지 판단이 아니므로
# exit_plan 에는 **시한만** 준다. 가격 조건을 지어내면 그것은 반사실이 아니라 창작이다.
#
# 방향을 롱으로 고정한 이유: `WAIT`·`SKIP` 은 둘 다 "사지 마라"이고 그 반대는 사는 것이다.
# 숏은 내지 않는다 — 도구 원문이 못 박았다:
#   "Confidence reflects the case for waiting, not a prediction of a price decline."
# 하락을 시사하지 않은 판정에 숏을 붙이면 반사실이 아니다.
#
# 한 줄 = client_order_id | verdict | confidence | 출처
PLAN='
'"$RUN_ID"'-wait-088|WAIT|0.88|reports/a/29-account-walls/RUN-LOG.md:148
'"$RUN_ID"'-wait-090|WAIT|0.90|reports/a/29-account-walls/RUN-LOG.md:149
'"$RUN_ID"'-wait-089|WAIT|0.89|reports/a/29-account-walls/RUN-LOG.md:150
'"$RUN_ID"'-skip-020|SKIP|0.20|reports/a/29-account-walls/RUN-LOG.md:158
'

echo 'client_order_id,tracking,verdict,confidence,source' > "$WORK/tool_log.csv"
echo "① 심기 — tracking=$RUN_ID"
while IFS='|' read -r COID VERDICT CONF SRC; do
  [ -n "${COID:-}" ] || continue
  # ↓ 서버로 가는 본문.
  #   metadata 에 **float 를 넣으면 500** 이다 — 계약 본문이 해시되는데 결정론 규칙이
  #   float 를 거부한다(canonical_json). 확신도는 반드시 **문자열**로 싣는다: "0.88".
  #   숫자로 재계산하는 것은 받는 쪽(아래 ④)의 일이다.
  BODY=$(jq -n --arg v "$VENUE" --arg s "$SYMBOL" --arg c "$COID" --arg t "$RUN_ID" \
               --arg verdict "$VERDICT" --arg conf "$CONF" --arg src "$SRC" \
               --argjson sec "$CLOSE_S" \
    '{venue:$v, symbol:$s, client_order_id:$c, side:"long",
      client_tracking_id:$t, tags:["counterfactual","part-29A"],
      exit_plan:{close_after_seconds:$sec},
      memo:"관망 반사실 — 그 판정의 반대를 낸다",
      metadata:{verdict:$verdict, confidence:$conf, source:$src}}')
  RESP=$(api -X POST "$WELTIQ_BASE_URL/v1/trial-buys" -d "$BODY")
  echo "   $COID $VERDICT/$CONF → $(echo "$RESP" | jq -r '.test_id // .error // "?"')"
  # ↓ 도구 쪽 로그. 서버에 보내는 metadata 와 **중복이 아니라 원본**이다 —
  #   서버는 이것을 해석하지 않고, 채점은 전부 여기서 한다.
  printf '%s,%s,%s,%s,%s\n' "$COID" "$RUN_ID" "$VERDICT" "$CONF" "$SRC" >> "$WORK/tool_log.csv"
done <<< "$PLAN"

echo "   (체결·청산이 돌 시간을 준다: $((CLOSE_S + 60))초)"; sleep "${SETTLE_S:-$((CLOSE_S + 60))}"

# ── ② 회수 — 추적 ID 로 계정 전체에서 내 런만 ────────────────────────────────
# tracking= 은 정확 일치 필터이고 user_id 안에서만 돈다. 다른 런은 섞이지 않는다.
echo "② 회수 — tracking=$RUN_ID"
api "$WELTIQ_BASE_URL/v1/forward-tests?tracking=$RUN_ID&limit=200" > "$WORK/list.json"
jq -r '.tests[] | "   \(.test_id)  \(.derived_status)"' "$WORK/list.json"

# ── ③ 전체 CSV — 한 번에 ─────────────────────────────────────────────────────
# format=csv 는 필터에 걸린 **전부**를 커서로 끝까지 돌아 한 번에 낸다.
# 열은 시험별 export 와 글자까지 같다 (행 생성기가 한 함수다).
echo '③ 전체 CSV — /v1/forward-tests/orders?format=csv (호출 1회)'
api "$WELTIQ_BASE_URL/v1/forward-tests/orders?tracking=$RUN_ID&format=csv" > "$WORK/all.csv"
echo "   $(($(wc -l < "$WORK/all.csv") - 1))행"

# ── ④ 조인 — 추적 ID + client_order_id ───────────────────────────────────────
# awk 를 쓰지 않는다: CSV 의 metadata·exit_plan 칸에 **인용된 쉼표**가 들어 있어
# 필드 구분자로 자르면 열이 밀린다. 조인은 python3 의 csv 모듈로만 한다.
echo '④ 조인 — all.csv × tool_log.csv'
python3 - "$WORK" <<'PY'
import csv, sys
w = sys.argv[1]
log = {(r['tracking'], r['client_order_id']): r for r in csv.DictReader(open(f'{w}/tool_log.csv'))}
rows = list(csv.DictReader(open(f'{w}/all.csv')))
cols = (list(rows[0]) if rows else []) + ['verdict', 'confidence', 'join']
out = csv.DictWriter(open(f'{w}/joined.csv', 'w', newline=''), cols); out.writeheader()
per, matched = {}, 0
for r in rows:
    m = log.get((r['client_tracking_id'], r['client_order_id']))
    r.update(verdict=m['verdict'] if m else '', confidence=m['confidence'] if m else '',
             join='matched' if m else 'unmatched')
    matched += bool(m); out.writerow(r)
    t = per.setdefault(r['test_id'], {'conf': None, 'verdict': '', 'enter': None, 'exit': None})
    if m:
        t['conf'], t['verdict'] = float(m['confidence']), m['verdict']
    if r['fill_qty']:
        t['enter' if r['action'] == 'enter' else 'exit'] = (
            float(r['fill_qty']), float(r['fill_px']), float(r['fee'] or 0))
print(f'   조인됨 {matched} / 안 됨 {len(rows) - matched}')
if len(rows) - matched:
    print('   안 되는 행 = 서버가 만든 자동 청산 주문이다 — client_order_id 가 "exit-plan:…" 이고\n'
          '   추적 ID 가 비어 있다. 도구 로그에 있을 수 없는 행이며, 그게 정상이다.')

# 판정별 손익분기 — 이 왕복의 목적지다.
#   손익분기 = |순손익| / 진입 금액 = "그 관망이 틀리려면 이 창 안에 필요했던 최소 움직임".
print(f'\n   {"판정":<8}{"확신도":>7}{"진입가":>16}{"청산가":>16}{"수수료":>13}{"순손익":>16}{"손익분기":>10}')
for tid, t in per.items():
    if not (t['enter'] and t['exit']):
        print(f"   {t['verdict']:<8}{t['conf'] if t['conf'] is not None else '-':>7}"
              f"{'미체결 — close_reason 을 보라':>50}")
        continue
    notional = t['enter'][0] * t['enter'][1]
    fee = t['enter'][2] + t['exit'][2]
    net = t['exit'][0] * t['exit'][1] - notional - fee
    print(f"   {t['verdict']:<8}{t['conf']:>7}{t['enter'][1]:>16.5f}{t['exit'][1]:>16.5f}"
          f"{fee:>13.8f}{net:>16.10f}{abs(net) / notional * 100:>9.4f}%")
print('   순손익 < 0 → 그 관망은 옳았다. 단 **가격이 그 창 동안 손익분기보다 크게 움직이지\n'
      '   않았다면** 이라는 조건부로만. 이 표는 그 문턱을 줄 뿐 도구의 옳고 그름을 말하지 않는다.')
PY

echo
echo "끝. 산출물 $WORK/{tool_log,all,joined}.csv"
