def __init__(self, feed_dict, full_analysis): # initiate common vatiables self.returns = feed_dict['input'] self.covar = self.returns.cov() del feed_dict['input'] columns = [] for col in self.returns.columns: columns.append(col.split('_')[0]) self.bins = oc.get_bins(self.returns) # save parameters in case replication is desired self.Parameters = deepcopy(feed_dict) self.Parameters.update({'num_bins': deepcopy(self.bins)}) objective, features, constraints, simulations, methods, tol, maxiter, disp = oc.unfeeder( feed_dict) if objective['target']: self.target = objective['target'] else: self.target = 0.0 # features if 'benchmark' in features: self.benchmark = features['benchmark'] else: raise AttributeError('Beta requires a benchmark.') self.periodicity = _embed_periodicity(features['periodicity']) if methods == 'arithmetic': self.mean_returns = self.returns.mean() * self.periodicity if methods == 'geometric': self.mean_returns = _geomean(self.returns, self.periodicity) if 'margin_int_rate' in features: self.margin_rate = features['margin_int_rate'] else: self.margin_rate = 0 # constraints if 'min_weights' in constraints: self.weight_bounds = tuple( zip(constraints['min_weights'], constraints['max_weights'])) else: self.weight_bounds = None constraints = self.get_constraints(constraints) # optimal portfolio self.guess = np.random.normal(0, 0.5, len(self.mean_returns)) / 10 self.OptiParam = minimize(self.optimize_beta, self.guess, method='SLSQP', bounds=self.weight_bounds, tol=tol, constraints=constraints, options={ 'maxiter': maxiter, 'disp': disp }) if not self.OptiParam['success']: print('Warning!', self.OptiParam['message']) tanw = self.OptiParam['x'] tanww = pd.DataFrame(tanw).T tanww.columns = columns tanr = self.weighted_annual_return(tanw) margin = np.sum(np.abs(tanw)) - 1 tanra = tanr - self.margin_rate * margin tans = self.weighted_annual_stddev(tanw) tanss = self.weighted_return(tanw) beta = self.benchmark.cov(tanss) / self.benchmark.std() self.Optimal = { 'Weights': tanww, 'Return': tanr, 'AdjReturn': tanra, 'StdDev': tans, 'Beta': beta, 'Series': tanss } # Beta frontier if full_analysis == True: analyze = np.linspace(max(self.Optimal['Return'] / 4, 0.0001), min(self.Optimal['Return'] * 4, 0.5), simulations) efficent = [] eff = [] for ret in analyze: self.ret = ret e = self.optimize_betas(ret, constraints, tol, maxiter, disp) we = e['x'] wew = pd.DataFrame(we).T wew.columns = columns margin = np.sum(np.abs(we)) - 1 re = self.weighted_annual_return( we) - self.margin_rate * margin se = self.weighted_annual_stddev(we) be = self.benchmark.cov( self.weighted_return(we)) / self.benchmark.std() efficent.append({ 'Weights': wew, 'Returns': re, 'StdDevs': se, 'Beta': be }) eff.append(e) self.EfficentParam = eff self.EfficentFrontier = efficent # Constituents self.ConstituentBeta = self.get_betas(columns)
def __init__(self, feed_dict, full_analysis): # initiate common vatiables self.returns = feed_dict['input'] self.covar = self.returns.cov() del feed_dict['input'] columns = [] for col in self.returns.columns: columns.append(col.split('_')[0]) self.bins = oc.get_bins(self.returns) # save parameters in case replication is desired self.Parameters = deepcopy(feed_dict) self.Parameters.update({'num_bins': deepcopy(self.bins)}) objective, features, constraints, simulations, methods, tol, maxiter, disp = oc.unfeeder( feed_dict) if objective['target']: self.dist_type = objective['target'] else: self.dist_type = False # features if 'benchmark' in features: self.benchmark = features['benchmark'] else: raise AttributeError('SharpeEdge requires a benchmark.') self.periodicity = _embed_periodicity(features['periodicity']) if methods == 'arithmetic': self.mean_returns = self.returns.mean() * self.periodicity self.benchmark_mean = self.benchmark.mean() * self.periodicity if methods == 'geometric': self.mean_returns = _geomean(self.returns, self.periodicity) self.benchmark_mean = _geomean(self.benchmark, self.periodicity) ## Benchmark AE param self.benchmark_stdev = self.benchmark.std() * np.sqrt(self.periodicity) if self.dist_type == False: if self.bins < 100: dist_list = [st.triang, st.dgamma, st.levy_stable, st.gennorm] else: dist_list = [st.norm, st.johnsonsu, st.t] dist = oc.get_distribution(self.benchmark, self.bins, dist_list) loc, scale, args = oc.unpack_dist_params(dist[1]) self.benchmark_p_loss = dist[0].cdf(0, loc=loc, scale=scale, *args) self.benchmark_p_profit = 1 - self.benchmark_p_loss self.benchmark_sharpeedge = ( self.benchmark_mean * self.benchmark_p_profit) / ( self.benchmark_stdev * self.benchmark_p_loss) self.benchmark_dist = (dist[0].name, dist[1], dist[2]) else: self.benchmark_p_loss = st.percentileofscore(self.benchmark, 0) / 100 self.benchmark_p_profit = 1 - self.benchmark_p_loss self.benchmark_sharpeedge = ( self.benchmark_mean * self.benchmark_p_profit) / ( self.benchmark_stdev * self.benchmark_p_loss) if 'margin_int_rate' in features: self.margin_rate = features['margin_int_rate'] else: self.margin_rate = 0 if 'rf' in features: self.rf = features['rf'] else: self.rf = 0 # constraints if 'min_weights' in constraints: self.weight_bounds = tuple( zip(constraints['min_weights'], constraints['max_weights'])) else: self.weight_bounds = None constraints = self.get_constraints(constraints) # optimal portfolio self.guess = np.random.normal(0, 0.5, len(self.mean_returns)) / 10 self.OptiParam = minimize(self.optimize_ae, self.guess, method='SLSQP', bounds=self.weight_bounds, tol=tol, constraints=constraints, options={ 'maxiter': maxiter, 'disp': disp }) if not self.OptiParam['success']: print('Warning!', self.OptiParam['message']) tanw = self.OptiParam['x'] tanww = pd.DataFrame(tanw).T tanww.columns = columns tanr = self.weighted_annual_return(tanw) margin = np.sum(np.abs(tanw)) - 1 tanra = tanr - self.margin_rate * margin tans = self.weighted_annual_stddev(tanw) if self.dist_type == False: ae, a, pp, pl, dist = self.optimize_ae(tanw, True) self.Optimal = { 'Weights': tanww, 'Return': tanr, 'AdjReturn': tanra, 'StdDev': tans, 'SharpeEdge': ae, 'Sharpe': (tanra - self.rf) / tans, 'Alpha': a, 'Prob_Profit': pp, 'Prob_Loss': pl, 'Distribution': dist, 'Series': self.weighted_return(tanw) } else: ae, a, pp, pl = self.optimize_var(tanw, True) self.Optimal = { 'Weights': tanww, 'Return': tanr, 'AdjReturn': tanra, 'StdDev': tans, 'SharpeEdge': ae, 'Sharpe': (tanra - self.rf) / tans, 'Alpha': a, 'Prob_Profit': pp, 'Prob_Loss': pl, 'Series': self.weighted_return(tanw) } # AlphaEdge frontier if full_analysis == True: analyze = np.linspace(max(self.Optimal['Return'] / 4, 0.0001), min(self.Optimal['Return'] * 4, 0.5), simulations) efficent = [] eff = [] for ret in analyze: self.ret = ret e = self.optimize_vars(ret, constraints, tol, maxiter, disp) we = e['x'] wew = pd.DataFrame(we).T wew.columns = columns margin = np.sum(np.abs(we)) - 1 re = self.weighted_annual_return( we) - self.margin_rate * margin se = self.weighted_annual_stddev(we) efficent.append({ 'Weights': wew, 'Returns': re, 'StdDevs': se, 'SharpeEdge': -self.optimize_ae(we) }) eff.append(e) self.EfficentParam = eff self.EfficentFrontier = efficent # Constituents self.ConstituentSharpeEdge = self.get_aes(columns)