You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中求解含标准差的股票价格不等式?

问题描述

我把过去19天的股票价格存在pd.DataFrame里,想找到满足 P < mean - 2.5*standard deviation 的价格P——这里的均值和标准差是包含P在内的20个数据(过去19天+P)的统计量。尝试用SymPy的solve函数求解时,调用np.std()报错,示例代码和错误信息如下:

from sympy.solvers import solve
from sympy import Symbol
x = Symbol('x')
solve(x-np.mean([1,2,3,x])-np.std([1,2,3,x]), x)

错误信息:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
AttributeError: 'Add' object has no attribute 'sqrt'

The above exception was the direct cause of the following exception:

TypeError                                 Traceback (most recent call last)
Input In [71], in <cell line: 4>()
      2 from sympy import Symbol
      3 x = Symbol('x')
----> 4 solve(x-np.mean([1,2,3,x])-np.std([1,2,3,x]), x)

File ~/opt/anaconda3/lib/python3.9/site-packages/numpy/core/fromnumeric.py:3645, in std(a, axis, dtype, out, ddof, keepdims, where)
   3642     else:
   3643         return std(axis=axis, dtype=dtype, out=out, ddof=ddof, **kwargs)
-> 3645 return _methods._std(a, axis=axis, dtype=dtype, out=out, ddof=ddof,
   3646                      **kwargs)

File ~/opt/anaconda3/lib/python3.9/site-packages/numpy/core/_methods.py:214, in _std(a, axis, dtype, out, ddof, keepdims, where)
    212     ret = ret.dtype.type(um.sqrt(ret))
    213 else:
--> 214     ret = um.sqrt(ret)
    216 return ret

TypeError: loop of ufunc does not support argument 0 of type Add which has no callable sqrt method
解决方法

报错核心原因是numpy的数值计算函数(np.mean、np.std)无法处理SymPy的符号变量,两者定位不同:numpy负责数值运算,SymPy负责符号运算,不能直接混用。下面提供两种可行方案:

方案1:用SymPy原生统计函数替换numpy函数

SymPy自带符号化的均值、标准差计算函数,直接替换numpy的对应函数即可正常求解:

from sympy.solvers import solve
from sympy import Symbol, mean, std
x = Symbol('x')
# 注意sympy的std默认用样本标准差(ddof=1),如果需要总体标准差可以加参数ddof=0
solve(x - mean([1,2,3,x]) - 2.5*std([1,2,3,x]), x)

方案2:代数推导后直接数值计算(更高效)

无需依赖符号计算工具,手动推导不等式的代数形式后直接计算,适合批量处理数据:

假设过去19天价格的总和为S,平方和为SS,加入P后共20个数据:

  • 均值 μ = (S + P)/20
  • 标准差 σ = sqrt( (SS + P²)/20 - μ² )

将上述式子代入原不等式 P < μ - 2.5σ,整理后可得到关于P的一元二次不等式,直接求解根即可确定P的范围:

import pandas as pd
import numpy as np

# 假设你的DataFrame是df,价格列名为'price'
past_prices = df['price'].tail(19).values
S = past_prices.sum()
SS = (past_prices ** 2).sum()
n = 20  # 19天+P的总数据量
k = 2.5  # 你的标准差倍数

# 整理后的二次不等式系数:a*P² + b*P + c < 0
a = n - k**2
b = -2*S + 2*(k**2)*S / n
c = (S**2)/n - (k**2)*(SS - (S**2)/n)

# 求解二次方程的根
roots = np.roots([a, b, c])
roots.sort()

# 根据二次函数开口方向确定解的区间
if a > 0:
    # 开口向上,不等式的解为两根之间
    valid_P_range = (roots[0], roots[1])
else:
    # 开口向下,解为两根之外
    valid_P_range = (-np.inf, roots[0]), (roots[1], np.inf)

print(f"满足条件的P范围:{valid_P_range[0]:.4f} < P < {valid_P_range[1]:.4f}")

内容的提问来源于stack exchange,提问作者Roy Chang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 03:12:42