【问题标题】:Optimization function yields wrong results优化函数产生错误的结果
【发布时间】:2022-01-21 05:06:42
【问题描述】:

我试图从 yuxing Yan 的 python 中复制某些代码用于金融。 我遇到了障碍,因为我得到了非常高的最小化数字(在这种情况下,股票权重,在使用 fmin() 优化后可能是 +(long) 和 (-short)。

谁能帮我换一双新眼睛。我已经看到一些关于避免将负数或复杂数字传递给 fmin() 的建议,但我无法承受它对我的代码至关重要

#让我们导入我们的模块

from scipy.optimize import fmin #to minimise our negative sharpe-ratio
import numpy as np#deals with numbers python
from datetime import datetime#handles date objects
import pandas_datareader.data as pdr #to read download equity data
import pandas as pd #for reading and accessing tables etc
import scipy as sp
from scipy.stats import norm
import scipy.stats as stats
from scipy.optimize import fminbound



assets=('AAPL',
'IBM',
'GOOG',
'BP',
'XOM',
'COST',
'GS')

#start and enddate to be downloaded
startdate='2016-01-01'
enddate='2016-01-31'
rf_rate=0.0003

n=len(assets)

#_______________________________________________
#This functions takes the assets,start and end dates and 
#returns portfolio return
#__________________________________________________
def port_returns (assets,startdate,enddate): 
                    
    #We use adjusted clsoing prices of sepcified dates of assets
     #as we will only be interested in returns
    data = pdr.get_data_yahoo(assets, start=startdate, end=enddate)['Adj Close']
    
    
    #We calculate the percentage change of our returns
    #using pct_change function in python
    returns=data.pct_change()
    return  returns
def portfolio_variance(returns,weight):
       #finding the correlation of our returns by 
        #dropping the nan values and transposing 
       correlation_coefficient = np.corrcoef(returns.dropna().T)
       
       #standard deviation of our returns
       std=np.std(returns,axis=0)
       
       #initialising our variance
       port_var = 0.0
    
       #creating a nested loop to calculate our portfolio variance
       #where the variance is w12σ12 + w22σ22 + 2w1w2(Cov1,2) 
       #and correlation coefficient is given by covaraince btn two assets  divided by standard
       #multiplication of standard deviation of both assets
       for i in range(n):
           for j in range(n):
            #we calculate the variance by continuously summing up the varaince between two
            #assets using i as base loop, multiplying by std and corrcoef
               port_var += weight[i]*weight[j]*std[i]*std[j]*correlation_coefficient[i, j]

       return port_var

def sharpe_ratio(returns,weights):
    #call our variance function
       variance=portfolio_variance(returns,weights)
       avg_return=np.mean(returns,axis=0)
        #turn our returns to an array
       returns_array = np.array(avg_return)
        #Our sharpe ratio uses  expected return gotten from multiplying weights and return
        # and standard deviation gotten by square rooting our variance
        #https://en.wikipedia.org/wiki/Sharpe_ratio
       return (np.dot(weights,returns_array) - rf_rate)/np.sqrt(variance)

def negate_sharpe_ratio(weights):
       #returns=port_returns (assets,startdate,enddate)
    #creating an array with our weights by
    #summing our n-1 inserted and subtracting by 1 to make our last weight
       weights_new=np.append(weights,1-sum(weights))
    #returning a negative sharpe ratio
       return -(sharpe_ratio(returns_data,weights_new))
      
returns_data=port_returns(assets,startdate,enddate)

# for n stocks, we could only choose n-1 weights
ones_weights_array= (np.ones(n-1, dtype=float) * 1.0 )/n
weight_1 = fmin(negate_sharpe_ratio,ones_weights_array)
final_weight = np.append(weight_1, 1 - sum(weight_1))
final_sharpe_ratio = sharpe_ratio(returns_data,final_weight)
print ('Optimal weights are ')
print (final_weight)
print ('final Sharpe ratio is ')
print(final_sharpe_ratio)

【问题讨论】:

  • 您需要正确格式化您的代码,以便我们可以更轻松地阅读,但尤其是因为 Python 代码对缩进很敏感。
  • 代码格式化。谢谢

标签: python optimization scipy-optimize quantitative-finance


【解决方案1】:

有几件事导致您的代码无法正常工作

assetsticker 中的项目列表吗?

是否应该将startdate 设置为等于begdate

您对port_returns() 的调用正在寻找从未定义的assetsstartdate

函数sharpe_ratio() 正在寻找一个从未定义过的名为rf_rate 的变量。我假设这是无风险利率和在脚本开头分配给rf 的值。那么rf 应该改成rf_rate 吗?

在将rf 更改为rf_rate,将begdate 更改为startdate,并设置assets = list(ticker) 后,看来这将按所写的那样工作

【讨论】:

  • 感谢您的回复。代码确实可以运行,但优化后我得到了非常奇怪的数字。理想情况下,它应该是小数点后几位,但我得到的数字是数千。我将代码编辑为好吧,如果你想再看一看。
  • 当我运行它时,我得到了有意义的重量。都在零和一之间。最佳权重为 [0.39138638 0.54119293 0.0674207 ] 您确定您使用的代码与您在问题中粘贴的代码完全相同吗?例如,不同的 rf_rate 值会使复制您的问题变得困难
  • 是的,我也确实得到了这些数字,但它们与书中的内容相去甚远。我想知道可能是什么问题。无论如何,我已经编辑了资产并且只制作了2016 年 1 月,以演示我之前描述的问题。如果您能进一步扩展为什么我会获得这些大的权重值,我会很高兴
  • 我明白了。编码方法的一个问题是 fmin 没有执行约束优化。它只是在寻找函数的最小值。对于某些输入集,您可能会遇到无限问题,这就是您看到巨大权重的原因。如果您在调用 fmin 时设置“full_output=True”,您应该能够验证这一点(它现在将返回 5 个值)。 docs.scipy.org/doc/scipy/reference/generated/….
  • “warnflag”的返回值将告诉您是否已达到最大函数评估/迭代。如果您看到它以及不合理的权重,则意味着程序在迭代限制后退出。您可能想尝试允许约束的 fmin 变体 (fmin_cobyla),或尝试另一个允许您设置约束优化并重新制定方法的包。例如,权重之和等于 1 应该是一个约束。您使用的这本书可能精选了一个有效的示例
猜你喜欢
  • 1970-01-01
  • 2020-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多