国内金价破 1000,「涨了多少」和「该买多少」是数学问题

国内金价刚破 1000 元/克,但「涨了多少」和「该买多少」是两门数学

一条新闻,把我们领进三门数学

8 月 24 日那天,我刷朋友圈看到三件事:

  • 第一条是「国内金价首次破 1000 元/克」的推送,配图是上海黄金交易所的收盘截图,显示 1004.21 元/克。
  • 第二条是同事在群里说「黄金这么猛,我加仓了」。
  • 第三条是另一个人在底下回:「涨了这么多,要不要追?买多少合适?」

这三个问题不是同一个问题。第一个问的是「涨了多少」,第二个问的是「明天还会涨吗」,第三个问的是「我该买多少」。第一个是积分的活儿,第二个是泰勒展开的活儿,第三个是带约束优化的活儿。

下面我就拿真实数据,一门一门地把它们拆开。

数据来源:上海黄金交易所 Au99.99 收盘价(2026-07-21 至 2026-08-24,共 25 个交易日,逐日公开),以及过去几年的年均价(约)。每张图都用 Python 从 CSV 重新画,可复现。


1.怎么算「涨了多少」

我从上金所拉了 7 月 21 日到 8 月 24 日共 25 个交易日的逐日 Au99.99 收盘价。长周期的对照锚点用过去几年的年均价。先看一眼全貌:

上半张是 2022 → 2025 的年均价,外加 2026 年截至 8 月 24 日的收盘快照。四年前均价 398,今年冲到 1004,整整翻了 2.5 倍。下半张是这一个多月的逐日线,前两周在 880 上下晃,从 8 月初开始加速,8 月 24 日收盘终于破千。

别把每天的涨幅简单加起来

这段时间到底涨了多少,最直觉的算法是把每天的日收益(今天除以昨天减 1)一路加总。

我跑了一遍:
真实累计涨幅=1004.21÷886.95−1=13.22真实累计涨幅 = 1004.21 ÷ 886.95 − 1 = 13.22% 真实累计涨幅=1004.21÷886.95−1=13.22

  • 7/21 收盘 886.95 元,8/24 收盘 1004.21 元。。
  • 但如果把每天的日收益简单相加,得到的是 12.60%。
  • 差了 0.62 个百分点,看上去不大,可方法上是错的。

因为「加日收益」忽略了一件小事:今天赚的 1%,明天也是按今天涨完之后的本金再算的,也就是常说的复利。正确的做法是把每一天的收益真正"攒"起来,得用对数收益:

每天算一个 ln(今天÷昨天)ln(今天 ÷ 昨天) ln(今天÷昨天),一路累加。

图里那两条线,简单相加是 12.60%,对数收益求和转回来恰好是 13.22%,和真实累计一模一样。

