skills/ppt-station-skill/reference/layout-waterfall.md
wangyitong a65adcc2e5 Initial commit: merged, deduplicated, and vetted skill collection
Sources: extracted from two upstream archives (skill-repo, skills-main),
merged with the following policy:

- 15 broken symlinks (pointing to /Users/jameslee/.cc-switch/skills or
  ../../.agents/skills on a foreign machine) discarded
- 3 real name collisions with identical content (ai-pair, ifind-http-api,
  zhipu-websearch) kept as one copy
- Functional overlaps deduped keeping the strongest variant:
  - docx family: kept docx (official, full toolchain) + docx-cn
    (GB/T 9704 Chinese official-document constants),
    dropped docx_writer (no scripts, name collided with docx)
  - humanizer family: kept humanizer-zh (6 zh reference docs),
    dropped humanizer (en, redundant for CN workflow)
- Skills that only ran in a foreign environment removed:
  ablemind-ops, app-publish, hlb-design-system, openclaw-adj-skill,
  claude-driver
- alphapai excluded from this public repo because its SKILL.md hard-coded
  live credentials

Result: 25 skills, 572 files, ~7.5 MB.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 14:47:12 +08:00

10 KiB
Raw Blame History

Layout: waterfall — 瀑布图/归因分析

幻灯片尺寸: 13.333 × 7.5 英寸 | 边距: 0.6 英寸 | 内容宽: 12.133 英寸


用途

收益归因、成本分解、利润桥图Profit Bridge、组合贡献分析。 展示"从起点 → 各因素贡献 → 终点"的累积变化过程。


ASCII 线框图

