# Asset Allocation

> 给个人投资者做资产配置方案：问清能承受多少亏损和本金情况，算出具体到 ETF 代码和权重的组合， 并用历史回测验证「最大回撤不超过 X%」这个承诺真的守得住，最后出一份报告。覆盖 A 股宽基、 债券、黄金、海外 QDII、行业主题 ETF。**被动配置，不预测涨跌、不选赛道。** Use when 用户想配资产组合、问「我这些钱该怎么分」「能承受 20% 亏损该怎么配」「帮我做个资产配置」 「组合该怎么调」「现在该再平衡了吗」「我的持仓偏离目标了吗」，或者给了本金和风险承受力想要一份方案。 Triggers on 资产配置、资产组合、配置比例、大类配置、组合方案、风险承受、最大回撤、再平衡、 仓位分配、股债配比、asset allocation、portfolio allocation、rebalance。 NOT for: 选个股、看某只股票好不好、预测大盘涨跌、短线交易、追热点板块。

- Skill: `henrywen98/asset-allocation` (Agent Skill, multi-file: 7 files)
- Install (CLI): `npx skillmds@latest add henrywen98/asset-allocation`
- Raw SKILL.md: https://api.skillmd.com/api/skills/henrywen98/asset-allocation/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: henrywen98 (https://skillmd.com/u/henrywen98)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/henrywen98/asset-allocation

---


# 资产配置

把「我有多少钱、最多能亏多少」变成「买哪几只 ETF、各占多少」，并且用历史数据证明那个「最多能亏多少」的承诺站得住。

## 三条不能破的规矩

**1. 不预测涨跌。** 组合由风险约束决定，不由对后市的看法决定。搜到的市场资讯只用来决定建仓节奏和写风险提示，**不用来调整权重**。用户问「现在该买什么方向」时，如实说这个 skill 不做方向判断，然后给他被动方案。

**2. 回撤守不住就直说。** `allocate.py` 抛 `InfeasibleConstraint` 时，原样把「最保守的组合历史回撤也有 X%」告诉用户，让他选放宽上限还是接受更低收益。**绝不自己放宽约束凑一个组合出来。**

**3. 报告里的回撤要报 p95，不要只报实现值。** 实现值是单次抽样，系统性乐观。正确说法是
「中位情形回撤 X%，二十分之一的概率超过 Y%」，不是「最大回撤 X%」。

回测窗口从 2014 年起，不含 2008 年。但自助在这里帮了忙：全仓沪深300 的自助 p95 是
-72.0%，而它 2008 年的真实回撤是 -72.3%——样本外那次崩盘的量级被恢复出来了。这说明
区块自助确实能外推一部分尾部，但它抓不到危机中相关性集体冲向 1 的情形。

## 流程

### 第 1 步：风险画像

必须问两组问题，**不能只问一组**。详见 `references/risk-profiling.md`。

- **意愿**（心理）：账户浮亏多少会让你睡不着 / 想割肉？
- **能力**（财务）：这笔钱多久不用？收入稳不稳？除这笔钱外有没有 6 个月的应急金？这笔钱占你总资产多大比例？

**两者冲突时取低的那个**，并在报告里写明按哪个来、为什么。一个说能扛 50% 但三年后要买房的人，实际上限远低于 50%。

同时问到：**本金金额**、**投资期限**、**是否已有持仓**。

### 第 2 步：确定资产菜单

默认核心四类，代码和理由见 `references/asset-menu.md`：

| 代码 | 名称 | 类别 | 建议上限 |
|------|------|------|----------|
| 510300 | 沪深300ETF | equity | 50% |
| 510500 | 中证500ETF | equity | 30% |
| 510880 | 红利ETF | equity | 30% |
| 511010 | 国债ETF | bond | 80% |
| 518880 | 黄金ETF | gold | 20% |
| 513100 | 纳指ETF | overseas | 25% |

