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

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())

一、依赖库缺失问题排查与修复

  1. 问题本质:报错显示liblapack.3.dylib缺失,该库是CoinUtils(Pulp默认CBC求解器的依赖)的底层线性代数库。
  2. 精准排查与修复步骤:
    • 检查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
  3. 替代方案:若lapack安装仍有问题,切换Pulp求解器为GLPK,安装命令conda install -c conda-forge glpk,代码中指定求解器:model.solve(pulp.GLPK(msg=True))

二、买卖优化模型代码结构最佳实践

  1. 模块化拆分:将数据获取、模型构建、求解、结果分析拆分为独立函数,便于维护和调试。
  2. 参数配置中心化:把股票代码、时间范围、初始资金、求解器类型等参数放在代码开头统一配置,便于修改。
  3. 约束逻辑修正:
    • 原代码中Buy[t] <= SOC[t]存在逻辑错误,应为Buy[t] <= SOC[t-1](用前一日持仓资金买当日股票)
    • SOC[t]更新公式需修正为现金与股票的状态转移逻辑,避免错误的除法运算。
  4. 调试增强:在model.solve()中添加msg=True参数,查看求解器详细输出,排查模型不可行原因。
  5. 结果可视化:添加代码将买卖决策与股价曲线结合展示,直观验证策略有效性。
  6. 异常处理优化:捕获求解器返回的非最优状态(如不可行、无界),给出针对性提示。

优化后代码示例

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 11:24:56