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

Scipy.optimize minimize函数行为异常求助排查

Fixing Abnormal Results from Scipy's minimize in Portfolio Optimization

Problem Breakdown

You’ve hit a tricky issue with your portfolio optimization code: Scipy’s optimize.minimize starts off okay but later returns invalid results, and you noticed the weights and returns parameters are getting swapped in the portfolio_stats function. Let’s walk through why this happens and how to fix it.

Root Cause

The problem boils down to a parameter order mismatch in your min_func_sharpe function. Here’s the breakdown:

  • Your portfolio_stats function expects parameters in the order: (returns, weights, rf)
  • But in the original code, you called it as portfolio_stats(weights, args[0], args[1]) — this swaps weights and returns (since args[0] is your returns data).

This swap doesn’t crash the code immediately (since both are arrays), but it completely invalidates the portfolio statistics calculations as the optimization iterates, leading to the abnormal results you saw.

The Fix

Correct the parameter order in min_func_sharpe to match what portfolio_stats expects:

def min_func_sharpe(weights,*args):
    return -portfolio_stats(args[0], weights, args[1])[2]

Now args[0] (your returns data) is passed first, followed by weights, then args[1] (the risk-free rate), aligning with the portfolio_stats signature.

Full Corrected Code

from math import exp
import numpy as np
import pandas_datareader.data as web
import matplotlib.pyplot as plt
import scipy.optimize as optimization

# 从Yahoo获取数据
def stock_data(stocks,start_date,end_date):
    start_date= start_date
    end_date= end_date
    data=web.DataReader(stocks,data_source='yahoo',start=start_date,end=end_date)['Adj Close']
    return data

# 计算日对数收益率(区别于算术收益率)
def stock_returns(data):
    daily_returns=(data/data.shift(1))
    daily_returns=np.log(daily_returns)
    return daily_returns

# 获取股票统计数据(基于对数收益率的年度近似值)
def stock_stats(returns):
    expected=returns.mean()*252
    variance=returns.var()*252
    covariance=returns.cov()*252
    return [expected,variance,covariance]

# 获取投资组合统计数据(基于对数收益率的年度近似值)
def portfolio_stats(returns,weights,rf):
    expected=np.sum(returns.mean()*weights)*252
    variance =np.dot(weights.T,np.dot(returns.cov()*252,weights))
    sd=np.sqrt(variance)
    sharpe=(expected-rf)/sd
    return [expected,sd,sharpe]

# 运行投资组合蒙特卡洛模拟
def monte_carlo_porfolios(stocks,returns,simulations,rf):
    mc_expected=[]
    mc_sd=[]
    optimum=[]
    sharpe=0
    for i in range(simulations):
        weights=np.random.random(len(stocks))
        weights /= np.sum(weights)
        stats =portfolio_stats(returns,weights,rf)
        expected =stats[0]
        sd =stats[1]
        mc_expected.append(expected)
        mc_sd.append(sd)
        if (expected-rf)/sd>sharpe:
            optimum=weights
            sharpe=(expected-rf)/sd
    mc_expected=np.array(mc_expected)
    mc_sd=np.array(mc_sd)
    return [mc_expected,mc_sd,np.array(optimum)]

# 定义待最小化函数(已修正参数顺序)
def min_func_sharpe(weights,*args):
    return -portfolio_stats(args[0], weights, args[1])[2]

# 通过优化算法寻找最优组合
def optimize_portfolio(initial,returns,rf):
    constraints = ({'type':'eq','fun':lambda x:np.sum(x)-1})
    bounds = tuple((0,1) for x in range(len(stocks)))
    optimum = optimization.minimize(fun=min_func_sharpe,x0=initial,args=(returns,rf),method='SLSQP',bounds=bounds,constraints=constraints)
    return optimum

stocks = ['AAPL','WMT','TSLA','GE','AMZN','DB']
start_date ='01/01/2010'
end_date ='01/01/2020'
rf=0.02
data = stock_data(stocks,start_date,end_date)
log_returns = stock_returns(data)
monte_carlo = monte_carlo_porfolios(stocks,log_returns,1000,rf)
print(optimize_portfolio(monte_carlo[2],log_returns,rf))

Quick Tip

When working with optimization functions (where inputs are passed indirectly via *args), always cross-verify parameter orders between the objective function and the helper functions it calls. Subtle mismatches like this are easy to miss but can completely derail your calculations.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:44:31