Files
ML4T/optimize_something/optimization.py
2020-09-07 21:24:45 -04:00

140 lines
4.8 KiB
Python

"""MC1-P2: Optimize a portfolio.
Copyright 2018, Georgia Institute of Technology (Georgia Tech)
Atlanta, Georgia 30332
All Rights Reserved
Template code for CS 4646/7646
Georgia Tech asserts copyright ownership of this template and all derivative
works, including solutions to the projects assigned in this course. Students
and other users of this template code are advised not to share it with others
or to make it available on publicly viewable websites including repositories
such as github and gitlab. This copyright statement should not be removed
or edited.
We do grant permission to share solutions privately with non-students such
as potential employers. However, sharing with other current or future
students of CS 7646 is prohibited and subject to being investigated as a
GT honor code violation.
-----do not edit anything above this line---
Student Name: Tucker Balch (replace with your name)
GT User ID: tb34 (replace with your User ID)
GT ID: 900897987 (replace with your GT ID)
"""
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import datetime as dt
import math
import scipy.optimize as opt
from util import get_data, plot_data
def get_sharpe_ratio(daily_returns):
SR = daily_returns.mean() / daily_returns.std()
k = math.sqrt(252) # daily sampling
SR = k * SR
return SR
def get_daily_returns(df):
daily_returns = df.copy()
daily_returns[1:] = (df[1:] / df[:-1].values) - 1
daily_returns = daily_returns.iloc[1:]
return daily_returns
def get_daily_portfolio_value(prices, allocs):
normed = prices / prices.iloc[0, :]
alloced = normed * allocs
port_values = alloced.sum(axis=1)
return port_values
def calculate_stats(prices, allocs):
port_value = get_daily_portfolio_value(prices, allocs)
cum_ret = (port_value.iloc[-1] / port_value.iloc[0]) - 1
daily_returns = get_daily_returns(port_value)
avg_daily_ret = daily_returns.mean()
std_daily_ret = daily_returns.std()
sharpe_ratio = get_sharpe_ratio(daily_returns)
return [cum_ret, avg_daily_ret, std_daily_ret, sharpe_ratio]
# This is the function that will be tested by the autograder
# The student must update this code to properly implement the functionality
def optimize_portfolio(sd=dt.datetime(2008,1,1), ed=dt.datetime(2009,1,1), \
syms=['GOOG','AAPL','GLD','XOM'], gen_plot=False):
# Read in adjusted closing prices for given symbols, date range
dates = pd.date_range(sd, ed)
prices_all = get_data(syms, dates) # automatically adds SPY
prices = prices_all[syms] # only portfolio symbols
prices_SPY = prices_all['SPY'] # only SPY, for comparison later
def calc_sr(allocs):
port_value = get_daily_portfolio_value(prices, allocs)
cum_ret = (port_value.iloc[-1] / port_value.iloc[0]) - 1
daily_returns = get_daily_returns(port_value)
sharpe_ratio = get_sharpe_ratio(daily_returns)
return sharpe_ratio * -1
# find the allocations for the optimal portfolio
len_syms = len(syms)
allocs = np.asarray([1 / len_syms for _ in range(len_syms)])
bounds = [(0, 1) for _ in range(len_syms)]
consts = ({'type': 'eq', 'fun': lambda inputs: 1.0 - np.sum(inputs)})
result = opt.minimize(calc_sr, x0=allocs, bounds=bounds, constraints=consts)
print(result)
allocs = result.x
cr, adr, sddr, sr = calculate_stats(prices, allocs)
# Compare daily portfolio value with SPY using a normalized plot
if gen_plot:
port_val = get_daily_portfolio_value(prices, allocs)
prices_SPY_normed = prices_SPY / prices_SPY.iloc[0]
df_temp = pd.concat([port_val, prices_SPY_normed], keys=['Portfolio', 'SPY'], axis=1)
ax = df_temp.plot(title="SPY and Portfolio Normed", fontsize=12)
plt.savefig('plot.png')
plt.show()
return allocs, cr, adr, sddr, sr
def report():
start_date = dt.datetime(2008,6,1)
end_date = dt.datetime(2009,6,1)
symbols = ['IBM', 'X', 'GLD', 'JPM']
allocations, cr, adr, sddr, sr = optimize_portfolio(sd = start_date, ed = end_date,\
syms = symbols, gen_plot = True)
def test_code():
# Define input parameters
# Note that ALL of these values will be set to different values by
# the autograder!
start_date = dt.datetime(2009,1,1)
end_date = dt.datetime(2010,1,1)
symbols = ['GOOG', 'AAPL', 'GLD', 'XOM', 'IBM']
allocations, cr, adr, sddr, sr = optimize_portfolio(sd = start_date, ed = end_date,\
syms = symbols, gen_plot = True)
# Print statistics
print(f"Start Date: {start_date}")
print(f"End Date: {end_date}")
print(f"Symbols: {symbols}")
print(f"Allocations:{allocations}")
print(f"Sharpe Ratio: {sr}")
print(f"Volatility (stdev of daily returns): {sddr}")
print(f"Average Daily Return: {adr}")
print(f"Cumulative Return: {cr}")
if __name__ == "__main__":
# test_code()
report()