如何使用Sympy Solve为时间序列求解未知变量X?
使用SymPy Solve处理时间序列逐行求解问题
一、简化场景示例
假设我们有时间序列格式的DataFrame,需要对每行数据求解方程:(1+df['LTEPSG']) * df['TTMEPS'] - X = 0,核心目标是为每行计算对应的X值,得到随时间变化的结果序列。
这类方程求解逻辑直接,X的解可简化为(1+LTEPSG)*TTMEPS,用SymPy处理时,可先定义符号变量,再通过符号求解得到表达式,最后逐行代入数值计算结果。
二、实际复杂方程求解需求
我们需要针对时间序列的每一行,求解以下方程中的X:df['SPX'] - (A+B+C+D+E) = 0
其中各变量定义为:
A = df['DIV1'] / (1 + df['US30'] + X)**1 B = df['DIV2'] / (1 + df['US30'] + X)**2 C = df['DIV3'] / (1 + df['US30'] + X)**3 D = df['DIV4'] / (1 + df['US30'] + X)**4 E = (df['DIV5'] + (df['DIVT']/X)) / (1 + df['US30'] + X)**5
对应时间序列数据集
| Dates | SPX | US30 | DIV1 | DIV2 | DIV3 | DIV4 | DIV5 | DIVT |
|---|---|---|---|---|---|---|---|---|
| 2022-09-01 | 3966.85 | 0.0337 | 74.695960 | 84.730615 | 96.113326 | 109.025190 | 123.671634 | 123.713312 |
| 2022-10-01 | 3678.43 | 0.0373 | 74.978836 | 84.906784 | 96.149292 | 108.880419 | 123.297276 | 123.343265 |
| 2022-11-01 | 3856.10 | 0.0414 | 73.660144 | 82.285010 | 91.919762 | 102.682647 | 114.705758 | 114.753246 |
| 2022-12-01 | 4076.57 | 0.0364 | 74.472697 | 82.454680 | 91.292173 | 101.076868 | 111.910287 | 111.951022 |
| 2023-01-01 | 3839.50 | 0.0397 | 73.966816 | 81.425629 | 89.636590 | 98.675544 | 108.625985 | 108.669110 |
三、解决方案代码
步骤说明
- 导入
pandas处理时间序列,sympy进行符号求解; - 定义符号变量X,并添加正实数约束(符合金融场景下的实际意义);
- 构建方程模板,将每行数据代入生成具体方程;
- 逐行调用数值求解函数得到X的解,保存到DataFrame中。
完整代码
import pandas as pd import sympy as sp # 1. 构建数据集 data = { 'Dates': ['2022-09-01', '2022-10-01', '2022-11-01', '2022-12-01', '2023-01-01'], 'SPX': [3966.85, 3678.43, 3856.10, 4076.57, 3839.50], 'US30': [0.0337, 0.0373, 0.0414, 0.0364, 0.0397], 'DIV1': [74.695960, 74.978836, 73.660144, 74.472697, 73.966816], 'DIV2': [84.730615, 84.906784, 82.285010, 82.454680, 81.425629], 'DIV3': [96.113326, 96.149292, 91.919762, 91.292173, 89.636590], 'DIV4': [109.025190, 108.880419, 102.682647, 101.076868, 98.675544], 'DIV5': [123.671634, 123.297276, 114.705758, 111.910287, 108.625985], 'DIVT': [123.713312, 123.343265, 114.753246, 111.951022, 108.669110] } df = pd.DataFrame(data) df['Dates'] = pd.to_datetime(df['Dates']) # 2. 定义符号变量,限定为正实数 X = sp.symbols('X', real=True, positive=True) # 3. 构建每行对应的方程 def build_equation(row): discount_rate = row['US30'] + X A = row['DIV1'] / (1 + discount_rate)**1 B = row['DIV2'] / (1 + discount_rate)**2 C = row['DIV3'] / (1 + discount_rate)**3 D = row['DIV4'] / (1 + discount_rate)**4 E = (row['DIV5'] + (row['DIVT'] / X)) / (1 + discount_rate)**5 return sp.Eq(row['SPX'], A + B + C + D + E) # 4. 逐行求解,初始值设为0.05(常见收益率范围) df['X_solution'] = df.apply(lambda row: sp.nsolve(build_equation(row), X, 0.05), axis=1) # 输出结果 print(df[['Dates', 'SPX', 'X_solution']])
关键说明
- 定义X时添加
real=True, positive=True约束,避免求解出无意义的复数或负根; - 使用
sp.nsolve进行数值求解,针对非线性方程效率更高,初始值设为0.05可提升求解的稳定性; - 通过
df.apply实现逐行处理,将每行数据代入方程得到对应X的解。
内容的提问来源于stack exchange,提问作者user20856754
相关产品推荐
相关产品推荐

