"""
投资决策 v4.1 — 真实数据修正版
================================
基于 009051 易方达中证红利 ETF 联接 真实历史数据 (5.9年年化 8.3%, 18% 波动).
基于沪深 300 全收益指数长期 CAGR ~10%, 25% 波动.

核心修正:
- v4 错误: 用 沪深300 (8%) → 中证红利 (8.5%) 假设, 推荐 B 方案 (3000纳+2000红利+2000纯债)
- v4.1 修正: 真实数据下, 沪深 300 (10%) 略胜中证红利 (8.3%), 但中证红利低波动是优势
- 新最优: E 方案 (2000纳+2000红利+1000沪深300+2000纯债) 不破产率 89.2% 最高

用户实际操作 (选项 B = 不卖沪深300 + 14,000 建仓中证红利):
- 38,000 沪深 300 保留不动 (自然稀释)
- 14,000 一次性 或 分批 买中证红利
- 月定投改为: 3000纳+2000红利+2000纯债 (跟 E 方案一致)
- 长期 = E 方案 (89.2% 不破产率)
"""

import numpy as np
import json

np.random.seed(42)
INFLATION = 0.025
N_ACC = 10000
N_RET = 5000
ACC_MONTHS = 120
RET_MONTHS = 1200

# ==== 真实历史参数 (基于 009051 真实数据) ====
ASSETS_ACC = {
    'ndx':   {'mean': 0.13,  'vol': 0.25},   # 纳指 159696
    'hs300': {'mean': 0.10,  'vol': 0.25},   # 沪深 300 (含分红, 散户实际)
    'div':   {'mean': 0.083, 'vol': 0.18},   # 中证红利 009051 真实
    'bond':  {'mean': 0.03,  'vol': 0.03},
}
ASSETS_RET = {
    'ndx':   {'mean': 0.08, 'vol': 0.20},
    'hs300': {'mean': 0.06, 'vol': 0.20},
    'div':   {'mean': 0.05, 'vol': 0.15},
    'bond':  {'mean': 0.03, 'vol': 0.03},
}

# ==== 保险 (xlsx 真实) ====
INS_INIT = 1_853_233
STOCK_INIT = 281_246
INS_GROWTH_EARLY = 0.04
INS_GROWTH_LATE = 0.034
STOCK_GROWTH = 0.04
INS_WITHDRAW = 5700
LIVING_COST_50 = 7000
PENSION_63 = 3000

# ==== 5 方案 (A/B/C/D/E) ====
PLANS = {
    'A 5000全纳指':                     {'ndx': 5000, 'hs300': 0,    'div': 0,    'bond': 2000},
    'B 3000纳+2000中证红利':             {'ndx': 3000, 'hs300': 0,    'div': 2000, 'bond': 2000},  # v4 推荐
    'C 3000纳+2000沪深300':              {'ndx': 3000, 'hs300': 2000, 'div': 0,    'bond': 2000},
    'D 2000纳+3000沪深300':              {'ndx': 2000, 'hs300': 3000, 'div': 0,    'bond': 2000},
    'E 2000纳+2000红利+1000沪深300 ⭐':  {'ndx': 2000, 'hs300': 1000, 'div': 2000, 'bond': 2000},
}

def sim_acc(plan):
    end_ndx, end_hs, end_div, end_bond, max_dd = [], [], [], [], []
    for _ in range(N_ACC):
        ndx, hs, div, bond = 0.0, 0.0, 0.0, 0.0
        peak, dd_max = 0, 0
        for _ in range(ACC_MONTHS):
            r_ndx = np.random.normal(ASSETS_ACC['ndx']['mean']/12, ASSETS_ACC['ndx']['vol']/np.sqrt(12))
            r_hs  = np.random.normal(ASSETS_ACC['hs300']['mean']/12, ASSETS_ACC['hs300']['vol']/np.sqrt(12))
            r_div = np.random.normal(ASSETS_ACC['div']['mean']/12, ASSETS_ACC['div']['vol']/np.sqrt(12))
            r_b   = np.random.normal(ASSETS_ACC['bond']['mean']/12, ASSETS_ACC['bond']['vol']/np.sqrt(12))
            ndx  = (ndx  + plan['ndx'])  * (1 + r_ndx)
            hs   = (hs   + plan['hs300']) * (1 + r_hs)
            div  = (div  + plan['div'])  * (1 + r_div)
            bond = (bond + plan['bond']) * (1 + r_b)
            tot = ndx + hs + div + bond
            peak = max(peak, tot)
            if peak > 0: dd_max = max(dd_max, (peak-tot)/peak)
        end_ndx.append(ndx); end_hs.append(hs); end_div.append(div); end_bond.append(bond)
        max_dd.append(dd_max)
    arr = np.array([a+b+c+d for a,b,c,d in zip(end_ndx, end_hs, end_div, end_bond)])
    return {
        'p10': float(np.percentile(arr, 10)),
        'p25': float(np.percentile(arr, 25)),
        'p50': float(np.median(arr)),
        'p75': float(np.percentile(arr, 75)),
        'p90': float(np.percentile(arr, 90)),
        'dd_p50': float(np.median(max_dd)),
        'dd_p95': float(np.percentile(max_dd, 95)),
        'loss': float(np.mean(arr < 840000) * 100),
        'ndx_p50': float(np.median(end_ndx)),
        'hs_p50': float(np.median(end_hs)),
        'div_p50': float(np.median(end_div)),
        'bond_p50': float(np.median(end_bond)),
    }

