sql中没有标准var()函数,应使用var_samp()计算样本方差以评估投资组合风险。postgresql、mysql支持var_samp()/var_pop(),sql server的var()仅限单列样本方差,sqlite不支持。

SQL里没有VAR()函数,别被名字骗了
SQL标准中根本不存在名为 VAR() 的聚合函数——这是常见误解的源头。PostgreSQL 有 var_pop() 和 var_samp(),SQL Server 用 VAR()(但仅限于 *单列样本方差*,且不支持窗口用法),MySQL 直到 8.0.22 才加入 VAR_POP() 和 VAR_SAMP(),而 SQLite 完全不提供方差函数。直接写 SELECT VAR(returns) FROM portfolio_data 在多数环境会报错:ERROR: function var(numeric) does not exist 或类似提示。
用 VAR_SAMP 或 VAR_POP 算投资收益方差时,选哪个?
投资组合风险评估通常基于历史样本(比如过去252个交易日的日收益率),属于「从总体中抽样」,应使用样本方差(Bessel校正),即 VAR_SAMP()。它除以 n−1,比 VAR_POP()(除以 n)更无偏、更常用。
-
VAR_SAMP(x)→ 推荐用于日/月收益率序列,尤其当样本量 numpy.var(x, ddof=1) 对齐时 -
VAR_POP(x)→ 仅当你确信手头数据就是全部总体(例如已穷尽某基金自成立至今所有日收益),且模型明确要求总体方差 - 注意:SQL Server 的
VAR()等价于VAR_SAMP();它的VARP()才对应VAR_POP()
计算组合方差前必须先算对收益率,不是简单用价格差
直接对原始价格列(如 price)调用 VAR_SAMP() 毫无金融意义——方差必须作用于**收益率**(return),且是**对数收益率**或**简单收益率**,取决于建模假设。
- 简单收益率:
(price - LAG(price) OVER (ORDER BY date)) / LAG(price) OVER (ORDER BY date) - 对数收益率(更常用,具可加性):
LN(price / LAG(price) OVER (ORDER BY date)) - 千万别在没生成收益率列的情况下直接对
price跑VAR_SAMP()——结果单位是「价格²」,无法解释为风险 - 若数据含多资产,需先按权重加权合成组合日收益,再对方差函数输入该合成序列,不能对各资产方差简单平均
实际执行时容易卡在 NULL 和分组逻辑上
真实市场数据常有停牌、缺失日期或异常值,VAR_SAMP() 遇到 NULL 会自动跳过,但若整列都是 NULL(比如没成功算出收益率),会返回 NULL 而非报错,极易被忽略。
- 务必检查收益率列是否为空:
SELECT COUNT(*) FILTER (WHERE daily_return IS NOT NULL) FROM returns_calc - 跨资产组合场景下,必须用子查询或 CTE 先聚合出每日组合收益,再对外层结果集调用
VAR_SAMP(),不能在未分组的明细表上直接算 - Oracle 用户注意:
VAR_SAMP()在空集上返回NULL,但某些旧版本对GROUP BY空结果可能报错,建议加HAVING COUNT(*) > 1防御
方差只是起点,真正的风险模型还得叠加协方差矩阵、夏普比率或VaR——但第一步,得让那个数字算出来,而且算对。











