Beispiel #1
0
    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)