首页 > 解决方案 > 从函数+循环制作列表

问题描述

这是整个代码:我想创建一个循环,每次从输入文件中跳过一行。

导入 pandas 作为 pd
导入 numpy 作为 np 导入 matplotlib.pyplot 作为 plt 导入 seaborn 作为 sns 导入 quandl 导入 scipy.optimize 作为 sco from pandas.plotting 导入 register_matplotlib_converters register_matplotlib_converters()

mylist=[]

for i in range(0,4):
    table = pd.read_excel(r"Priser.xlsx",skiprows=i,usecols="b,c,d,e,f,g,h,i,j,k,l,m,n,o,p")
    table1 = np.array(table.values)

    returns = np.log(table) - np.log(table.shift(1))
    mean_returns = returns.mean()
    cov_matrix = returns.cov()
    num_portfolios = 1
    risk_free_rate = 0.0178

    def portfolio_annualised_performance(weights, mean_returns, cov_matrix):
        returns = np.sum(mean_returns*weights ) *252
        std = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights))) * np.sqrt(252)
        return std, returns

    def random_portfolios(num_portfolios, mean_returns, cov_matrix, risk_free_rate):
        results = np.zeros((3,num_portfolios))
        weights_record = []
        for i in range(num_portfolios):
            weights = np.random.random(15)
            weights /= np.sum(weights)
            weights_record.append(weights)
            portfolio_std_dev, portfolio_return = portfolio_annualised_performance(weights, mean_returns, cov_matrix)
            results[0,i] = portfolio_std_dev
            results[1,i] = portfolio_return
            results[2,i] = (portfolio_return - risk_free_rate) / portfolio_std_dev
        return results, weights_record


    def neg_sharpe_ratio(weights, mean_returns, cov_matrix, risk_free_rate):
        p_var, p_ret = portfolio_annualised_performance(weights, mean_returns, cov_matrix)
        return -(p_ret - risk_free_rate) / p_var

    def max_sharpe_ratio(mean_returns, cov_matrix, risk_free_rate):
        num_assets = len(mean_returns)
        args = (mean_returns, cov_matrix, risk_free_rate)
        constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
        bound = (0.0,1.0)
        bounds = tuple(bound for asset in range(num_assets))
        result = sco.minimize(neg_sharpe_ratio, num_assets*[1./num_assets,], args=args,
                            method='SLSQP', bounds=bounds, constraints=constraints)
        return result

    def portfolio_volatility(weights, mean_returns, cov_matrix):
        return portfolio_annualised_performance(weights, mean_returns, cov_matrix)[0]

    def min_variance(mean_returns, cov_matrix):
        num_assets = len(mean_returns)
        args = (mean_returns, cov_matrix)
        constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
        bound = (0.0,0.15)
        bounds = tuple(bound for asset in range(num_assets))

        result = sco.minimize(portfolio_volatility, num_assets*[1./num_assets,], args=args,
                            method='SLSQP', bounds=bounds, constraints=constraints)

        return result

    def efficient_return(mean_returns, cov_matrix, target):
        num_assets = len(mean_returns)
        args = (mean_returns, cov_matrix)

        def portfolio_return(weights):
            return portfolio_annualised_performance(weights, mean_returns, cov_matrix)[1]

        constraints = ({'type': 'eq', 'fun': lambda x: portfolio_return(x) - target},
                    {'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
        bounds = tuple((0,1) for asset in range(num_assets))
        result = sco.minimize(portfolio_volatility, num_assets*[1./num_assets,], args=args, method='SLSQP', bounds=bounds, constraints=constraints)
        return result


    def efficient_frontier(mean_returns, cov_matrix, returns_range):
        efficients = []
        for ret in returns_range:
            efficients.append(efficient_return(mean_returns, cov_matrix, ret))
        return efficients

    def display_calculated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate):
        results, _ = random_portfolios(num_portfolios,mean_returns, cov_matrix, risk_free_rate)

        max_sharpe = max_sharpe_ratio(mean_returns, cov_matrix, risk_free_rate)
        sdp, rp = portfolio_annualised_performance(max_sharpe['x'], mean_returns, cov_matrix)
        max_sharpe_allocation = pd.DataFrame(max_sharpe.x,index=table.columns,columns=['allocation'])
        max_sharpe_allocation.allocation = [round(i*100,2)for i in max_sharpe_allocation.allocation]
        max_sharpe_allocation = max_sharpe_allocation.T

        min_vol = min_variance(mean_returns, cov_matrix)
        sdp_min, rp_min = portfolio_annualised_performance(min_vol['x'], mean_returns, cov_matrix)
        min_vol_allocation = pd.DataFrame(min_vol.x,columns=['allocation'])
        min_vol_allocation.allocation = [round(i*100,2)for i in min_vol_allocation.allocation]
        min_vol_allocation = min_vol_allocation.T


        print (min_vol_allocation)
        mylist.append(min_vol_allocation)


        plt.figure(figsize=(10, 7))
        plt.scatter(results[0,:],results[1,:],c=results[2,:],cmap='YlGnBu', marker='o', s=10, alpha=0.3)
        plt.colorbar()
        plt.scatter(sdp,rp,marker='*',color='r',s=500, label='Maximum Sharpe ratio')
        plt.scatter(sdp_min,rp_min,marker='*',color='g',s=500, label='Minimum volatility')

        target = np.linspace(rp_min, 0.32, 50)
        efficient_portfolios = efficient_frontier(mean_returns, cov_matrix, target)
        plt.plot([p['fun'] for p in efficient_portfolios], target, linestyle='-.', color='black', label='efficient frontier')
        plt.title('Calculated Portfolio Optimization based on Efficient Frontier')
        plt.xlabel('annualised volatility')
        plt.ylabel('annualised returns')
        plt.legend(labelspacing=0.8)




display_calculated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate)

这给出了以下输出:

                 0     1     2    3     4      5     6     7     8     9     10    11    12    13   14
allocation  0.0  3.51  0.15  2.4  0.59  12.58  6.04  15.0  8.55  3.63  2.55  15.0  15.0  15.0  0.0

             0     1     2    3     4      5     6     7     8     9     10    11    12    13   14
allocation  0.0  3.51  0.15  2.4  0.59  12.58  6.04  15.0  8.55  3.63  2.55  15.0  15.0  15.0  0.0

             0     1     2    3     4      5     6     7     8     9     10    11    12    13   14
allocation  0.0  3.51  0.15  2.4  0.59  12.58  6.04  15.0  8.55  3.63  2.55  15.0  15.0  15.0  0.0

当代码在循环中运行时,我想将分配中的所有值保存到列表中。我无法弄清楚如何使用附加功能来做到这一点。

标签: python

解决方案


我认为您的问题归结为在错误的时间做事。您当前的代码结构非常奇怪,您的函数定义在一个循环中(因此它们不断被重新定义),但仅在循环结束后调用:

my_list = []

for x in whatever():
    def foo(arg):
        my_list.append(arg)

foo(x)

这没有多大意义。该函数不依赖于x,并且调用只发生在最后一个x值(以及函数的最后一个定义,因为每个定义都是相同的,所以这部分并不重要)。

你应该重新安排事情。在循环外定义所有函数,并在其中调用它们:

my_list = []

def foo(arg):
    mylist.append(arg)

for x in whatever():
    foo(x)

此调用foo(仅定义一次!)为每个值x获取。该函数将每个附加到my_list(这非常简化,您的真实代码将进行大量处理并附加结果)。请注意,让函数执行附加可能并不理想。函数对其结果可能更有意义return,并让调用代码决定如何处理它。该设计可能允许您使用列表推导或map函数。


推荐阅读