Created
May 23, 2019 03:46
-
-
Save sshariff01/db52042cf74cd2a5011391a831a03fa5 to your computer and use it in GitHub Desktop.
ML4T - Project 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""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: Shoabe Shariff | |
GT User ID: sshariff3 | |
GT ID: 903272097 | |
""" | |
import pandas as pd | |
import matplotlib.pyplot as plt | |
import numpy as np | |
import datetime as dt | |
from util import get_data, plot_data | |
import scipy.optimize as spo | |
import math | |
import pdb | |
# This is the function that will be tested by the autograder | |
# The student must update this code to properly implement the functionality | |
def initial_allocations(syms): | |
number_of_syms = len(syms) | |
init_allocs = [] | |
while len(init_allocs) < number_of_syms: | |
init_allocs.append(1.0 / number_of_syms) | |
return np.asarray(init_allocs) | |
def neg_sharpe_ratio(allocs, prices): | |
start_val = 1000000 | |
normalized_prices = prices.apply(lambda x: x/x[0], axis=0) | |
alloced = normalized_prices * allocs | |
pos_vals = alloced * start_val | |
port_val = pos_vals.sum(axis=1) | |
daily_rets = port_val.diff()[1:] | |
return -1 * daily_rets.mean() / daily_rets.std() | |
def compute_daily_returns(df): | |
daily_returns = df.copy() | |
daily_returns[1:] = (df[1:] / df[:-1].values) - 1 | |
return daily_returns.ix[1:] | |
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 | |
# find the allocations for the optimal portfolio | |
# note that the values here ARE NOT meant to be correct for a test case | |
init_allocs = initial_allocations(syms) # add code here to find the allocations | |
bnds = [] | |
while len(bnds) < len(syms): | |
bnds.append((0.0, 1.0)) | |
cnstrnts = ({ 'type': 'eq', 'fun': lambda inputs: 1.0 - np.sum(inputs) }) | |
optimizer_result = spo.minimize(neg_sharpe_ratio, init_allocs, args=(prices,), constraints=cnstrnts, bounds=bnds) | |
allocs = optimizer_result.x | |
start_val = 1000000 | |
normalized_prices = prices / prices.ix[0,:] # .apply(lambda x: x/x[0], axis=0) | |
alloced = normalized_prices * allocs | |
pos_vals = alloced * start_val | |
port_val = pos_vals.sum(axis=1) | |
daily_rets = compute_daily_returns(port_val) | |
cr = (port_val[-1]/port_val[0]) - 1 | |
adr = daily_rets.mean() | |
sddr = daily_rets.std() | |
sr = math.sqrt(252) * daily_rets.mean() / daily_rets.std() | |
# Get daily portfolio value | |
# port_val = prices_SPY # add code here to compute daily portfolio values | |
# Compare daily portfolio value with SPY using a normalized plot | |
if gen_plot: | |
# add code to plot here | |
normalized_SPY = prices_SPY / prices_SPY.ix[0,:] | |
daily_portfolio_value = alloced.sum(axis=1).to_frame() | |
df_to_plot = daily_portfolio_value.join(normalized_SPY) | |
df_temp = pd.concat([df_to_plot], axis=1) | |
df_temp.columns=['Portfolio', 'SPY'] | |
df_temp.plot() | |
plt.show() | |
return allocs, cr, adr, sddr, sr | |
def test_code(): | |
# This function WILL NOT be called by the auto grader | |
# Do not assume that any variables defined here are available to your function/code | |
# It is only here to help you set up and test your 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'] | |
# Assess the portfolio | |
allocations, cr, adr, sddr, sr = optimize_portfolio(sd = start_date, ed = end_date,\ | |
syms = symbols, \ | |
gen_plot = False) | |
# Print statistics | |
print "Start Date:", start_date | |
print "End Date:", end_date | |
print "Symbols:", symbols | |
print "Allocations:", allocations | |
print "Sharpe Ratio:", sr | |
print "Volatility (stdev of daily returns):", sddr | |
print "Average Daily Return:", adr | |
print "Cumulative Return:", cr | |
if __name__ == "__main__": | |
# This code WILL NOT be called by the auto grader | |
# Do not assume that it will be called | |
# test_code() | |
# optimize_portfolio() | |
optimize_portfolio(sd=dt.datetime(2008,6,1), ed=dt.datetime(2009,6,1), syms=['IBM','X','GLD','JPM'], gen_plot=True) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment