【问题标题】:Python pandas stock basket return optimizationPython pandas 股票篮子收益优化
【发布时间】:2018-12-06 14:07:04
【问题描述】:

我想创建一个脚本,根据一篮子股票的整体回报,寻找一个月内买卖一篮子股票的最佳时间。

例如,假设我在第 2 天买入并在第 12 天卖出,股票 1 的最高回报率为 8%,如果我在第 9 天买入并在第 15 天卖出,股票 2 的最高回报率为 4%如果我在第 1 天买入并在第 20 天卖出,股票 3 的最高回报率为 -1%。我的问题是你如何编写一个脚本来查看所有三只股票的所有回报可能性并得出一个输出如果我必须在同一天购买所有三只股票并在同一天卖出,那么整个一揽子股票的回报率最高。

例如,所有三只股票的最高回报可能是在第 4 天买入并在第 17 天卖出,其中股票 1 的整体投资回报率为 7%、股票 2 为 3.5% 和 -1.25股票 3 的百分比。这是基于这样一个事实,即如果必须在同一天买卖所有三只股票,我们将无法获得每只股票的最佳回报。

【问题讨论】:

  • 这是作业题吗?
  • 不,我意识到这不是一个前瞻性指标/更多的是对特定股票/行业分析组的回测

标签: python pandas numpy


【解决方案1】:

按日期对 df 进行排序。

df = df.sort_values(by ='Date', ascending=True)

然后每天汇总所有股票

df['total'] = df[['TSLA Price', 'NVDA Price', 'AAPL Price']].sum(axis=1)

然后使用下面的函数

def max_profit(li):
    max_profit, purchase_on, sell_on = 0, 0, 0
    for i, buy in enumerate(li):
        for j, sell in enumerate(li[i+1:]):
            if sell-buy > max_profit:
                max_profit, purchase_on, sell_on = sell-buy, i, i+j+1
    return max_profit, purchase_on, sell_on

max_profit, purchase_on, sell_on = max_profit(df['total'].tolist())

买入/卖出日期将是...

buy_date, sell_date = df['Date'].iloc[purchase_on], df['Date'].iloc[sell_on ]

要不同的权重,只需将股票乘以权重,然后求和。

【讨论】:

  • 普拉迪普!这很棒!这看起来很棒,我只能看到一个问题-运行代码后,它确实将回报固定在收盘价之间的最大收益范围内,但是,由于某种原因,它给出了销售日期-1-例如它准确地将 11/23 列为购买日期,但将 11/30 列为销售日期,看起来计算考虑到 12/3 作为最大收益的销售日期,但将 11/30 列为销售日期- (计算正确,日期正确,但打印时列出的销售日期不准确)
  • 是的,sell_on 应该是 i+j+1。已更正
  • 普拉迪普,非常感谢!您非常有才华,再次感谢您的帮助!
【解决方案2】:

这看起来像是一篇很老的帖子,但我会用我为你准备的内容加入。

import pandas as pd  
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import scipy.optimize as sco
import datetime as dt
import math
from datetime import datetime, timedelta
from pandas_datareader import data as wb
from sklearn.cluster import KMeans
np.random.seed(777)


start = '2018-06-30'
end = '2020-06-30'
# N = 90
# start = datetime.now() - timedelta(days=N)
# end = dt.datetime.today()



tickers = ['AXP','AAPL','BA','CAT','CSCO','CVX','XOM','GS','HD','IBM','INTC','JNJ','KO','JPM','MCD','MMM','MRK','MSFT','NKE','PFE','PG','TRV','UNH','RTX','VZ','V','WBA','WMT','DIS','DOW']

thelen = len(tickers)

price_data = []
for ticker in tickers:
    prices = wb.DataReader(ticker, start = start, end = end, data_source='yahoo')[['Adj Close']]
    price_data.append(prices.assign(ticker=ticker)[['ticker', 'Adj Close']])

df = pd.concat(price_data)
df.dtypes
df.head()
df.shape

pd.set_option('display.max_columns', 500)

df = df.reset_index()
df = df.set_index('Date')
table = df.pivot(columns='ticker')
# By specifying col[1] in below list comprehension
# You can select the stock names under multi-level column
table.columns = [col[1] for col in table.columns]
table.head()

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


returns = table.pct_change()
mean_returns = returns.mean()
cov_matrix = returns.cov()
num_portfolios = 10000
risk_free_rate = 0.0178



def display_simulated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate):
    results, weights = random_portfolios(num_portfolios,mean_returns, cov_matrix, risk_free_rate)
    
    max_sharpe_idx = np.argmax(results[2])
    sdp, rp = results[0,max_sharpe_idx], results[1,max_sharpe_idx]
    max_sharpe_allocation = pd.DataFrame(weights[max_sharpe_idx],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_idx = np.argmin(results[0])
    sdp_min, rp_min = results[0,min_vol_idx], results[1,min_vol_idx]
    min_vol_allocation = pd.DataFrame(weights[min_vol_idx],index=table.columns,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("-")
    print("Maximum Sharpe Ratio Portfolio Allocation\n")
    print("Annualised Return:", round(rp,2))
    print("Annualised Volatility:", round(sdp,2))
    print("\n")
    print(max_sharpe_allocation)
    print("-")
    print("Minimum Volatility Portfolio Allocation\n")
    print("Annualised Return:", round(rp_min,2))
    print("Annualised Volatility:", round(sdp_min,2))
    print("\n")
    print(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')
    plt.title('Simulated Portfolio Optimization based on Efficient Frontier')
    plt.xlabel('annualised volatility')
    plt.ylabel('annualised returns')
    plt.legend(labelspacing=0.8)
    

display_simulated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate)

结果:

Maximum Sharpe Ratio Portfolio Allocation

Annualised Return: 0.16
Annualised Volatility: 0.25


            AAPL   AXP    BA   CAT  CSCO   CVX   DIS   DOW    GS    HD   IBM  \
allocation  4.76  1.63  1.03  0.26  1.22  0.05  6.86  0.43  1.02  6.42  0.88   

            INTC   JNJ   JPM    KO   MCD   MMM   MRK  MSFT   NKE   PFE    PG  \
allocation  2.56  0.64  4.92  0.27  6.64  4.13  6.99  5.49  4.52  2.35  6.36   

            RTX   TRV   UNH    V    VZ   WBA   WMT  XOM  
allocation  5.3  1.79  0.39  6.8  7.06  0.67  5.98  2.6  
-
Minimum Volatility Portfolio Allocation

Annualised Return: 0.13
Annualised Volatility: 0.24


            AAPL   AXP    BA   CAT  CSCO   CVX   DIS   DOW    GS    HD   IBM  \
allocation  4.43  0.59  0.59  1.01  1.69  0.56  1.04  0.81  0.64  1.44  1.72   

            INTC   JNJ  JPM    KO   MCD   MMM   MRK  MSFT  NKE   PFE    PG  \
allocation  3.43  3.47  2.9  5.43  7.61  4.99  7.78  4.72  2.2  7.13  6.72   

             RTX   TRV   UNH     V    VZ   WBA   WMT   XOM  
allocation  0.47  4.56  2.95  0.47  6.84  7.81  4.76  1.23 

最后:

您还可以尝试其他事情。查看下面的链接了解所有详细信息。

https://github.com/ASH-WICUS/Notebooks/blob/master/Portfolio%20Optimization.ipynb

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-13
    相关资源
    最近更新 更多