def get_portfolio_stats(portfolio, rfr=0.0, sf=252): """Take a portfolio dataframe as input and return its cumulative return, average daily return, standard deviation and sharpe ratio. Parameters: ---------- portfolio: dataframe containing prices of the portfolio. rfr: float - risk free rate sf: int - sampling frequency per year, needed to calculate shapre ratio. Return cumulative return, average daily return, standard deviation and sharpe ratio """ #Cumulative return cum_ret = (portfolio[-1] / portfolio[0]) - 1 #Daily returns and delete row 1 = zero because it affects calculations. daily_returns = compute_daily_returns(portfolio) daily_returns = daily_returns[1:] #Average daily return ave_daily_ret = daily_returns.mean() #Std dev of daily returns std_daily_ret = daily_returns.std() #Sharp ratio of portfolio sharpe_ratio = np.sqrt(sf) * ((daily_returns - rfr).mean()) / std_daily_ret #end value of portfolio #end_val = portfolio[-1] return cum_ret, ave_daily_ret, std_daily_ret, sharpe_ratio
def test_run(): start_date = '2009-01-01' end_date = '2012-12-31' dates = pd.date_range(start_date, end_date) symbols = ['SPY'] df = get_data(symbols, dates) daily_returns = compute_daily_returns(df) plot_data(daily_returns, title="Daily returns", ylabel="Daily returns") daily_returns.hist(bins=20) mean = daily_returns['SPY'].mean() print("mean:\t\t\t{}".format(mean)) std = daily_returns['SPY'].std() print("std. deviation:\t{}".format(std)) plt.axvline(mean, color='red', linestyle='dashed', linewidth=1) plt.axvline(std, color='black', linestyle='dashed', linewidth=1) plt.axvline(-std, color='black', linestyle='dashed', linewidth=1) plt.show() kurtosis = daily_returns.kurtosis() print("kurtosis:\t{}".format(kurtosis))
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 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 test_run(): start_date = '2007-01-01' end_date = '2013-08-31' dates = pd.date_range(start_date, end_date) symbols = ['SPY', 'XOM'] # Get data df = util.get_data(symbols, dates) # util.plot_data(df, "SPY") # Compute daily returns daily_returns = util.compute_daily_returns(df) # util.plot_data(daily_returns, title='Daily Returns', ylabel='Daily Returns') daily_returns['SPY'].hist(bins=20, label='SPY') daily_returns['XOM'].hist(bins=20, label='XOM') plt.legend(loc='upper right') plt.show()
def test_run(): """Plot histograms""" start_date = '2009-01-01' end_date = '2012-12-31' dates = pd.date_range(start_date, end_date) symbols = ['SPY', 'XOM'] df = get_data(symbols, dates) # Plot stocks plot_data(df) # Compute daily returns daily_returns = compute_daily_returns(df) plot_data(daily_returns, title="Daily returns") # Plot histograms same chart daily_returns['SPY'].hist(bins=20, label="SPY") daily_returns['XOM'].hist(bins=20, label="XOM") plt.legend(loc="upper left") plt.show()
def run(): """read data""" dates = pd.date_range('2016-01-01', '2018-06-01') symbols = ['ETHUSD'] df = get_data(symbols, dates) """compute daily returns""" dailyReturns = compute_daily_returns(df) dailyReturns.hist(bins=20) mean = dailyReturns.mean() std = dailyReturns.std() kurtosis = dailyReturns.kurtosis() print("Mean:"+ dailyReturns.mean().to_string().split(' ', 1)[1]) print("standard dev:"+ dailyReturns.std().to_string().split(' ', 1)[1]) print("kurtosis:"+ dailyReturns.kurtosis().to_string().split(' ', 1)[1]) plt.axvline(float(mean), color='w', linestyle='dashed', linewidth=2) plt.axvline(float(std), color='r', linestyle='dashed', linewidth=2) plt.axvline(float(-std), color='r', linestyle='dashed', linewidth=2) plt.show()
def portfolio_stats(portfolio_df): """Takes as input a portfolio dataframe. Returns a dictionary with portfolio's mean, std_dev, cum return, and sharpe ratio.""" #Calculate the daily returns of the portfolio daily_returns = compute_daily_returns(portfolio_df) #Delete the first row which is zero daily_returns = daily_returns[1:] #Calculate statistics port_cum_return = (portfolio_df[-1] / portfolio_df[0]) - 1 avg_daily_return = daily_returns.mean() std_dev_daily_return = daily_returns.std() sharpe_ratio = avg_daily_return / std_dev_daily_return results = { 'port_cum_return': port_cum_return, 'ave_daily_return': avg_daily_return, 'std_dev_daily_return': std_dev_daily_return, 'sharpe_ratio': sharpe_ratio } return results
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
def addEvidence(self, symbol = "GOOG", \ sd=dt.datetime(2004,8,19), \ ed=dt.datetime(2005,8,19), \ sv = 10000): syms = [symbol] dates = pd.date_range(sd, ed) # read price data prices_all = ut.get_data(syms, dates) # automatically adds SPY prices = prices_all[syms] # only portfolio symbols prices_SPY = prices_all['SPY'] # only SPY, for comparison later if self.verbose: print prices.head() # discretize ratio close/SMA ratio_close_SMA = ut.compute_ratio_close_SMA(prices, window=self.window) ratio_close_SMA.dropna(inplace=True) self.ratio_close_SMA_thresholds = ut.compute_discretizing_thresholds( ratio_close_SMA[symbol], steps=10) discrete_close_SMA = ut.discretize_df_thresholds(ratio_close_SMA[symbol], \ self.ratio_close_SMA_thresholds) # discretize percent_b percent_b = ut.compute_percent_b(prices, window=self.window) percent_b.dropna(inplace=True) self.percent_b_thresholds = ut.compute_discretizing_thresholds( percent_b[symbol], steps=10) discrete_percent_b = ut.discretize_df_thresholds(percent_b[symbol],\ self.percent_b_thresholds) # compute daily returns of the stock stock_daily_returns = ut.compute_daily_returns(prices) # compute daily absolute changes of the stock stock_daily_changes = ut.compute_daily_changes(prices) # initiate a Q-learner self.learner = ql.QLearner(num_states=3000,\ num_actions = 3, \ alpha = self.alpha, \ gamma = self.gamma, \ rar = self.rar, \ radr = self.radr, \ dyna = 0, \ learning = self.learning,\ verbose=False) # initiate cumulative return cumulative_return = list() num_trials = 300 for trial in range(0, num_trials): # initiate holding (holding takes values -1, 0 , 1) holding = 0 # initiate portfolio value portfolio = sv ## for each day in the training data with features # set the state and get the first action state_since_entry = ut.discretize_return_since_entry(portfolio, sv, threshold=0.1) state = ut.stack_digits([holding+1,\ state_since_entry, \ discrete_close_SMA[0],\ discrete_percent_b[0]]) action = self.learner.querysetstate(state) holding = action - 1 ##move to new state according to action and then get a new action for t in discrete_close_SMA[1:].index.tolist(): # daily return as rewards r = stock_daily_returns[symbol][t] * holding state_since_entry = ut.discretize_return_since_entry( portfolio, sv, threshold=0.1) state = ut.stack_digits([holding+1, \ state_since_entry, \ discrete_close_SMA[t], \ discrete_percent_b[t]]) action = self.learner.query(state, r) #update portfolio value portfolio += stock_daily_changes[symbol][t] * holding * 100 holding = action - 1 cumulative_return.append(portfolio / sv - 1) #print "cumulative return of training:",cumulative_return[-1] return cumulative_return
def testPolicy(self, symbol = "IBM", \ sd=dt.datetime(2009,12,31), \ ed=dt.datetime(2011,12,31), \ sv = 10000): syms = [symbol] dates = pd.date_range(sd, ed) # read price data prices_all = ut.get_data(syms, dates) # automatically adds SPY prices = prices_all[syms] # only portfolio symbols prices_SPY = prices_all['SPY'] # only SPY, for comparison later # discretize ratio close/SMA ratio_close_SMA = ut.compute_ratio_close_SMA(prices, window=self.window) ratio_close_SMA.dropna(inplace=True) discrete_close_SMA = ut.discretize_df_thresholds(ratio_close_SMA[symbol], \ self.ratio_close_SMA_thresholds) # discretize percent_b percent_b = ut.compute_percent_b(prices, window=self.window) percent_b.dropna(inplace=True) discrete_percent_b = ut.discretize_df_thresholds(percent_b[symbol],\ self.percent_b_thresholds) # compute daily returns of the stock stock_daily_returns = ut.compute_daily_returns(prices) # compute daily absolute changes of the stock stock_daily_changes = ut.compute_daily_changes(prices) holding = 0 portfolio = sv trades = prices_all[[ symbol, ]] # only portfolio symbols trades.values[:, :] = 0 # set them all to nothing for t in discrete_close_SMA.index.tolist(): # compute current state state_since_entry = ut.discretize_return_since_entry(portfolio, sv, threshold=0.1) state = ut.stack_digits([holding+1, \ state_since_entry, \ discrete_close_SMA[t], \ discrete_percent_b[t]]) action = self.learner.querysetstate(state) #update portfolio value portfolio += stock_daily_changes[symbol][t] * holding * 100 old_holding = holding holding = action - 1 trades[symbol][t] = (holding - old_holding) * 100 cumulative_return = portfolio / sv - 1 #print "cumulative return of testing:",cumulative_return return trades, cumulative_return
import numpy as np import matplotlib.pyplot as plt from util import get_data, plot_data, compute_daily_returns if __name__ == "__main__": # Define date range start_date = '2015-10-02' end_date = '2017-10-17' # Read data dates = pd.date_range(start_date, end_date) symbols = ['SPY', 'XOM', 'ALRM'] df = get_data(symbols, dates) plot_data(df) # Compute daily returns daily_returns = compute_daily_returns(df) #plot_data(daily_returns, title="Daily returns", ylabel="Daily returns") # Plot both histogram on the same chart #daily_returns['SPY'].hist(bins=20, label="SPY") #daily_returns['XOM'].hist(bins=20, label="XOM") #plt.show() """ # Get mean and standard deviation mean = daily_returns['SPY'].mean() print("Mean=", mean) std = daily_returns['SPY'].std() print("st.dev=",std) plt.axvline(mean, color='w', linestyle='dashed', linewidth=2) plt.axvline(std, color='r', linestyle='dashed', linewidth=2)
def test_run(): # Read data and plot dates = pd.date_range('2009-01-01', '2012-12-31') symbols = ['SPY', 'XOM', 'GLD', 'GOOG'] initialize = 'n' # toggles whether or not to initialize with SPY data (must be 'n' if SPY is in symbols) df = get_data(symbols, dates, initialize) plot_data(df) # Compute daily returns daily_returns = compute_daily_returns(df) plot_data(daily_returns, title='Daily Returns', xlabel='Date', ylabel='Daily Returns') # Plot a histogram daily_returns.hist(bins=20) # Get mean and stdev mean = daily_returns['SPY'].mean() print 'mean=', mean std = daily_returns['SPY'].std() print 'stdev=', std # Scatterplot SPY vs GOOG daily_returns.plot(kind='scatter', title='Correlation SPY vs GOOG', x='SPY', y='GOOG') # beta is the slope of the line in the scatterplot, and alpha is the intercept beta_GOOG, alpha_GOOG = np.polyfit(daily_returns['SPY'], daily_returns['GOOG'], 1) # this returns the alpha and beta for GOOG # below '-' indicates a line should be drawn plt.plot(daily_returns['SPY'], beta_GOOG*daily_returns['SPY'] + alpha_GOOG, '-', color='r') # plots a regression curve using y = mx + b print '\nGOOG beta = ', beta_GOOG print 'GOOG alpha = ', alpha_GOOG # higher alpha would mean the stock performed better than the SPY plt.show() # Scatterplot SPY vs XOM daily_returns.plot(kind='scatter', title='Correlation SPY vs XOM', x='SPY', y='XOM') # beta is the slope of the line in the scatterplot, and alpha is the intercept beta_XOM, alpha_XOM = np.polyfit(daily_returns['SPY'], daily_returns['XOM'], 1) # this returns the alpha and beta for XOM # below '-' indicates a line should be drawn plt.plot(daily_returns['SPY'], beta_GOOG*daily_returns['SPY'] + alpha_XOM, '-', color='r') # plots a regression curve using y = mx + b print '\nXOM beta = ', beta_XOM print 'XOM alpha = ', alpha_XOM # higher alpha would mean the stock performed better than the SPY plt.show() # Calculate Correlation Coefficient # this uses pearson correlation coeff method to estimate how closely the data points fit the regression line print '\nCorrelation Coefficients:\n', daily_returns.corr(method='pearson') # plot separate plots for each stock plt.axvline(mean, color='w', linestyle='dashed', linewidth=2) # adds vertical dashed line at the mean plt.axvline(std, color='r', linestyle='dashed', linewidth=2) plt.axvline(-std, color='r', linestyle='dashed', linewidth=2) plt.show() # plot overlayed plots daily_returns['SPY'].hist(bins=20, label='SPY') daily_returns['XOM'].hist(bins=20, label='XOM') daily_returns['GLD'].hist(bins=20, label='GLD') plt.legend(loc='upper right') plt.show() # Compute kurtosis # This is how closely a dataset fits a gaussian normal distribution +num has longer tails, -num shorter tails print '\nKurtosis:\n', daily_returns.kurtosis()
def plot_params(list_data_tuples): #script_el_param='' #div_el_param='<h4> Time-series plot for computed parameters <table style="width 50%"> <tr>' list_plots=[] # Here we need to compute the following: # (1) Daily returns (2) Rolling standard deviation (3) Bollinger bands (4) Rolling std # Generate plot for each symbols df=util.get_data(list_data_tuples) # Normalize the data df=df/df.ix[0,:] daily_returns = util.compute_daily_returns(df) rolling_mean=util.get_rolling_mean(df, window=20) # drop the rows where the values are 0, for instance for window 20, the first 20 are zeros rolling_mean=rolling_mean[(rolling_mean.sum(axis=1)!=0)] rolling_std=util.get_rolling_std(df, window=20) rolling_std=rolling_std[(rolling_std.sum(axis=1)!=0)] u_bollinger_bnd,l_bollinger_bnd=util.get_bollinger_bands(rolling_mean, rolling_std) param_dict={'Rolling mean':rolling_mean,'Rolling SD': rolling_std,'Bollinger Bands':(u_bollinger_bnd,l_bollinger_bnd),'Daily returns':daily_returns} colors=viridis(len(daily_returns.columns)); TOOLS='pan,wheel_zoom,box_zoom,reset,save,box_select,crosshair' for param in param_dict.keys(): hover=HoverTool( tooltips=[ ("Metric",'$y') ] ) p = figure(width=1200, height=500, x_axis_type="datetime",tools=[TOOLS,hover]) if param =="Bollinger Bands": upper_band=param_dict[param][0] lower_band=param_dict[param][1] for (i,sym) in enumerate(upper_band): p.line(upper_band.index,upper_band[sym],legend=sym,color=colors[i],line_width=2) for (i,sym) in enumerate(lower_band): p.line(lower_band.index,lower_band[sym],legend=sym,color=colors[i],line_width=2,line_dash='dashed') else: for (i,sym) in enumerate(param_dict[param]): p.line(param_dict[param].index,param_dict[param][sym],legend=sym,color=colors[i],line_width=2) p.title.text = param p.legend.location = "top_left" p.xaxis.axis_label = 'Date' p.yaxis.axis_label = param tab=Panel(child=p,title=param) list_plots.append(tab) if len(list_plots)!=0: script_el_param, div_el_param=components(Tabs(tabs=list_plots)) else: script_el_param='' div_el_param='' return script_el_param, div_el_param