┌─────────────────────────────────────────────────────────────┐
│ [标题]                                          y=0.25       │
│ ▬▬ (accent 装饰线 2.0")                         y=0.90       │
│                                                              │
│  起始值        增加项    增加项    减少项    最终值           │
│  ┌──────┐      ┌──────┐                                     │
│  │      │      │ +██  │ +██      │      │                   │
│  │ 基础 │      │      │          │ -██  │ ┌──────┐          │
│  │      │      │      │          │      │ │ 合计 │          │
│  └──────┘      └──────┘          └──────┘ └──────┘          │
│   8.50%        +2.10%  +1.30%   -1.80%   10.10%            │
│  [期初收益]   [权益贡献] [债券贡献] [汇率拖累] [期末收益]   │
│                                                              │
└─────────────────────────────────────────────────────────────┘

数据结构说明

瀑布图数据包含:

  • start — 起始值(期初,作为第一个完整柱)
  • items — 各贡献因素(浮动柱,正向或负向)
  • end — 终止值(期末,作为最后一个完整柱,可自动计算)

精确坐标标注

固定元素

元素 x y w h 字号 颜色 对齐
页面标题 0.60 0.25 12.133 0.60 title_size-2 text_dark
装饰线 0.60 0.90 2.00 0.04 accent
零基准线 0.60 图表区中心 12.133 0.02 text_muted

图表区域

参数 说明
chart_x 0.60 图表左边界
chart_y 1.30 图表顶部(内容区起始)
chart_w 12.133 图表宽度
chart_h 5.50 图表高度(到 y=6.80
bar_area_h 4.00 柱体绘制区高度y=1.50 ~ y=5.50
label_y 5.60 标签行 y柱下方
value_y 1.20 数值标注 y柱上方浮动
footer_y 6.20 数据来源行

柱体尺寸计算

N = len(items) + 2    # 总柱数start + items + end
bar_gap = 0.20        # 柱间距(英寸)
bar_w = (chart_w - bar_gap * (N - 1)) / N   # 每柱宽

# N=5: bar_w = (12.133 - 0.80) / 5 = 2.267"
# N=6: bar_w = (12.133 - 1.00) / 6 = 1.856"
# N=7: bar_w = (12.133 - 1.20) / 7 = 1.562"
# N=8: bar_w = (12.133 - 1.40) / 8 = 1.342"

bar_x[i] = chart_x + i * (bar_w + bar_gap)

柱体高度计算

# 图表坐标系
y_axis_max = max(所有累积值的最大值) * 1.15    # 留 15% 上边距
y_axis_min = min(所有累积值的最小值) * 1.15    # 留 15% 下边距(负值时)
y_range = y_axis_max - y_axis_min

# 将数据值映射到像素(英寸)
def value_to_y(v):
    return chart_y + bar_area_h * (1 - (v - y_axis_min) / y_range)

# 起始柱完整柱从0到start_value
start_bar_top = value_to_y(start_value)
start_bar_bottom = value_to_y(0)
start_bar_h = start_bar_bottom - start_bar_top

# 贡献柱(浮动柱,从累积值到累积值+delta
for item in items:
    bar_top = value_to_y(max(cumsum, cumsum + item.value))
    bar_bottom = value_to_y(min(cumsum, cumsum + item.value))
    bar_h = bar_bottom - bar_top
    cumsum += item.value

# 连接虚线(前一柱的浮动底部 → 当前柱底部)
连接线: w=bar_gap, h=0.01, 颜色=text_muted, 虚线样式

颜色规则

柱类型 条件 颜色变量
起始柱 primary
正向贡献柱 item.value > 0 positive
负向贡献柱 item.value < 0 negative
终止柱 primary
连接虚线 text_muted

数值标注(柱顶/底 + 数值)

元素 位置 字号 颜色 格式
起始/终止数值 柱顶上方 0.10" body_size text_dark "X.XX%"
正向贡献值 柱顶上方 0.10" body_size positive "+X.XX%"
负向贡献值 柱底下方 0.10" body_size negative "-X.XX%"
柱体内标注(高柱时) 柱体垂直居中 body_size-1 text_light 同上

底部标签行

元素 x y w h 字号 颜色 对齐
柱体标签 bar_x[i] 5.60 bar_w 0.45 caption_size text_muted

数据接口

data = {
    "title": str,                    # 页面标题
    "subtitle": str,                 # 可选,如 "2024年全年收益归因分析"
    "start": {
        "label": str,                # 如 "期初收益"
        "value": float,              # 如 8.50
        "value_fmt": str,            # 如 "8.50%" 或 "850亿"
    },
    "items": [
        {
            "label": str,            # 贡献因素名称8字以内
            "value": float,          # 数值(正=向上,负=向下)
            "value_fmt": str,        # 显示文字(如 "+2.10%"
            "direction": "up" | "down",  # 可选,若不传则根据 value 符号判断
        },
        ...
    ],
    "end": {
        "label": str,                # 如 "期末收益"
        "value": float | None,       # None则自动计算(start + sum(items))
        "value_fmt": str | None,
    },
    "unit": str,                     # 可选,如 "%" 或 "亿元"用于Y轴标注
    "show_connector": bool,          # 是否显示连接虚线,默认 True
}

实现伪代码

def layout_waterfall(slide, data, theme):
    m = theme["margin"]
    sw = 13.333
    cw = sw - 2 * m    # 12.133

    set_slide_bg(slide, theme["bg_light"])
    add_text(slide, data["title"],
             x=m, y=0.25, w=cw, h=0.60,
             font_size=theme["title_size"]-2, color=theme["text_dark"],
             bold=True, font_name=theme["header_font"])
    add_rect(slide, m, 0.90, 2.0, 0.04, fill=theme["accent"])

    # 计算柱体布局
    all_bars = [data["start"]] + data["items"] + [data["end"]]
    N = len(all_bars)
    bar_gap = 0.20
    bar_w = (cw - bar_gap * (N - 1)) / N

    chart_y = 1.50
    bar_area_h = 4.00

    # 计算值域
    cumsum = data["start"]["value"]
    all_values = [0, cumsum]
    for item in data["items"]:
        cumsum += item["value"]
        all_values.append(cumsum)
    end_val = data["end"].get("value") or cumsum
    all_values.append(end_val)

    y_max = max(all_values) * 1.15
    y_min = min(all_values) * 1.15 if min(all_values) < 0 else 0
    y_range = y_max - y_min

    def val_to_y(v):
        return chart_y + bar_area_h * (1 - (v - y_min) / y_range)

    # 绘制零线
    zero_y = val_to_y(0)
    add_rect(slide, m, zero_y, cw, 0.015, fill=theme["text_muted"])

    # 绘制柱体
    cumsum = 0
    prev_top_y = None
    for i, bar in enumerate(all_bars):
        bx = m + i * (bar_w + bar_gap)
        is_total = (i == 0 or i == N - 1)

        if is_total:
            v = bar.get("value", cumsum)
            top_y = val_to_y(max(v, 0))
            bot_y = val_to_y(min(v, 0))
            color = theme["primary"]
        else:
            v = bar["value"]
            base = cumsum
            top_y = val_to_y(max(base, base + v))
            bot_y = val_to_y(min(base, base + v))
            color = theme["positive"] if v >= 0 else theme["negative"]
            cumsum += v

        bar_h = bot_y - top_y
        add_rect(slide, bx, top_y, bar_w, bar_h, fill=color)

        # 连接线
        if prev_top_y is not None and data.get("show_connector", True) and not is_total:
            add_rect(slide, bx - bar_gap, prev_top_y, bar_gap, 0.01,
                     fill=theme["text_muted"])
        prev_top_y = bot_y if v >= 0 else top_y

        # 数值标注
        fmt = bar.get("value_fmt", f"{v:+.2f}%")
        label_y = top_y - 0.30 if v >= 0 else bot_y + 0.05
        add_text(slide, fmt,
                 x=bx, y=label_y, w=bar_w, h=0.28,
                 font_size=theme["body_size"], color=color,
                 bold=True, align="center", font_name=theme["body_font"])

        # 底部标签
        add_text(slide, bar["label"],
                 x=bx, y=5.60, w=bar_w, h=0.45,
                 font_size=theme["caption_size"], color=theme["text_muted"],
                 align="center", font_name=theme["body_font"])

设计要点

  1. 柱间连接虚线 从前一柱的"累积底部"水平延伸到当前柱,帮助读者追踪累积过程
  2. 数值标注位置: 正向柱标在顶部上方,负向柱标在底部下方(避免遮挡柱体)
  3. 起始/终止柱(汇总柱)用 primary 色,与贡献柱颜色形成视觉区分
  4. 最多 8 个柱(含起始和终止);超过时建议合并小贡献项为"其他"
  5. 含负值时零线显示并加粗0.02"),负值柱延伸到零线以下

测试数据示例

data = {
    "title": "2024年组合收益归因分析",
    "subtitle": "单位: 百分点(%",
    "start": {"label": "期初基准", "value": 0, "value_fmt": "0%"},
    "items": [
        {"label": "权益资产", "value": 3.20, "value_fmt": "+3.20%"},
        {"label": "债券资产", "value": 1.80, "value_fmt": "+1.80%"},
        {"label": "另类资产", "value": 0.90, "value_fmt": "+0.90%"},
        {"label": "汇率影响", "value": -0.60, "value_fmt": "-0.60%"},
        {"label": "费用扣除", "value": -0.30, "value_fmt": "-0.30%"},
    ],
    "end": {"label": "期末收益", "value": None, "value_fmt": None},  # 自动计算=5.00%
}

与 投行级研报 GTM 的对应

投行级研报 P4GDP分解、P44EPS贡献等页面均使用堆叠柱变体。 真正的"利润桥"瀑布图(浮动柱)在收益归因报告中极为常见,需单独布局支持。