"""weltiq 슬롯 내보내기(export)의 체결을 jesse 의 '매매 순서 셔플' 몬테카를로에 태운다.

jesse 의 몬테카를로는 자기 백테스트 결과에만 붙는다. 그래서 우리 원장을 jesse 가
쓰는 매매 목록 모양으로 바꿔 주고, 셔플·재구성·신뢰구간 계산은 jesse 의 함수를
그대로 부른다(직접 구현하지 않는다).

사용법:  python wq_trades_monte_carlo.py <export.json> [셔플_횟수]
"""
import json, sys, random
from datetime import datetime

import numpy as np
from jesse.research.monte_carlo.monte_carlo_trades import (
    _reconstruct_equity_curve_from_trades,
    _calculate_metrics_from_equity_curve,
    _calculate_confidence_intervals,
    _calculate_max_drawdown,
)

SEED = 20260922
N = int(sys.argv[2]) if len(sys.argv) > 2 else 500


def ts(s):
    return datetime.fromisoformat(s).timestamp()


def round_trips(fills):
    """OPEN 과 그 뒤의 REDUCE 를 짝지어 한 건의 매매로 만든다 (수수료 차감)."""
    out, open_fill = [], None
    for f in fills:
        if f['action'] == 'OPEN':
            open_fill = f
        elif f['action'] == 'REDUCE' and open_fill is not None:
            qty = float(open_fill['qty'])
            pnl = (float(f['px']) - float(open_fill['px'])) * qty \
                  - float(open_fill['fee']) - float(f['fee'])
            out.append({'PNL': pnl,
                        'opened_at': ts(open_fill['at']),
                        'closed_at': ts(f['at'])})
            open_fill = None
    return out


def main(path):
    ex = json.load(open(path))
    fills = ex['fills']
    perf = ex['performance']
    start_balance = float(perf['start_balance'])

    trades = round_trips(fills)
    curve = [{'name': 'Portfolio',
              'data': [{'time': ts(p['at']) if p['at'] else ts(fills[0]['at']),
                        'value': float(p['equity'])}
                       for p in perf['equity_curve']]}]

    original = _calculate_metrics_from_equity_curve(curve, start_balance)
    print(f"슬롯      : {ex['slot']['container_id']}  ({ex['slot']['venue']}, "
          f"{ex['slot']['symbols']}, tf={ex['slot']['tf']})")
    print(f"doc_hash  : {ex['slot']['doc_hash']}")
    print(f"체결 {len(fills)}건 → 왕복 매매 {len(trades)}건, 수수료 합계 {perf['fees']} USDT")
    print(f"원본      : 수익률 {original['total_return']:.4f}%  "
          f"최대낙폭 {original['max_drawdown']:.4f}%")
    print(f"우리 쪽 성능표의 최대낙폭: -{perf['max_drawdown_pct']}%  (대조용)")
    print()

    rng = random.Random(SEED)
    sims = []
    for i in range(N):
        shuffled = trades[:]
        rng.shuffle(shuffled)
        c = _reconstruct_equity_curve_from_trades(shuffled, curve, start_balance)
        sims.append(_calculate_metrics_from_equity_curve(c, start_balance))

    # jesse 는 original 을 result['metrics'] 에서 읽는다 — 그 모양으로 맞춰 준다.
    conf = _calculate_confidence_intervals(
        {'metrics': {'net_profit_percentage': original['total_return'],
                     'max_drawdown': original['max_drawdown'],
                     'sharpe_ratio': original['sharpe_ratio'],
                     'calmar_ratio': original['calmar_ratio']}},
        sims)
    for name, m in conf['metrics'].items():
        p = m['percentiles']
        print(f"[{name}]  원본 {m['original']:.4f}")
        print(f"   5th {p['5th']:.4f} | 50th {p['50th']:.4f} | 95th {p['95th']:.4f}"
              f"   (p={m['p_value']})")
    print()
    print(f"셔플 {N}회, 시드 {SEED}")
    json.dump({'original': original, 'confidence': conf, 'num_scenarios': N,
               'seed': SEED, 'trades': len(trades)},
              open('/private/tmp/jesse-tut/wq_mc_result.json', 'w'),
              indent=1, default=float)


if __name__ == '__main__':
    main(sys.argv[1])
