"""Reproduce article analysis; standard library only, no product job execution."""

import argparse
import hashlib
import json
import math
import platform
import random
from decimal import Decimal, getcontext
from pathlib import Path

getcontext().prec = 60
directory = Path(__file__).resolve().parent
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--input', type=Path, default=directory / 'backtest-profit-concentration-outlier-trades-demo-screenshots.json')
parser.add_argument('--output', type=Path, default=directory / 'monte-carlo-losing-streak-drawdown-analysis.json')
arguments = parser.parse_args()
source_path = arguments.input
source_bytes = source_path.read_bytes()
source = json.loads(source_bytes)
trades = sorted(source['trades'], key=lambda trade: (trade['exitTime'], trade['id']))
assert len(trades) == 19
assert len({trade['id'] for trade in trades}) == len(trades)
assert all(trade['instrumentId'] == 'CRYPTO:BINANCE:BTCUSDT' for trade in trades)
assert all(Decimal(trade['fee']) == 0 for trade in trades)
assert all(Decimal(trade['quantity']).quantize(Decimal('0.00000001')) == Decimal('0.05') for trade in trades)
assert all(left['exitTime'] <= right['entryTime'] for left, right in zip(trades, trades[1:]))
pnls = [Decimal(trade['pnl']) for trade in trades]
capital = Decimal('10000')


def metrics(indices):
	equity = capital
	peak = capital
	max_pct = Decimal(0)
	max_dollars = Decimal(0)
	streak = longest = 0
	curve = [str(capital)]
	for index in indices:
		pnl = pnls[index]
		equity += pnl
		peak = max(peak, equity)
		assert peak > 0
		max_dollars = max(max_dollars, peak - equity)
		max_pct = max(max_pct, (peak - equity) / peak * 100)
		streak = streak + 1 if pnl < 0 else 0
		longest = max(longest, streak)
		curve.append(str(equity))
	return {'pnl': str(equity - capital), 'endingEquity': str(equity), 'maxDrawdownPct': str(max_pct), 'maxDrawdownDollars': str(max_dollars), 'longestLosingStreak': longest, 'equityAfterVirtualClose': curve}


def nearest_rank(values, p):
	return sorted(values)[max(0, math.ceil(p * len(values)) - 1)]


baseline = metrics(list(range(19)))
assert abs(Decimal(baseline['pnl']) - Decimal(source['performance']['totalNetProfit'])) < Decimal('0.00000001')
assert sum(pnl > 0 for pnl in pnls) == 7
assert sum(pnl < 0 for pnl in pnls) == 12
methods = []
for method, seed in [('shuffle', 20261002), ('iid-bootstrap', 20261003), ('circular-block-3', 20261004)]:
	rng = random.Random(seed)
	paths = []
	for iteration in range(60):
		if method == 'shuffle':
			indices = list(range(19))
			rng.shuffle(indices)
		elif method == 'iid-bootstrap':
			indices = [rng.randrange(19) for _ in range(19)]
		else:
			indices = []
			while len(indices) < 19:
				start = rng.randrange(19)
				indices.extend((start + offset) % 19 for offset in range(3))
			indices = indices[:19]
		result = metrics(indices)
		if method == 'shuffle':
			assert sorted(indices) == list(range(19))
			assert Decimal(result['pnl']) == Decimal(baseline['pnl'])
		paths.append({'iteration': iteration + 1, 'sourceIndicesZeroBased': indices, **result})
	summary = {}
	for field in ['pnl', 'maxDrawdownPct', 'maxDrawdownDollars', 'longestLosingStreak']:
		values = [Decimal(str(path[field])) for path in paths]
		summary[field] = {label: str(value) for label, value in [('minimum', min(values)), ('medianNearestRank', nearest_rank(values, 0.5)), ('p90NearestRank', nearest_rank(values, 0.9)), ('maximum', max(values))]}
	methods.append({'method': method, 'seed': seed, 'iterations': 60, 'summary': summary, 'paths': paths})

output = {
	'observedDate': '2026-10-03',
	'analysisKind': 'Author calculation from retained executed reported trade P&L; not native Monte Carlo',
	'inputPath': source_path.name,
	'inputSha256': hashlib.sha256(source_bytes).hexdigest(),
	'backtestId': source['backtestId'],
	'strategyId': source['strategyId'],
	'sourceStatus': source['status'],
	'configuration': source['configuration'],
	'rules': source['rules'],
	'nativePerformance': source['performance'],
	'tradesInExitOrder': trades,
	'arithmetic': 'Decimal, precision 60; no interim rounding',
	'pythonVersion': platform.python_version(),
	'rng': 'Python random.Random MT19937, independently reset per method',
	'initialCapital': str(capital),
	'percentileMethod': 'Nearest rank: sorted values[ceil(p*n)-1], median p=0.5 and p90 p=0.9',
	'sizing': 'Fixed recorded dollar P&L; no compounding/resizing/rerun',
	'fees': 'No extra deduction; source fees all zero despite configured crypto 0.1%',
	'baseline': baseline,
	'methods': methods,
}
target = arguments.output
target.write_text(json.dumps(output, indent='\t') + '\n')
print(json.dumps({'baseline': baseline, 'summary': [{key: method[key] for key in ['method', 'seed', 'iterations', 'summary']} for method in methods], 'output': str(target)}, indent=2))
