Pulp优化调试求助:依赖库缺失报错及代码结构咨询
问题描述
首次使用Pulp工具,基于AAL.L股票价格构建买卖时机优化模型,运行时出现依赖库缺失报错,无法定位原因,不知道如何精准排查,同时想了解这类优化代码的结构最佳实践。
报错信息
An error occurred during optimization: dyld[657]: Library not loaded: '@rpath/liblapack.3.dylib' Referenced from: '/Users/pepeslier/anaconda3/lib/libCoinUtils.3.11.6.dylib' Reason: tried: '/Users/XXX/anaconda3/lib/liblapack.3.dylib' (no such file), '/Users/XXX/anaconda3/lib/liblapack.3.dylib' (no such file), '/Users/XXX/anaconda3/lib/liblapack.3.dylib' (no such file), '/Users/XXX/anaconda3/bin/../lib/liblapack.3.dylib' (no such file), '/Users/XXX/anaconda3/bin/../lib/liblapack.3.dylib' (no such file), '/usr/local/lib/liblapack.3.dylib' (no such file), '/usr/lib/liblapack.3.dylib' (no such file) Traceback (most recent call last): File "/Users/XXX/.spyder-py3/temp.py", line 37, in <module> model.solve() File "/Users/XXX/anaconda3/lib/python3.11/site-packages/pulp/pulp.py", line 1913, in solve status = solver.actualSolve(self, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/XXX/anaconda3/lib/python3.11/site-packages/pulp/apis/coin_api.py", line 137, in actualSolve return self.solve_CBC(lp, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/XXX/anaconda3/lib/python3.11/site-packages/pulp/apis/coin_api.py", line 206, in solve_CBC raise PulpSolverError( pulp.apis.core.PulpSolverError: Pulp: Error while trying to execute, use msg=True for more detailscbc
完整代码
import pulp import pandas as pd import datetime as dt import yfinance as yf import traceback df = yf.download(tickers='AAL.L', start='2018-01-01',end='2018-02-01') try: # Create a PuLP problem model = pulp.LpProblem("Profits", pulp.LpMaximize) #Define parameters T = len(df['Close']) price = df['Close'].values # Define decision variables Buy = {t: pulp.LpVariable(f"Buy_{t}" , lowBound=0) for t in range(T)} Sell = {t: pulp.LpVariable(f"Sell_{t}", lowBound=0) for t in range(T)} SOC = {t: pulp.LpVariable(f"SOC_{t}" , lowBound=0) for t in range(T)} # Define constraints model += SOC[0] == 10 model += Buy[0] <= SOC[0] model += Sell[0] == 0 for t in range(1,T): model += SOC[t] == SOC[t-1] - Buy[t]/price[t] + Sell[t]*price[t] model += Buy[t] <= SOC[t] model += Sell[t] <= SOC[t] # Define the objective function model += pulp.lpSum( Sell[t] * price[t] - Buy[t] * price[t] for t in range(T) ) model.solve() # Check if the solution is optimal if pulp.LpStatus[model.status] == "Optimal": # Print the variable values and other results for var in model.variables(): print(f"{var.name}: {var.varValue}") print("Objective value:", pulp.value(model.objective)) else: print("Optimal solution not found.") except pulp.PulpSolverError: print("An error occurred during optimization:") print(traceback.format_exc()) except Exception: print("An unexpected error occurred:") print(traceback.format_exc())
一、依赖库缺失问题排查与修复
- 问题本质:报错显示
liblapack.3.dylib缺失,该库是CoinUtils(Pulp默认CBC求解器的依赖)的底层线性代数库。 - 精准排查与修复步骤:
- 检查conda环境中是否安装lapack:运行
conda list | grep lapack - 若未安装,执行
conda install -c conda-forge lapack - 若已安装但版本不匹配,卸载后重装指定版本:
conda remove lapack && conda install -c conda-forge lapack=3.* - 验证库路径:运行
find /Users/XXX/anaconda3 -name "liblapack*.dylib",确认是否存在liblapack.3.dylib;若存在但路径不对,创建软链接:ln -s /path/to/liblapack.3.dylib /Users/XXX/anaconda3/lib/liblapack.3.dylib
- 检查conda环境中是否安装lapack:运行
- 替代方案:若lapack安装仍有问题,切换Pulp求解器为GLPK,安装命令
conda install -c conda-forge glpk,代码中指定求解器:model.solve(pulp.GLPK(msg=True))
二、买卖优化模型代码结构最佳实践
- 模块化拆分:将数据获取、模型构建、求解、结果分析拆分为独立函数,便于维护和调试。
- 参数配置中心化:把股票代码、时间范围、初始资金、求解器类型等参数放在代码开头统一配置,便于修改。
- 约束逻辑修正:
- 原代码中
Buy[t] <= SOC[t]存在逻辑错误,应为Buy[t] <= SOC[t-1](用前一日持仓资金买当日股票) SOC[t]更新公式需修正为现金与股票的状态转移逻辑,避免错误的除法运算。
- 原代码中
- 调试增强:在
model.solve()中添加msg=True参数,查看求解器详细输出,排查模型不可行原因。 - 结果可视化:添加代码将买卖决策与股价曲线结合展示,直观验证策略有效性。
- 异常处理优化:捕获求解器返回的非最优状态(如不可行、无界),给出针对性提示。
优化后代码示例
import pulp import pandas as pd import yfinance as yf import matplotlib.pyplot as plt # 中心化参数配置 TICKER = 'AAL.L' START_DATE = '2018-01-01' END_DATE = '2018-02-01' INITIAL_CASH = 10 SOLVER = pulp.GLPK(msg=True) def fetch_stock_data(ticker, start, end): """获取股票收盘价数据""" df = yf.download(tickers=ticker, start=start, end=end) return df['Close'].dropna() def build_trading_model(prices, initial_cash): """构建买卖时机优化模型""" T = len(prices) model = pulp.LpProblem("MaximizeTradingProfit", pulp.LpMaximize) # 决策变量:Buy[t]为t日买入股票花费的现金,Sell[t]为t日卖出的股票数量 Buy = pulp.LpVariable.dicts("Buy", range(T), lowBound=0) Sell = pulp.LpVariable.dicts("Sell", range(T), lowBound=0) # 状态变量:Cash[t]为t日结束时的现金,Stock[t]为t日结束时的股票持仓量 Cash = pulp.LpVariable.dicts("Cash", range(T), lowBound=0) Stock = pulp.LpVariable.dicts("Stock", range(T), lowBound=0) # 初始状态约束 model += Cash[0] == initial_cash - Buy[0] model += Stock[0] == Buy[0] / prices.iloc[0] model += Sell[0] == 0 # 首日无持仓,禁止卖出 # 每日状态转移约束 for t in range(1, T): # 现金更新:前一日现金 - 当日买股花费 + 当日卖股收入 model += Cash[t] == Cash[t-1] - Buy[t] + Sell[t] * prices.iloc[t] # 股票更新:前一日股票 - 当日卖出数量 + 当日买入数量 model += Stock[t] == Stock[t-1] - Sell[t] + Buy[t] / prices.iloc[t] # 卖出数量不能超过前一日持仓 model += Sell[t] <= Stock[t-1] # 目标函数:期末总价值最大化(现金+股票市值) model += Cash[T-1] + Stock[T-1] * prices.iloc[-1] return model, Buy, Sell, Cash, Stock def analyze_results(model, Buy, Sell, prices): """分析求解结果并可视化""" status = pulp.LpStatus[model.status] if status != "Optimal": print(f"求解状态:{status},未找到最优解") return # 提取决策变量值 buy_values = [pulp.value(Buy[t]) for t in range(len(prices))] sell_values = [pulp.value(Sell[t]) for t in range(len(prices))] # 打印关键结果 print(f"最优期末总价值:{round(pulp.value(model.objective), 2)}") print("每日买入金额:", [round(v, 2) for v in buy_values]) print("每日卖出股票数量:", [round(v, 2) for v in sell_values]) # 可视化买卖点与股价 plt.figure(figsize=(12,6)) plt.plot(prices.index, prices.values, label='股价', color='blue') # 标记买入点 buy_dates = prices.index[[v > 0.01 for v in buy_values]] plt.scatter(buy_dates, prices.loc[buy_dates], marker='^', color='green', label='买入') # 标记卖出点 sell_dates = prices.index[[v > 0.01 for v in sell_values]] plt.scatter(sell_dates, prices.loc[sell_dates], marker='v', color='red', label='卖出') plt.title('AAL.L 买卖时机优化结果') plt.xlabel('日期') plt.ylabel('股价') plt.legend() plt.show() if __name__ == "__main__": try: prices = fetch_stock_data(TICKER, START_DATE, END_DATE) model, Buy, Sell, Cash, Stock = build_trading_model(prices, INITIAL_CASH) model.solve(SOLVER) analyze_results(model, Buy, Sell, prices) except Exception as e: print(f"运行出错:{str(e)}") import traceback traceback.print_exc()
内容的提问来源于stack exchange,提问作者Peslier53
相关产品推荐
相关产品推荐

