ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

美赛财产保险可持续性建模:Python可复现方案与破产概率模拟

美赛财产保险可持续性建模:Python可复现方案与破产概率模拟 简介这份资源是2024年美国大学生数学建模竞赛ICM Problem E的完整参赛作品围绕财产保险可持续性这一议题用Python构建了从数据预处理到建模预测的全流程方案。内容适合数学建模初学者、进阶学习者以及需要完成课程设计、大作业或毕业设计的学生参考也可作为保险精算与风险评估方向的入门实践案例。压缩包共43个文件约18.43MB包含7个Python脚本、3个Excel数据表、16张PNG与7张SVG图表、2份PDF文档及LaTeX源码等覆盖灰色预测、层次分析、模糊综合评价、灰色关联与支持向量机等多类模型实现。资源中附有ROC曲线、PCA降维对比、混淆矩阵、灵敏度分析等可视化结果以及可复用的svm_model.pkl模型文件便于读者理解建模思路、复现实验流程并迁移到同类赛题。目前已有111人学习下载适合希望系统掌握美赛建模方法与Python实现技巧的读者。1. 财产保险可持续性建模从一道美赛题到可复现的 Python 方案2024年美国大学生数学建模竞赛的这道题核心是给财产保险的可持续性建一套能算、能调、能解释的模型。很多人第一反应是去搜优秀论文但真正动手时卡在三个地方极端天气导致的巨灾赔付怎么量化、保险定价里的风险因子怎么选、Python 里用什么库把这三者串起来。这篇笔记不聊论文怎么写只讲一个一线工程师会怎么把这道题拆成可运行的代码从数据构造、风险建模到可持续性指标计算每一步都给参数和踩坑记录。适合正在准备数学建模竞赛的学生也适合想用 Python 做保险精算原型的从业者。读完你能拿到一套能跑通的骨架改改参数就能套到类似题目上。2. 财产保险可持续性的建模骨架三个模块与数据从哪来2.1 可持续性到底在算什么赔付率、费率与资本充足财产保险的可持续性落到公式上就是三个量的平衡赔付率Loss Ratio、费率充足度Rate Adequacy和资本缓冲Capital Buffer。赔付率是赔款除以保费费率充足度是实际费率与目标费率的比值资本缓冲是可用资本除以风险资本。这三个指标任何一个长期失衡保险产品就不可持续。美赛题里通常会给一个地区多年的气象数据和保单数据要求你评估在气候变化下这套保险还能不能做下去。我一般会把问题拆成三层第一层是风险层用历史灾害数据拟合极端事件的频率和强度分布第二层是定价层把风险层的输出映射成纯保费再加上费用和利润附加第三层是可持续层用蒙特卡洛模拟未来多年的赔付和资本变化看破产概率。这三层在 Python 里分别对应 scipy.stats 做分布拟合、numpy 做定价计算、numpy 加循环做模拟。不要一上来就写模拟先把前两层的数据结构定清楚不然后面改参数会非常痛苦。提示美赛题给的数据往往不完整气象数据可能只有站点日值保单数据可能只有年度汇总。常见做法是用公开的 NOAA 或 ERA5 再分析数据补气象用题里给的保单结构反推暴露度。2.2 数据构造用 Python 生成可复现的模拟数据集真实竞赛数据往往有缺失我习惯先构造一份可控的模拟数据来验证模型逻辑再替换成真实数据。下面这段代码生成一个地区 20 年的财产暴露度、灾害事件和赔付记录。关键参数是暴露度增长率、灾害频率和赔付分布的形状参数。import numpy as np import pandas as pd np.random.seed(42) # 固定随机种子保证结果可复现 years np.arange(2004, 2024) n_years len(years) # 暴露度初始 1000 亿每年增长 3% exposure 1000 * (1.03 ** np.arange(n_years)) # 灾害频率泊松分布均值从 2 次/年线性增到 4 次/年 freq_lambda np.linspace(2, 4, n_years) n_events np.random.poisson(freq_lambda) # 每次事件的赔付对数正态分布均值随暴露度缩放 records [] for i, y in enumerate(years): for e in range(n_events[i]): # 对数正态参数mu 随年份略增sigma 固定 mu np.log(exposure[i] * 0.01) 0.1 * i sigma 0.8 loss np.random.lognormal(mu, sigma) records.append({year: y, event_id: e, loss: loss}) df pd.DataFrame(records) print(df.groupby(year)[loss].sum().head())这段代码的逻辑是暴露度按复利增长灾害次数用泊松分布模拟单次赔付用对数正态分布。参数0.01是基准损失率0.1 * i让损失随年份缓慢上升模拟气候变化影响。sigma0.8控制赔付的尾部厚度值越大极端事件越多。跑完你会得到一个按年汇总的赔付序列后面定价和模拟都用它。注意随机种子必须固定否则每次跑出来的可持续性指标都不一样论文里没法复现。我见过有人忘了设种子结果答辩时被问为什么两次结果差 20%。2.3 风险层建模拟合频率与强度的分布拿到赔付记录后第一步是拟合频率分布和强度分布。频率用泊松或负二项强度用对数正态或帕累托。Python 里用 scipy.stats 的 fit 方法可以快速得到参数但要注意拟合前先做描述性统计看看有没有明显的离群值。from scipy import stats # 频率拟合每年事件数 annual_counts df.groupby(year).size().values mu_freq annual_counts.mean() print(f泊松均值: {mu_freq:.2f}) # 强度拟合单次赔付的对数正态参数 losses df[loss].values shape, loc, scale stats.lognorm.fit(losses, floc0) print(f对数正态 shape{shape:.3f}, scale{scale:.3f}) # 拟合优度检验KS 检验 ks_stat, p_value stats.kstest(losses, lognorm, args(shape, 0, scale)) print(fKS 统计量{ks_stat:.4f}, p值{p_value:.4f})floc0强制位置参数为零因为赔付不可能是负数。shape就是对数正态的 sigmascale是 exp(mu)。KS 检验的 p 值大于 0.05 说明拟合可以接受。如果 p 值很小说明尾部拟合不好常见做法是换帕累托分布或者用极值理论里的广义帕累托分布拟合超阈值部分。这一步的参数直接决定后面纯保费的大小所以不要跳过拟合优度检验。3. 定价与可持续性模拟把参数变成可调的函数3.1 纯保费计算从期望赔付到风险附加纯保费等于期望赔付加上风险附加。期望赔付用频率乘以强度期望风险附加常用方差原理或标准差原理。下面这个函数把前面的拟合参数封装起来输入暴露度和年份输出纯保费。def pure_premium(exposure, mu_freq, shape, scale, loading0.3): exposure: 暴露度保额 mu_freq: 年灾害频率均值 shape, scale: 对数正态参数 loading: 风险附加系数默认 0.3 expected_loss mu_freq * scale * np.exp(shape**2 / 2) # 方差原理的风险附加 var_loss mu_freq * (scale**2) * (np.exp(shape**2) - 1) * np.exp(shape**2) risk_load loading * np.sqrt(var_loss) return expected_loss risk_load # 计算 2024 年的纯保费 premium_2024 pure_premium(exposure[-1], mu_freq, shape, scale) print(f2024 年纯保费: {premium_2024:.2f})loading0.3是风险附加系数实际定价里这个值由资本成本和目标偿付能力决定。expected_loss是对数正态的期望公式var_loss是方差公式。这两个公式在精算教材里都有但很多人写代码时会把方差公式里的 exp 项漏掉导致风险附加偏小。跑完这个函数你得到的是一个基准纯保费后面模拟里可以按年份调整暴露度和频率参数。3.2 蒙特卡洛模拟未来 30 年破产概率怎么算可持续性的核心指标是破产概率即资本金不足以覆盖赔付的概率。用蒙特卡洛模拟未来 30 年每年抽样灾害次数和赔付额扣掉保费收入看资本金什么时候跌破零。def simulate_ruin(initial_capital, premium, mu_freq, shape, scale, n_years30, n_sims10000, expense_ratio0.25): initial_capital: 初始资本金 premium: 年保费收入 expense_ratio: 费用率从保费里扣除 ruin_count 0 for _ in range(n_sims): capital initial_capital for y in range(n_years): n_events np.random.poisson(mu_freq) losses np.random.lognormal( np.log(scale), shape, n_events ).sum() net_premium premium * (1 - expense_ratio) capital net_premium - losses if capital 0: ruin_count 1 break return ruin_count / n_sims # 假设初始资本 500 亿年保费 80 亿 ruin_prob simulate_ruin(500, 80, mu_freq, shape, scale) print(f30 年破产概率: {ruin_prob:.4f})n_sims10000是模拟次数次数越多结果越稳定但计算时间线性增长。expense_ratio0.25是费用率包括运营成本和佣金。内层循环每年抽样一次灾害次数和赔付总额更新资本金。如果资本金跌破零就记一次破产并跳出。这个函数跑 10000 次大概需要几十秒如果嫌慢可以把 n_sims 降到 5000但破产概率的置信区间会变宽。提示破产概率对初始资本和保费非常敏感。我一般会先跑一个基准场景然后做敏感性分析看破产概率随保费变化的曲线找到使破产概率低于 1% 的最低保费。3.3 可持续性指标把破产概率翻译成业务语言破产概率是统计语言业务方更关心的是「保费要涨多少才能可持续」。我一般会算两个衍生指标一是可持续保费即让破产概率等于目标值比如 1%的保费二是保费缺口即当前保费与可持续保费的差值。from scipy.optimize import brentq def target_ruin(premium, target0.01): return simulate_ruin(500, premium, mu_freq, shape, scale) - target # 二分法找可持续保费 sustainable_premium brentq(target_ruin, 50, 200) print(f可持续保费: {sustainable_premium:.2f}) print(f保费缺口: {sustainable_premium - 80:.2f})brentq是 scipy 里的二分法求根函数在 50 到 200 之间找使破产概率等于 1% 的保费。这个函数每次调用都会跑一遍模拟所以总计算量是模拟次数乘以迭代次数。如果嫌慢可以先用粗网格搜索缩小范围再用二分法精修。跑完你会得到一个具体的保费数字这个数字就是论文里最有说服力的结论之一。4. 避坑与排查建模时最容易翻车的五个地方4.1 分布拟合不检验尾部风险被低估现象模拟出来的破产概率很低但实际历史数据里出现过极端赔付。原因直接用对数正态拟合全部数据尾部被平均掉了。解决用极值理论拟合超阈值部分或者用帕累托分布替换对数正态。我一般会画 QQ 图看尾部偏离程度。4.2 暴露度增长和灾害频率增长混在一起现象纯保费逐年上升但分不清是暴露度涨了还是灾害变多了。原因两个参数都随时间变化没有做分离。解决固定一个参数做敏感性分析或者用回归模型分别估计趋势。常见做法是把暴露度标准化只看单位暴露度的损失率变化。4.3 蒙特卡洛模拟次数太少结果不稳定现象每次跑出来的破产概率差好几个百分点。原因n_sims 太小抽样误差大。解决至少跑 10000 次或者用方差缩减技术。我习惯先跑 1000 次看大概范围再跑 10000 次出最终结果。4.4 忘了扣费用和再保险现象保费收入全用来赔付资本金永远不降。原因没有扣费用率和再保险分出。解决在模拟里加 expense_ratio 和再保险层。再保险可以用一个简单的分层函数模拟比如赔付超过自留额的部分分给再保人。4.5 随机种子没固定论文无法复现现象答辩时评委让你现场跑一遍结果和论文里不一样。原因没有设 np.random.seed。解决在代码开头固定种子并在论文里注明。如果用了多个随机过程每个都要设独立的种子。5. 进阶技巧用敏感性分析找到可持续性的临界点敏感性分析是这道题的加分项。我一般会做三组保费对破产概率的敏感性、初始资本对破产概率的敏感性、灾害频率对可持续保费的影响。下面这段代码用循环生成敏感性曲线比手动改参数快得多。import matplotlib.pyplot as plt premiums np.linspace(60, 120, 13) ruin_probs [simulate_ruin(500, p, mu_freq, shape, scale, n_sims2000) for p in premiums] plt.plot(premiums, ruin_probs, markero) plt.axhline(0.01, colorr, linestyle--, label目标 1%) plt.xlabel(年保费亿) plt.ylabel(30 年破产概率) plt.legend() plt.savefig(sensitivity.png, dpi150)n_sims2000是为了加快敏感性分析的速度最终结论再用 10000 次跑。axhline画出 1% 的目标线曲线与目标线的交点就是可持续保费。这张图放在论文里比一张表格直观得多。我还会把灾害频率的均值从 2 调到 6看可持续保费怎么变通常频率每增加 1 次保费要涨 15% 到 25%。最后一个习惯每次改完参数先跑一遍基准场景确认没报错再跑敏感性分析。我踩过的最大坑是改了一个参数忘了同步改另一个结果整晚的模拟都白跑了。希望帮到你。本文还有配套的精品资源点击获取
返回列表