这就是牛顿-莱布尼茨公式的离散版本。连续微积分里有一条:
∫(P′/P)dt=lnP+C∫ (P'/P) dt = ln P + C ∫(P′/P)dt=lnP+C

累计量等于「相对变化率」的积分。换成离散,就是:
「每天的相对变化」=对数收益ln(Pt/ Pt−1 )「每天的相对变化」= 对数收益ln(P_t / P_{t-1}) 「每天的相对变化」=对数收益ln(Pt/Pt−1)

一路加总 = ln(真实累计比),再 exp 回来 = 真实累计涨幅。

三百年这条公式解决的就是这类「把变化攒成总量」的问题。黄金的逐日涨跌,只是它的一份应用题。所以: 算累计收益,先把每天的涨幅取对数再相加,再取指数。这才是精确版本。


2.怎么猜「明天还会涨吗」

每天收盘,你会拿到三个数:今天的价格、昨天到今天的涨幅、过去几天的趋势。朴素做法是"昨天涨了 X%,明天大概也涨 X%",也就是用一个固定斜率往明天平推。

数学上有个更体面的写法,叫泰勒展开。挑一个「展开点」 t0=8月12日 t₀ = 8 月 12 日 t0=8月12日,在那一点附近,把价格 P(t) 写成:
P(t0+h)≈P(t0)+P′(t0) h+ 12! P′′(t0) h2+ 13! P′′(t0) h3+⋯ P(t_0 + h) \approx P(t_0) + P'(t_0)\,h + \tfrac{1}{2!}P''(t_0)\,h^2 + \tfrac{1}{3!}P''(t_0)\,h^3 + \cdots P(t0+h)≈P(t0)+P′(t0)h+2!1P′′(t0)h2+3!1P′′(t0)h3+⋯

每一阶项的分母里都藏着一个阶乘 n!。0 阶是常数,1 阶是线性,2 阶开始抓曲率,3 阶抓曲率的变化。阶越高,分母的阶乘越大,远处那一项衰减得越快。这就是为什么"阶越多、展开点附近越准,但远距离不一定更稳"。

我拿真实的 8 月 12 日算了一下:

  • 当天收盘 P0=955.75元 P₀ = 955.75 元 P0=955.75元。
  • 一阶斜率 P′=(949.24−946.70)/2≈1.27元/天(轻微上行)P′ = (949.24 − 946.70) / 2 ≈ 1.27 元/天(轻微上行) P′=(949.24−946.70)/2≈1.27元/天(轻微上行)。
  • 二阶曲率 P″=949.24−2×955.75+946.70≈−15.56(轻微下凹,也就是拐弯朝下)P″ = 949.24 − 2 × 955.75 + 946.70 ≈ −15.56(轻微下凹,也就是拐弯朝下) P″=949.24−2×955.75+946.70≈−15.56(轻微下凹,也就是拐弯朝下)。

把这三个数代回去,看 8 月 12 日往后 ±2 天,0/1/2 阶泰勒分别说什么:

  • 0 阶是一条平直的黄点线:明天还是 955.75 元。
  • 1 阶是一条倾斜的蓝虚线:明天 957.02 元,后天 958.29 元,直线往上爬。
  • 2 阶是一条带弯曲的绿点划线:在 8 月 13 日几乎完美贴合实际(绿点和黑点重合在 949.24),但到 8 月 14 日就被拉到了 927 元附近,跟实际 940.72 元明显脱钩。 图 3:在 8/12 处做泰勒展开,向左右 ±2 天展示 0/1/2 阶逼近曲线,分母的 0!/1!/2! 标注在图例里。

真相是:8 月 13 日金价小幅下跌,8 月 14 日又继续小幅下跌,和朴素"线性外推往上走"的方向完全相反。一阶泰勒在拐弯处立刻走偏;二阶在展开点附近贴合得很好(这是泰勒的本性),但远离展开点就开始飘了。

这件事的实操启示

我并不打算用泰勒来预测明天金价。但它告诉我两件事: 第一,"看斜率就押方向"的朴素预测,遇到拐弯就翻车,一周前的趋势不是后一周的剧本。 第二,越靠近今天的信息越值钱,越远越贬值。这正好就是阶乘 n! 替我们做的事,它把远处的不可靠悄悄压低了。


3.怎么定「该买多少」

把"追涨"翻译成一个数学题

光知道涨了 13% 不够用,到底买不买、买多少?直觉的回答是"涨了加仓、跌了减仓"。但这个直觉没法对抗一个事实:你永远不知道明天是涨是跌。

一个更稳的思路是把"买多少"当成一道带约束的优化题:

在「我想赚 X%」的目标下,把波动压到最小。

波动(风险)用什么量?两个资产组合的方差有现成公式:
σp2=w2σg2+(1−w)2σs2+2w(1−w)ρ σgσs \sigma_p^2 = w^2\sigma_g^2 + (1-w)^2\sigma_s^2 + 2w(1-w)\rho\,\sigma_g\sigma_s σp2=w2σg2+(1−w)2σs2+2w(1−w)ρσgσs

我们要做的,是在「收益达到某个目标」的约束下,让 σₚ² 取最小。这正是拉格朗日乘子法登场的地方:给约束乘一个系数 λ,再联立求导,最后写出闭式解。

我用真实黄金数据算了一次。先把每个参数摆清楚

这两类资产我只演示方法,不构成任何投资建议:

  • 黄金:用 7/21 到 8/24 这 25 个交易日折算出年化收益 ≈ 130.4%、年化波动 ≈ 18.4%。注意这是把一个月出头当一年来年化,现实中不会持续,仅作示例。
  • 股票指数:用一组假设参数:年化收益 8%、年化波动 18%、与黄金的相关性 0.1(低相关,避险资产的常见设定)。

蓝色那条弯成"香蕉形"的曲线就是两资产有效前沿,把权重 w 从 0 调到 1,每一个组合在「年化波动 σₚ」和「年化收益 μₚ」平面上都对应一个点,能取到的最优组合连起来就是这条曲线。绿星标的就是最小方差组合点,黄金权重 w* ≈ 0.487,约一半黄金、一半股票。

把这条曲线翻译成大白话:

  • 想要更高的年化收益,就得接受更大的波动,没有"高收益低风险"的免费午餐;
  • 想把波动压到最小,就得到绿星那个组合,约五五开;
  • 黄金和股票相关性低(ρ = 0.1),意味着两个资产的涨跌不太同步,这就是黄金在组合里值钱的原因,它让你能拿到"同样的收益、更低的波动",或"同样的波动、更高的收益"。

拉格朗日乘子法并不是帮你预测金价,而是帮你回答一个更实际的问题:在不知道明天涨不涨的前提下,手里这点钱该按什么比例放进不同资产。它不能让你不亏钱,但能让你的风险结构变得清楚。


总结一下

标题里我问了两个问题:

  • 涨了多少,上个月真实涨幅是 13.22%,但更关键的是怎么算:把每天的对数收益加总,再取指数。这条路叫牛顿-莱布尼茨的离散版本,原理就是把"每天的变化率"攒成"总累计量"。
  • 该买多少,没有万能答案,但怎么想:把"想赚多少"翻译成"在某个收益目标下把波动压到最小",由拉格朗日乘子法给出闭式组合。这条路把"拍脑袋"换成了"算清楚"。

明天还会涨吗,泰勒展开告诉我的是一件更诚实的事:我们手里的信息越远越贬值,阶乘 n! 已经替我们把那种不可靠悄悄压低了,根据我们现有的信息来预测往往是不靠谱的.

金价破千也许是一时的,但它把我们领进的这三门数学,是处理任何时间序列、任何不确定未来的通用工具。

如果大家有更好的计算方法,或者有关于数学知识的新理解,欢迎评论区讨论哦。写文不易,三连支持下作者吧,你是大好人。


方法与可复现

代码:make_gold_figures.py(matplotlib + numpy,受管 venv 跑)。依赖:matplotlibnumpy

python 复制代码
# -*- coding: utf-8 -*-
import csv
from datetime import datetime
import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib import font_manager as fm

# ---------- 字体 ----------
FONT = "Heiti SC"
if not any(f.name == FONT for f in fm.fontManager.ttflist):
    FONT = "PingFang SC"
plt.rcParams["font.family"] = FONT
plt.rcParams["axes.unicode_minus"] = False
plt.rcParams["font.size"] = 12

# ---------- Okabe-Ito 色盲安全配色 ----------
C = {
    "orange": "#E69F00", "sky": "#56B4E9", "green": "#009E73",
    "yellow": "#F0E442", "blue": "#0072B2", "verm": "#D55E00",
    "purple": "#CC79A7", "black": "#000000",
}

BASE = "运行结果存放路径"

def load_daily():
    dates, closes = [], []
    with open(f"数据文件路径1", encoding="utf-8-sig") as f:
        for row in csv.DictReader(f):
            dates.append(datetime.strptime(row["date"], "%Y-%m-%d"))
            closes.append(float(row["close_yuan_per_g"]))
    return np.array(dates), np.array(closes, float)

def load_annual():
    yrs, avgs, notes = [], [], []
    with open(f"数据文件路径2", encoding="utf-8-sig") as f:
        for row in csv.DictReader(f):
            yrs.append(int(row["year"])); avgs.append(float(row["avg_yuan_per_g"]))
            notes.append(row["note"])
    return np.array(yrs), np.array(avgs, float), notes

def style(ax):
    ax.spines["top"].set_visible(False); ax.spines["right"].set_visible(False)
    ax.grid(True, alpha=0.25, lw=0.6)
    ax.tick_params(length=0)

dates, P = load_daily()
yrs, avgs, _ = load_annual()

# =====================================================================
# fig1:金价破千全景(上:长周期年均;下:逐日 7/21--8/24 标出千元线)
# =====================================================================
fig, (a1, a2) = plt.subplots(2, 1, figsize=(8, 7), dpi=150)
fig.subplots_adjust(hspace=0.32, left=0.10, right=0.95, top=0.93, bottom=0.07)

# 上:长周期年均
a1.plot(yrs, avgs, "-o", color=C["verm"], lw=2.4, ms=7, zorder=3)
for x, y in zip(yrs, avgs):
    a1.annotate(f"{y:.0f}", (x, y), textcoords="offset points", xytext=(0, 9),
                ha="center", fontsize=10, color=C["black"])
a1.axhline(1000, color=C["purple"], ls="--", lw=1.4)
a1.annotate("1000 元/克", (yrs[-1], 1000), color=C["purple"], fontsize=9,
             xytext=(-4, -12), textcoords="offset points", ha="right")
a1.set_title("上金所 Au99.99 年均价:四年爬坡,2026 破千", fontsize=13, weight="bold")
a1.set_ylabel("元/克")
a1.set_xticks(yrs)
a1.set_ylim(300, 1120)
style(a1)

# 下:逐日
a2.plot(dates, P, "-o", color=C["blue"], lw=2.2, ms=4, zorder=3, label="Au99.99 收盘")
a2.axhline(1000, color=C["purple"], ls="--", lw=1.4, label="1000 元/克")
i_break = int(np.argmax(P >= 1000))
a2.scatter([dates[i_break]], [P[i_break]], color=C["verm"], s=90, zorder=5)
a2.annotate(f"8/24 收盘 {P[i_break]:.2f}\n国内首次破千", (dates[i_break], P[i_break]),
             xytext=(-10, -42), textcoords="offset points", ha="right", fontsize=9.5,
             color=C["verm"], arrowprops=dict(arrowstyle="-", color=C["verm"], lw=1))
a2.set_title("2026 年 7/21--8/24 逐日收盘:从 887 冲到 1004", fontsize=13, weight="bold")
a2.set_ylabel("元/克"); a2.set_ylim(860, 1030)
a2.tick_params(axis="x", rotation=0)
import matplotlib.dates as mdates
a2.xaxis.set_major_formatter(mdates.DateFormatter("%m/%d"))
a2.legend(frameon=False, loc="lower right")
style(a2)
fig.savefig(f"图片路径1", dpi=300)
print("fig1 done")

# =====================================================================
# fig2:日收益 → 累计(牛顿莱布尼茨离散版 / 对数收益)
# =====================================================================
simp_ret = P[1:] / P[:-1] - 1.0                 # 简单日收益率
log_ret = np.log(P[1:] / P[:-1])               # 对数日收益率
cum_simple = np.cumsum(simp_ret)               # 简单相加(会高估)
cum_log = np.cumsum(log_ret)                   # 对数相加 = 真实累计对数收益
true_cum = P[-1] / P[0] - 1.0                   # 真实累计涨幅
print(f"真实累计涨幅 = {true_cum*100:.2f}%  简单相加={cum_simple[-1]*100:.2f}%  "
      f"对数求和转回={ (np.exp(cum_log[-1])-1)*100:.2f}%")

fig, (b1, b2) = plt.subplots(2, 1, figsize=(8, 7), dpi=150)
fig.subplots_adjust(hspace=0.32, left=0.10, right=0.95, top=0.93, bottom=0.07)
xd = dates[1:]
b1.bar(xd, simp_ret * 100, color=C["sky"], width=0.6, zorder=2)
b1.axhline(0, color=C["black"], lw=0.8)
b1.set_title("每天涨多少?日收益率(变化率的快照)", fontsize=13, weight="bold")
b1.set_ylabel("日收益率 %")
b1.xaxis.set_major_formatter(mdates.DateFormatter("%m/%d"))
style(b1)

b2.plot(xd, cum_simple * 100, "-o", color=C["orange"], lw=2, ms=3,
        label=f"简单日收益相加 = {cum_simple[-1]*100:.2f}%")
b2.plot(xd, (np.exp(np.cumsum(log_ret)) - 1) * 100, "-o", color=C["green"], lw=2.2, ms=3,
        label=f"对数收益求和转回 = {(np.exp(cum_log[-1])-1)*100:.2f}%")
b2.axhline(true_cum * 100, color=C["purple"], ls="--", lw=1.4,
           label=f"真实累计 = {true_cum*100:.2f}%")
b2.set_title("攒起来涨多少?简单相加是近似,对数收益求和才精确", fontsize=13, weight="bold")
b2.set_ylabel("累计涨幅 %"); b2.legend(frameon=False, fontsize=9.5)
b2.xaxis.set_major_formatter(mdates.DateFormatter("%m/%d"))
style(b2)
fig.savefig(f"图片路径2", dpi=300)
print("fig2 done")

# =====================================================================
# fig3:泰勒逐阶逼近(在 8/12 处展开,向左右外推 ±2 天)
# 说明:n 阶项分母有个 n!(0!=1, 1!=1, 2!=2)逐项出现;
#       阶越高、展开点附近贴合越好,远处仍会偏(这是泰勒的本性)。
# =====================================================================
t = np.arange(len(P))
t0 = int(np.where((dates == datetime(2026, 8, 12)))[0][0])
P0 = P[t0]
P1 = (P[t0 + 1] - P[t0 - 1]) / 2.0
P2 = (P[t0 + 1] - 2 * P[t0] + P[t0 - 1])
print(f"t0=8/12  P0={P0:.2f}  P'={P1:.3f}  P''={P2:.3f}")

# h ∈ [-2, +2],5 个点,看清"展开点附近谁更准"
left, right = 2, 2
tt = np.arange(t0 - left, t0 + right + 1)
PP = P[tt]
hh = tt - t0
T0 = np.full_like(hh, P0, float)
T1 = P0 + P1 * hh
T2 = P0 + P1 * hh + P2 * hh**2 / 2.0

fig, ax = plt.subplots(figsize=(8, 5.2), dpi=150)
fig.subplots_adjust(left=0.11, right=0.95, top=0.91, bottom=0.11)
ax.plot(tt, PP, "-o", color=C["black"], lw=2.6, ms=6, zorder=5, label="实际金价")
ax.plot(tt, T0, color=C["orange"], lw=1.8, ls=":", label="0 阶(常数,÷0!)")
ax.plot(tt, T1, color=C["sky"], lw=2.0, ls="--", label="1 阶(线性,÷1!)")
ax.plot(tt, T2, color=C["green"], lw=2.0, ls="-.", label="2 阶(含曲率,÷2!)")
ax.axvline(t0, color=C["verm"], ls=":", lw=1.2)
ax.annotate("展开点 8/12", (t0, P0), color=C["verm"], fontsize=10,
             xytext=(8, 14), textcoords="offset points")
ax.annotate("线性外推走偏", (t0 + 1, T1[left + 1]),
             xytext=(8, 14), textcoords="offset points", fontsize=9, color=C["sky"],
             arrowprops=dict(arrowstyle="-", color=C["sky"], lw=0.8))
ax.annotate("二阶在展开点\n附近贴合", (t0 + 1, T2[left + 1] - 0.5),
             xytext=(8, -42), textcoords="offset points", fontsize=9, color=C["green"],
             arrowprops=dict(arrowstyle="-", color=C["green"], lw=0.8))
ax.set_title("只知道当下金价+斜率,怎样预判明天?泰勒展开逐阶逼近",
             fontsize=12.5, weight="bold")
ax.set_ylabel("元/克")
labels = [dates[int(i)].strftime("%m/%d") for i in tt]
ax.set_xticks(tt); ax.set_xticklabels(labels)
ax.set_ylim(910, 970)
ax.legend(frameon=False, fontsize=9.5, loc="lower center")
style(ax)
fig.savefig(f"图片路径3", dpi=300)
print("fig3 done")

# =====================================================================
# fig4:两资产风险-收益前沿(拉格朗日求最小方差组合)
# =====================================================================
# 黄金:基于 7/21--8/24 窗口的真实测算(年化,仅示例)
mu_g = float(np.mean(log_ret) * 252)
sig_g = float(np.std(log_ret, ddof=1) * np.sqrt(252))
# 股票指数:示例参数(明确标注,非真实推荐)
mu_s, sig_s, rho = 0.08, 0.18, 0.10
print(f"黄金(窗口测算) 年化收益≈{mu_g*100:.1f}%  年化波动≈{sig_g*100:.1f}%")
w = np.linspace(0, 1, 201)
sig_p = np.sqrt(w**2 * sig_g**2 + (1 - w)**2 * sig_s**2 + 2 * w * (1 - w) * rho * sig_g * sig_s)
mu_p = w * mu_g + (1 - w) * mu_s
# 全局最小方差组合(拉格朗日闭式)
w_min = (sig_s**2 - rho * sig_g * sig_s) / (sig_g**2 + sig_s**2 - 2 * rho * sig_g * sig_s)
i_min = int(np.argmin(sig_p))
print(f"最小方差组合 黄金权重 w* = {w_min:.3f}")

fig, ax = plt.subplots(figsize=(8.4, 5.6), dpi=150)
fig.subplots_adjust(left=0.12, right=0.95, top=0.92, bottom=0.11)
ax.plot(sig_p * 100, mu_p * 100, color=C["blue"], lw=2.4, zorder=3, label="两资产有效前沿")
ax.scatter([sig_g * 100], [mu_g * 100], color=C["verm"], s=80, zorder=5)
ax.annotate("黄金", (sig_g * 100, mu_g * 100), xytext=(8, -4),
             textcoords="offset points", fontsize=10, color=C["verm"])
ax.scatter([sig_s * 100], [mu_s * 100], color=C["orange"], s=80, zorder=5)
ax.annotate("股票指数(示例)", (sig_s * 100, mu_s * 100), xytext=(-8, 10),
             textcoords="offset points", fontsize=10, color=C["orange"], ha="right")
ax.scatter([sig_p[i_min] * 100], [mu_p[i_min] * 100], color=C["green"], s=140, zorder=6,
            marker="*")
ax.annotate(f"最小方差组合\n黄金 {w_min*100:.0f}% / 股票 { (1-w_min)*100:.0f}%",
             (sig_p[i_min] * 100, mu_p[i_min] * 100), xytext=(14, -8),
             textcoords="offset points", ha="left", fontsize=9.5, color=C["green"])
ax.set_title("想赚 X%,怎样把波动压到最小?带约束求最优(拉格朗日)", fontsize=12.5, weight="bold")
ax.set_xlabel("年化波动(风险) %"); ax.set_ylabel("年化收益(目标) %")
ax.legend(frameon=False, loc="lower center", fontsize=9.5, bbox_to_anchor=(0.5, 0.02))
style(ax)
fig.savefig(f"图片路径4", dpi=300)
print("fig3 done" if False else "fig4 done")
print("ALL FIGURES SAVED")
相关推荐
2401_8652616342 分钟前
亦唐科技:推动国产贴片机技术突破,打造智能制造新标杆
人工智能
智能运维指南42 分钟前
Confluence 停服、数据出境、知识散落:企业知识管理系统如何破局?
大数据·人工智能·microsoft
张人玉44 分钟前
茶树 NeRF(Neural Radiance Fields,神经辐射场)三维重建与数据分析可视化系统——基于神经辐射场的茶树三维重建方法实现可视化大屏
python·数据挖掘·数据分析·echarts·three.js
x861 小时前
Operit 深度拆解:手机里的开源 AI 操作系统
人工智能·智能手机·开源
钉钉开发者社区1 小时前
来钉钉,接入 DeepSeek Harness
人工智能·ai·钉钉·钉钉cli
脉动数据行情11 小时前
Python WebSocket 国内商品期货|螺纹钢 & 铁矿石实时行情监听
开发语言·python·websocket
龙虾PRO1 小时前
大模型时代二进制漏洞攻防体系重构:从 AFL 模糊测试到 AI 智能体的全链路落地路径
人工智能·重构
围炉聊科技1 小时前
OpenAdapt:录制一次,确定性回放
人工智能·后端·架构
武汉星际互动1 小时前
边聊边办深度测评:从咨询到办结一站办成
人工智能·政务