#!/usr/bin/env bash
# 12 TradingAgents 의 `Hold` — "지금 추가하지 마라" — 를 반사실 시험 주문으로 채점하는 레시피.
#
#   ┌─ 설계 원칙 ────────────────────────────────────────────────────────────┐
#   │ **의도는 도구가 갖는다.** weltiq 는 집행 기록(주문·체결·수수료·청산 사유)을 갖고,   │
#   │ Rating·근거·지평은 **저장하지 않는다.** 서버로 가는 것은                        │
#   │ client_order_id · client_tracking_id · tags 뿐이고, 판정은 tool_log.csv 로.    │
#   │ 나중에 둘을 잇는 것은 **추적 ID 하나**다.                                      │
#   └───────────────────────────────────────────────────────────────────────┘
#
# 기준 뼈대: ../roundtrip/roundtrip.sh. 회수 CSV 만 계정 전체 엔드포인트
# `GET /v1/forward-tests/orders?format=csv` (2026-09-28 신설) 한 번으로 바꿨다.
#
# 쓰는 법:
#   export WELTIQ_API_KEY='wk_...'            # scope: run-forward-tests, read-data
#   export RUN_ID='tradingagents-hold-1'
#   ./04-trial-order-tradingagents-hold.sh
#
# 주의: 진입 접수 1건 = 월 한도 1회. 아래 PLAN 은 1건이다.
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:=tradingagents-hold-$(date +%Y%m%d-%H%M%S)}"
: "${VENUE:=binance-spot}"
: "${SYMBOL:=BTCUSDT}"
: "${CLOSE_S:=600}"
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' "$@"; }

# ── ① 심기 ──────────────────────────────────────────────────────────────────
#
# Hold 는 "팔지도 사지도 마라"이고, 이 도구가 **구체적으로 금지한 행동**은
# "지금 추가하는 것"이다:
#   "…do not add at the current 81,526.82 level beneath the 82,253.84–83,000 resistance zone."
# 그 금지된 행동을 그대로 한다 — 지금 시장가로 추가 매수(롱).
#
# 숏을 내지 않는 이유: 이 도구의 중기 방향은 "constructive medium-term trend" 로 상승이다.
# 78,473.91 아래는 "reason to reduce risk" 이지 하락 주장이 아니다.
#
# 레벨 처리를 정직하게 적는다: 이 도구는 이 둘을 stop/target 이라고 **부르지 않았다**
# (기록 원문 `Price Target: not provided`). 도구가 이름 붙인 두 수준 —
#   78,473.91 = "reason to reduce risk"  ·  83,000 = 저항대 상단(돌파 확인선)
# 을 exit_plan 으로 옮긴 것이고, **역할 배정은 이 스크립트의 판단**이다.
# 숫자 자체는 원문 그대로이고 한 자리도 고치지 않았다.
#
# 틱: binance-spot 의 가격 틱은 0.01 이라 78473.91·83000 은 그대로 통과한다.
# 실수 레벨을 내는 도구는 그렇지 않다 — 같은 회차의 다른 편에서 stop 82034.9994 가
# `422` 를 받았고, 82035.00 으로 **반올림한 뒤에야** 201 이 됐다. 서버는 조용히
# 반올림해 주지 않는다. 반올림이 필요하면 **보수적인 쪽**으로 한다
# (롱이면 손절은 올림 = 더 가깝게, 목표는 버림 = 더 가깝게).
COID="$RUN_ID-hold-add"
echo 'client_order_id,tracking,verdict,rating,forbidden_action,source' > "$WORK/tool_log.csv"
echo "① 심기 — tracking=$RUN_ID"
BODY=$(jq -n --arg v "$VENUE" --arg s "$SYMBOL" --arg c "$COID" --arg t "$RUN_ID" \
             --argjson sec "$CLOSE_S" \
  '{venue:$v, symbol:$s, client_order_id:$c, side:"long",
    client_tracking_id:$t, tags:["counterfactual","part-12"],
    exit_plan:{close_after_seconds:$sec, stop_loss:"78473.91", take_profit:"83000"},
    memo:"Hold 반사실 — 금지된 행동(지금 추가)을 그대로 한다",
    metadata:{verdict:"Hold", rating:"Hold", level_roles:"assigned_by_harness",
              source:"reports/b/01/21-tradingagents-decision.json:10"}}')
RESP=$(api -X POST "$WELTIQ_BASE_URL/v1/trial-buys" -d "$BODY")
echo "   $COID → $(echo "$RESP" | jq -r '.test_id // .error // "?"')"
printf '%s,%s,Hold,Hold,"add at 81526.82",reports/b/01/21-tradingagents-decision.json:10\n' \
  "$COID" "$RUN_ID" >> "$WORK/tool_log.csv"

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

# ── ② 회수 — 추적 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 — 한 번에 ─────────────────────────────────────────────────────
# 자동 청산 주문은 **추적 ID·태그를 물려받는다.** 그래서 진입 한 건만 심었어도
# 이 CSV 에는 진입 줄과 청산 줄이 같이 온다 — 왕복 비용이 여기서 나온다.
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))행"

# ── ④ 조인 ──────────────────────────────────────────────────────────────────
# awk 를 쓰지 않는다: 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', 'forbidden_action', '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 '',
             forbidden_action=m['forbidden_action'] if m else '',
             join='matched' if m else 'unmatched')
    matched += bool(m); out.writerow(r)
    t = per.setdefault(r['test_id'], {'verdict': '', 'enter': None, 'exit': None,
                                      'reason': r.get('close_reason', '')})
    if m:
        t['verdict'] = m['verdict']
    if r.get('close_reason'):
        t['reason'] = r['close_reason']
    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}  '
      f'(안 되는 행 = 서버가 만든 자동 청산 주문이다. 정상이다)')

print(f'\n   {"판정":<8}{"진입가":>16}{"청산가":>16}{"수수료":>13}{"순손익":>16}{"손익분기":>10}  사유')
for t in per.values():
    if not (t['enter'] and t['exit']):
        print(f"   {t['verdict']:<8}  미체결 — close_reason={t['reason'] or '?'}")
        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['enter'][1]:>16.5f}{t['exit'][1]:>16.5f}{fee:>13.8f}"
          f"{net:>16.10f}{abs(net) / notional * 100:>9.4f}%  {t['reason']}")
print('   순손익 < 0 → "지금 추가하지 마라"는 옳았다. 단 **가격이 그 창 동안 손익분기보다\n'
      '   크게 오르지 않았다면** 이라는 조건부로만. 이 표는 문턱을 줄 뿐 판정하지 않는다.')
PY

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