Я хочу создать сценарий, который ищет оптимальное время для покупки и продажи корзины акций в течение месяца на основе общей доходности корзины.
Например, предположим, что у акции 1 самая высокая доходность в 8%, если я покупаю во 2 день и продаю в день 12, у акции 2 самая высокая доходность в 4%, если я покупаю в день 9 и продаю в день 15 и акция 3. имеет самую высокую доходность -1%, если я покупаю в день 1 и продаю в день 20. Мой вопрос заключается в том, как написать сценарий, который будет рассматривать все возможности возврата для всех трех акций и выдавать результат, который дает наивысший результат. возврат к общей корзине акций, если бы мне пришлось покупать все три акции в один и тот же день и продавать в один и тот же день.
Например, наивысший доход для всех трех акций может быть при покупке в 4-й день и продаже в 17-й день, когда общая прибыль на вложенный доллар составляет 7% для акции 1, 3,5% для акций 2 и -1,25% для акций. 3. Это основано на том факте, что мы не смогли бы получить наиболее оптимальную доходность для каждой акции, если бы все три акции были куплены и проданы в один и тот же день.
Нет, я понимаю, что это не прогнозный индикатор / скорее тестирование на истории для конкретной группы акций / анализ сектора.






отсортировать 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- так, например, в нем точно указано 23 ноября как дата покупки, но указано, что 30 ноября должно быть датой продажи, и похоже, что расчет принимает во внимание 12/3 как дату продажи для максимальной прибыли, но указывает 30 ноября как дату продажи - (правильный расчет с правильной датой, но при печати указана неточная дата продажи)
Да, sell_on должно быть i + j + 1. Исправлено
Прадип, большое спасибо! Вы очень талантливы, еще раз спасибо за вашу помощь!
Это похоже на очень старый пост, но я сразу перейду к тому, что у меня есть для вас.
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
Это проблема с домашним заданием?