1
0
Fork 0

Finish project 2.

master
Felix Martin 2020-09-07 21:24:45 -04:00
parent a7e17c6059
commit 927c5eb9de
4 changed files with 76 additions and 23 deletions

View File

@ -36,5 +36,7 @@ unzip -n zips/19fall_optimize_something.zip -d ./
# Reports # Reports
- [Report 1](./martingale/martingale.md) - [Report 1](./martingale/martingale.md)
- [Report 2](#) - [Report 2](./optimize_something/readme.md)
- [Report 3](#)

View File

@ -30,8 +30,42 @@ import pandas as pd
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
import datetime as dt import datetime as dt
import math
import scipy.optimize as opt
from util import get_data, plot_data 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 # This is the function that will be tested by the autograder
# The student must update this code to properly implement the functionality # 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), \ def optimize_portfolio(sd=dt.datetime(2008,1,1), ed=dt.datetime(2009,1,1), \
@ -43,41 +77,52 @@ def optimize_portfolio(sd=dt.datetime(2008,1,1), ed=dt.datetime(2009,1,1), \
prices = prices_all[syms] # only portfolio symbols prices = prices_all[syms] # only portfolio symbols
prices_SPY = prices_all['SPY'] # only SPY, for comparison later prices_SPY = prices_all['SPY'] # only SPY, for comparison later
plot_data(prices_all) 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 # find the allocations for the optimal portfolio
# note that the values here ARE NOT meant to be correct for a test case len_syms = len(syms)
allocs = np.asarray([0.2, 0.2, 0.3, 0.3]) # add code here to find the allocations allocs = np.asarray([1 / len_syms for _ in range(len_syms)])
cr, adr, sddr, sr = [0.25, 0.001, 0.0005, 2.1] # add code here to compute stats bounds = [(0, 1) for _ in range(len_syms)]
consts = ({'type': 'eq', 'fun': lambda inputs: 1.0 - np.sum(inputs)})
# Get daily portfolio value result = opt.minimize(calc_sr, x0=allocs, bounds=bounds, constraints=consts)
port_val = prices_SPY # add code here to compute daily portfolio values print(result)
allocs = result.x
cr, adr, sddr, sr = calculate_stats(prices, allocs)
# Compare daily portfolio value with SPY using a normalized plot # Compare daily portfolio value with SPY using a normalized plot
if gen_plot: if gen_plot:
# add code to plot here port_val = get_daily_portfolio_value(prices, allocs)
df_temp = pd.concat([port_val, prices_SPY], keys=['Portfolio', 'SPY'], axis=1) prices_SPY_normed = prices_SPY / prices_SPY.iloc[0]
pass 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 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
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 # Define input parameters
# Note that ALL of these values will be set to different values by # Note that ALL of these values will be set to different values by
# the autograder! # the autograder!
start_date = dt.datetime(2009,1,1) start_date = dt.datetime(2009,1,1)
end_date = dt.datetime(2010,1,1) end_date = dt.datetime(2010,1,1)
symbols = ['GOOG', 'AAPL', 'GLD', 'XOM', 'IBM'] symbols = ['GOOG', 'AAPL', 'GLD', 'XOM', 'IBM']
# Assess the portfolio
allocations, cr, adr, sddr, sr = optimize_portfolio(sd = start_date, ed = end_date,\ allocations, cr, adr, sddr, sr = optimize_portfolio(sd = start_date, ed = end_date,\
syms = symbols, \ syms = symbols, gen_plot = True)
gen_plot = False)
# Print statistics # Print statistics
print(f"Start Date: {start_date}") print(f"Start Date: {start_date}")
@ -90,6 +135,5 @@ def test_code():
print(f"Cumulative Return: {cr}") print(f"Cumulative Return: {cr}")
if __name__ == "__main__": if __name__ == "__main__":
# This code WILL NOT be called by the auto grader # test_code()
# Do not assume that it will be called report()
test_code()

BIN
optimize_something/plot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@ -0,0 +1,7 @@
# Report
IBM, X, GLD, JPM portfolio optimization for the timeframe from 08-06-01 till
09-06-01.
![](plot.png)