def sim_ret(plan, acc):
    succ, end_v, bk_ages = 0, [], []
    for _ in range(N_RET):
        ndx, hs, div, bond = acc['ndx_p50'], acc['hs_p50'], acc['div_p50'], acc['bond_p50']
        ins, stock = INS_INIT, STOCK_INIT
        bankrupt = False
        for m in range(RET_MONTHS):
            age = 50 + m/12
            ndx *= (1 + np.random.normal(ASSETS_RET['ndx']['mean']/12, ASSETS_RET['ndx']['vol']/np.sqrt(12)))
            hs  *= (1 + np.random.normal(ASSETS_RET['hs300']['mean']/12, ASSETS_RET['hs300']['vol']/np.sqrt(12)))
            div *= (1 + np.random.normal(ASSETS_RET['div']['mean']/12, ASSETS_RET['div']['vol']/np.sqrt(12)))
            bond *= (1 + np.random.normal(ASSETS_RET['bond']['mean']/12, ASSETS_RET['bond']['vol']/np.sqrt(12)))
            ins *= (1 + (INS_GROWTH_EARLY if age < 68 else INS_GROWTH_LATE)/12)
            stock *= (1 + STOCK_GROWTH/12)
            ins -= INS_WITHDRAW
            if ins < 0: ins = 0
            cost = LIVING_COST_50 * ((1 + INFLATION) ** (age - 50))
            pen = PENSION_63 * ((1 + INFLATION) ** max(0, age-63))
            gap = cost - INS_WITHDRAW - pen
            if gap > 0:
                if stock >= gap: stock -= gap
                else:
                    gap -= stock; stock = 0
                    if bond >= gap: bond -= gap
                    else:
                        gap -= bond; bond = 0
                        if div >= gap: div -= gap
                        else:
                            gap -= div; div = 0
                            if hs >= gap: hs -= gap
                            else:
                                gap -= hs; hs = 0
                                if ndx >= gap: ndx -= gap
                                else:
                                    bankrupt = True; bk_ages.append(age); break
        if not bankrupt:
            succ += 1
            end_v.append(ndx + hs + div + bond + ins + stock)
    return {
        'success': succ/N_RET*100,
        'p10': float(np.percentile(end_v, 10)) if end_v else 0,
        'p25': float(np.percentile(end_v, 25)) if end_v else 0,
        'p50': float(np.median(end_v)) if end_v else 0,
        'p75': float(np.percentile(end_v, 75)) if end_v else 0,
        'p90': float(np.percentile(end_v, 90)) if end_v else 0,
        'mean_bk_age': float(np.mean(bk_ages)) if bk_ages else 150,
    }

print("="*90)
print("参数: 纳指 13%/25%  沪深300 10%/25%  中证红利 8.3%/18%  纯债 3%/3%")
print("="*90)
print("Phase 1: 40-50岁 10年积累期 (10,000次)")
print("="*90)
print(f"{'方案':<40}{'P10':>10}{'P50':>10}{'P90':>10}{'回撤':>9}{'亏损%':>8}")
print("-"*90)
accs = {}
for name, p in PLANS.items():
    r = sim_acc(p)
    accs[name] = r
    print(f"{name:<40}{r['p10']/10000:>8.1f}万{r['p50']/10000:>8.1f}万{r['p90']/10000:>8.1f}万{r['dd_p50']*100:>7.1f}%{r['loss']:>7.1f}%")

print()
print("="*90)
print("Phase 2: 50-150岁 100年退休期 (5,000次, 含保险+通胀+养老金)")
print("="*90)
print(f"{'方案':<40}{'不破产率':>10}{'破产年龄':>10}{'150岁P50':>12}{'150岁P10':>12}")
print("-"*90)
rets = {}
for name, p in PLANS.items():
    r = sim_ret(p, accs[name])
    rets[name] = r
    print(f"{name:<40}{r['success']:>8.1f}%{r['mean_bk_age']:>8.1f}岁{r['p50']/10000:>10.1f}万{r['p10']/10000:>10.1f}万")

# 保存
output = {
    'parameters': {
        'inflation': INFLATION,
        'assets_acc': ASSETS_ACC,
        'assets_ret': ASSETS_RET,
        'ins_initial': INS_INIT,
        'stock_initial': STOCK_INIT,
        'ins_withdrawal_monthly': INS_WITHDRAW,
        'pension_at_63': PENSION_63,
        'n_sims_acc': N_ACC,
        'n_sims_ret': N_RET,
    },
    'plans': PLANS,
    'accumulation': {name: {k: v for k, v in r.items() if k not in ['ndx_p50','hs_p50','div_p50','bond_p50']} for name, r in accs.items()},
    'accumulation_p50': {name: {'ndx': r['ndx_p50'], 'hs300': r['hs_p50'], 'div': r['div_p50'], 'bond': r['bond_p50']} for name, r in accs.items()},
    'retirement': rets,
    'cashflow_table': {
        str(age): {
            'cost': LIVING_COST_50 * ((1 + INFLATION) ** (age - 50)) if age >= 50 else 0,
            'insurance': INS_WITHDRAW,
            'pension': PENSION_63 * ((1 + INFLATION) ** max(0, age-63)) if age >= PENSION_63 else 0,
            'gap': (LIVING_COST_50 * ((1 + INFLATION) ** (age - 50)) if age >= 50 else 0) - INS_WITHDRAW - (PENSION_63 * ((1 + INFLATION) ** max(0, age-63)) if age >= PENSION_63 else 0),
        }
        for age in [50, 55, 60, 62, 63, 65, 70, 80, 90, 100, 120, 150]
    },
}
with open('sim_v4.json', 'w', encoding='utf-8') as f:
    json.dump(output, f, ensure_ascii=False, indent=2)
print()
print("📁 sim_v4.json 已保存 (5 方案)")
