def efficient_frontier(returns_monthly, returns_annual): returns = np.array(returns_annual) covar = np.array(returns_monthly.cov() * 12) weights_0 = np.array(list(range(0, 51))) / 50 weights = np.array([weights_0, 1 - weights_0]).T port_returns = [w[0] * returns[0] + w[1] * returns[1] for w in weights] port_vars = [w[0]**2 * covar[0,0] + \ w[1]**2 * covar[1,1] + \ 2 * w[0] * w[1] * covar[0,1] for w in weights] port_sds = [np.sqrt(v) for v in port_vars] port_SRs = [ sharpe_ratio(average_exp_return(returns_annual, w), np.sqrt(portfolio_variance(covar, w))) for w in weights ] df = pd.DataFrame([port_returns, port_sds, port_SRs]).transpose() df.columns = ['Returns', 'Volatility', 'Sharpe Ratio'] plt.style.use('seaborn-deep') df.plot.scatter(x='Volatility', y='Returns', c='Sharpe Ratio', cmap='RdYlGn', edgecolors='black', figsize=(6, 6), grid=True) plt.xlabel('Volatility (Std. Deviation)') plt.ylabel('Expected Returns') plt.title('Efficient Frontier') plt.show()
def compute_params(list_data_tuples): df=util.get_data(list_data_tuples) # Here columns will be the list of symbols as requested by user # Now compute the parameters and for each symbol in this above dataframe # Also get the data description using the describe feature describe_features=df.describe() computed_df=pd.DataFrame(index=['CDR','ADR','STDDR','SR'],columns=df.columns) for sym in df.columns: dr=util.compute_daily_returns(df[sym]) cdr=util.cummulative_return(df[sym]) adr=dr.mean() sddr=np.std(dr) sr=util.sharpe_ratio(adr, sddr) computed_df.ix['CDR'][sym]=cdr computed_df.ix['ADR'][sym]=adr computed_df.ix['STDDR'][sym]=sddr computed_df.ix['SR'][sym]=sr return computed_df,describe_features
def sharpe_function(allocs,df,sv=1000000,sf=252.0,rfr=0.0): """Takes the allocations and computes the sharpe ratio""" # 1. Normalize the prices according to the first day df=df/df.ix[0,:] # 2. Multiply each column by allocation to the corresponding equity df=allocs*df # Number of columns in df should be same as the elements in alloc # 3. Multiply these normalized allocations by starting value of overall portfolio, to get position values df=sv*df; # sv is the start-value # 4. Sum each row (i.e., all position values for each day). That is your portfolio value df=df.sum(axis=1) # This gives daily portfolio value dr_df=util.compute_daily_returns(df) adr=dr_df.mean(); # This is daily-return data frame # 5c. Standard deviation sddr=np.std(dr_df) # 5d. Sharpe ratio sr= util.sharpe_ratio(adr=adr,sddr=sddr,sf=sf,rfr=0.0) # -1 is multiplied as max=min*-1 return sr*-1
def negative_sharpe(allocs, data, start_val, dates, symbols): """ C: numpy.poly1d object or equivalent array representing polynomial coefficients data: 2D array where each row is a point (x, y) Returns error as a single real value. """ result = util.sharpe_ratio( util.portfolio_daily_values(start_val, dates, symbols, allocs)) #print('result: ', result) return result
def test_run(): start_date = '2010-08-31' end_date = '2013-01-01' dates = pd.date_range(start_date, end_date) symbols = ['SPY', 'XOM', 'GLD'] allocs = pd.Series({'SPY': 0.4, 'XOM': 0.4, 'GLD': 0.2}) start_val = 1000000 # one million dollars!!! # Get data port_vals = util.portfolio_daily_values(start_val, dates, symbols, allocs) daily_returns = util.daily_returns(port_vals) print('Average Daily Returns:=', daily_returns.mean()) print('Standard Daily Return or Risk:=', daily_returns.std()) print('Sharpe Ratio:=', util.sharpe_ratio(daily_returns)) daily_returns.plot() plt.show()
def compute_indicators(portvals, sf=252.0, rfr=0.0): # Compute daily returns daily_returns = util.compute_daily_returns(portvals) # compute cumulative daily return for portfolio cr = util.cummulative_return(portvals) # average daily return adr = daily_returns.mean() # standard deviation of the daily return sddr = daily_returns.std() # Sharpe ratio sr = util.sharpe_ratio(adr, sddr, sf, rfr) return sr, cr, sddr, adr
def max_sharpe_ratio_weights(returns_monthly, returns_annual, step=0.0001): max_sr_weights = [0.0, 1.0] max_sr = float('-inf') covariance = np.array(returns_monthly.cov() * 12) returns = np.array(returns_annual) weight_1 = 0.0 while weight_1 <= 1.0: weight_2 = 1 - weight_1 expected = average_exp_return(returns, [weight_1, weight_2]) variance = portfolio_variance(covariance, [weight_1, weight_2]) sr = sharpe_ratio(expected, np.sqrt(variance)) if sr > max_sr: max_sr_weights = [weight_1, weight_2] max_sr = sr weight_1 += step return max_sr, max_sr_weights
def access_portfolio(sd=datetime.datetime(2008,1,1),ed=datetime.datetime(2009,1,1), sym=['GOOG','AAPL','GLD','XOM'], allocs=[0.1,0.2,0.3,0.4],sv=1000000,rfr=0.0,sf=252.0,gen_plot=False): """ This function computes statistics for the portfolio Usage: cr, adr, sddr, sr, ev = assess_portfolio(sd=dt.datetime(2008,1,1), ed=dt.datetime(2009,1,1), syms=['GOOG','AAPL','GLD','XOM'],allocs=[0.1,0.2,0.3,0.4], \ sv=1000000, rfr=0.0, sf=252.0, gen_plot=False) Outputs: cr: Cumulative return adr: Average period return (if sf == 252 this is daily return) sddr: Standard deviation of daily return sr: Sharpe ratio ev: End value of portfolio Inputs: sd: A datetime object that represents the start date ed: A datetime object that represents the end date syms: A list of symbols that make up the portfolio (note that your code should support any symbol in the data directory) allocs: A list of allocations to the stocks, must sum to 1.0 sv: Start value of the portfolio rfr: The risk free return per sample period for the entire date range (a single number, not an array). sf: Sampling frequency per year gen_plot: If True, create a plot named plot.png """ # First get data for the date and symbols dt_range=pd.date_range(sd, ed) # Create series of dates for which the data needs to be obtained df=util.get_data(sym, dt_range); # This gets the adjust close value of the stock for each date and date frame index is date # If SPY exists in the df, then drop it (we need SPY to get the dates for all the trading dates) normalized_plot_df=pd.DataFrame(df.SPY/df.SPY[0],index=df.index) df=df.drop('SPY',axis=1) # To compute daily portfolio, we need to follow these steps: # 1. Normalize the prices according to the first day df=df/df.ix[0,:] # 2. Multiply each column by allocation to the corresponding equity df=allocs*df # Number of columns in df should be same as the elements in alloc # 3. Multiply these normalized allocations by starting value of overall portfolio, to get position values df=sv*df; # sv is the start-value # 4. Sum each row (i.e., all position values for each day). That is your portfolio value df=df.sum(axis=1) # This gives daily portfolio value # 5. Compute statistics from the total portfolio value # 5a. Cummulative daily return cr= util.cummulative_return(df); # 5b. Average daily return dr_df=util.compute_daily_returns(df) adr=dr_df.mean(); # This is daily-return data frame # 5c. Standard deviation sddr=np.std(dr_df) # 5d. Sharpe ratio sr=util.sharpe_ratio(adr=adr,sddr=sddr,sf=sf,rfr=rfr) # sr=sf**(1.0/2)*(adr-rfr)/sddr # 5e. End value of the portfolio (How much your portfolio values at the end of the duration) ev=df.ix[-1]; # Plot the normalized portfolio again normalized SPY normalized_plot_df=normalized_plot_df.join(pd.DataFrame(df/df.ix[0],columns=['Portfolio']),how='inner') if gen_plot==True: util.plot_data(normalized_plot_df, title='Daily portfolio value and SPY',y_label='Normalized price') return cr,adr,sddr,sr,ev