**行业/主题 ETF 不进核心优化。** 它们最早的（512880 证券、512660 军工）也是 2016-08 才上市，2015 年那波暴跌不在数据里，回撤约束覆盖不到。要配就单独走「卫星仓」，合计 ≤ 20%，并在报告里写明这部分不受回撤约束保护。

### 第 3 步：拉数据

```bash
python3 scripts/fetch_history.py \
  --codes 510300,510500,510880,511010,518880,513100 \
  --start 2014-01-01 --out data/core_prices.csv
```

纯标准库，不需要 venv。数据源是腾讯（免 key、不封 IP）。东财的历史接口在部分网络下被 DNS 劫持，所以不用它。

### 第 4 步：算权重

```bash
.venv/bin/python scripts/allocate.py \
  --prices data/core_prices.csv \
  --specs data/core_specs.json \
  --max-dd 0.20
```

`--max-dd 0.20` 就是第 1 步问出来的那个数（取能力和意愿的低者）。

**默认按自助 p95 口径判定，不是历史实现值。** 历史上实现的那一个最大回撤是单条路径的
一次抽样，有效样本量为 1，拿它当上限系统性乐观——实测在这套资产上乐观约 6 个百分点。
所以 `allocate.py` 会跑平稳区块自助，用回撤分布的 95 分位来卡约束。代价是慢一些
（几秒到十几秒）。想要旧行为传 `--risk-metric realized`，但要知道你拿到的数字偏乐观。

输出 JSON，含 `weights`、`metrics`、`bootstrap`、`robustness`、`holding_period`、`frontier`。

**必看 `frontier`。** 它是各回撤档位上能拿到的最高年化，直接回答「多承受 10% 回撤能多赚多少」。实测这条曲线在 35-40% 处见顶后下降——多数情况下把上限放到 20% 以上收益增量很小，这个结论要主动告诉用户。

**必看 `robustness.breached_in_subperiod`。** 为 true 说明全窗口达标只是被某一段的大涨稀释了，某个子区间其实破了上限。这时必须在报告里明确警告。

**期限 5 年以内的用户，必须加 `--horizon-years N`（N = 他的期限）。** 最大回撤衡量的是
「中途最难看的时候有多难看」，适合能一直拿着的人。期限短的人真正面对的是**到期那天的盈亏**
——中途跌多深无所谓，到期是亏是赚才决定他能不能拿回本金。加了这个参数会多输出
`holding_period`（持有这么久的收益分布：最差、5 分位、中位、亏钱概率），报告里要放进去。

### 第 5 步：搜当前市况

用 WebSearch 查两件事：

- 主要宽基（沪深300、中证500）当前估值分位
- 近期宏观风险事件

**只影响两个输出**，不改权重：

- **建仓节奏**：估值分位高 → 建议分 6-12 期建仓；分位低 → 可一次性建仓。
- **风险提示段落**。

### 第 6 步：出报告 + 存档案

报告模板见 `references/reporting.md`。存档到 `portfolio-profile.json`。

**档案含个人财务数据，绝不能进任何 git 仓库。** 写档案前先确认目标目录不在版本控制下。

## 何时不适用

- **这笔钱一年内要用** → 先说清楚：一年不够从下跌里恢复，正常做法是货币基金或国债逆回购。
  用户坚持要配的话，必须带 `--horizon-years 1` 并把持有期收益分布放进报告。
- 用户想选个股 → 这个 skill 只做 ETF 大类配置
- 用户想知道现在该买什么方向 → 如实说不做方向判断
- 用户要短线交易或追热点 → 不适用，说明理由
- 本金太小（几千元）→ 场内 ETF 有最小 100 份的买入单位，六只标的分不开，建议先做两三只

## 参考文件

- `references/risk-profiling.md` — 两维问卷、打分、取低规则
- `references/asset-menu.md` — ETF 清单，含各自的坑（QDII 溢价、流动性）
- `references/reporting.md` — 报告模板

## 免责

这是研究和规划工具，不是投资建议。历史回测不预示未来。每份报告结尾都要写这句。

