Exemple #1
0
def main():
    for br, p in zip(BENCH_R, PORTFOLIOS):
        print(p)
        df = pd.DataFrame()
        # 计算组合分年收益率与最大回撤
        returns = get_portfolio_return(p)
        returns_year = returns.resample('Y').apply(
            lambda x: empyrical.cum_returns_final(x))
        mdd_year = returns.resample('Y').apply(
            lambda x: empyrical.max_drawdown(x))
        # 扣除申购赎回费
        filename = '%s/%s.xlsx' % (DATA_DIR, p)
        cost = pd.read_excel(filename, sheet_name='费率', index_col=0)
        df['组合收益率'] = returns_year - cost['申购费'] - cost['赎回费']
        df['组合最大回撤'] = mdd_year
        # 计算基准分年收益率与最大回撤
        returns = get_bench_return(br[0], br[1])
        returns_year = returns.resample('Y').apply(
            lambda x: empyrical.cum_returns_final(x))
        mdd_year = returns.resample('Y').apply(
            lambda x: empyrical.max_drawdown(x))
        df['基准收益率'] = returns_year
        df['基准最大回撤'] = mdd_year
        df['超额收益率'] = df['组合收益率'] - df['基准收益率']
        # 保存到结果
        filename = '%s/%s分年统计.xlsx' % (DATA_DIR, p)
        df.to_excel(filename)
Exemple #2
0
def create_perf_attrib_stats(perf_attrib, risk_exposures):
    """
    Takes perf attribution data over a period of time and computes annualized
    multifactor alpha, multifactor sharpe, risk exposures.
    """
    summary = OrderedDict()
    specific_returns = perf_attrib['specific_returns']
    common_returns = perf_attrib['common_returns']

    summary['Annual multi-factor alpha'] =\
        ep.annual_return(specific_returns)

    summary['Multi-factor sharpe'] =\
        ep.sharpe_ratio(specific_returns)

    # empty line between common/specific/total returns
    summary[' '] = ' '
    summary['Cumulative specific returns'] =\
        ep.cum_returns_final(specific_returns)
    summary['Cumulative common returns'] =\
        ep.cum_returns_final(common_returns)
    summary['Total returns'] =\
        ep.cum_returns_final(perf_attrib['total_returns'])

    summary = pd.Series(summary)

    risk_exposure_summary = risk_exposures.sum(axis='rows')
    return summary, risk_exposure_summary
Exemple #3
0
 def test_total(self):
     res_a = empyrical.cum_returns_final(ret['a'])
     res_b = empyrical.cum_returns_final(ret['b'])
     res_c = empyrical.cum_returns_final(ret['c'])
     assert isclose(ret['a'].vbt.returns.total(), res_a)
     pd.testing.assert_series_equal(
         ret.vbt.returns.total(),
         pd.Series([res_a, res_b, res_c], index=ret.columns))
Exemple #4
0
 def test_total_return(self):
     res_a = empyrical.cum_returns_final(ret['a'])
     res_b = empyrical.cum_returns_final(ret['b'])
     res_c = empyrical.cum_returns_final(ret['c'])
     assert isclose(ret['a'].vbt.returns.total(), res_a)
     pd.testing.assert_series_equal(
         ret.vbt.returns.total(),
         pd.Series([res_a, res_b, res_c],
                   index=ret.columns).rename('total_return'))
     pd.testing.assert_series_equal(
         ret.vbt.returns.rolling_total(ret.shape[0], minp=1).iloc[-1],
         pd.Series([res_a, res_b, res_c],
                   index=ret.columns).rename(ret.index[-1]))
Exemple #5
0
def Analysis(results):
    """
    技术指标分析器
    :param results:
    {
    'returns':[0.1,0.1,0.1],
    'benchmark':[0.1,0.1,0.1]
    'trades':[[2020.01.01 01:00:00,'BUY',6234.10,1]]
    }
    :return:
    """
    res = pnl_res(results["returns"])
    bres = pnl_res(results["benchmark"])
    return_ratio = empyrical.cum_returns_final(res)
    annual_return_ratio = empyrical.annual_return(res)
    sharp_ratio = empyrical.sharpe_ratio(res, 0.035 / 252)
    return_volatility = empyrical.annual_volatility(res)
    max_drawdown = empyrical.max_drawdown(res)
    alpha, beta = empyrical.alpha_beta_aligned(res, bres)
    pls, wr = pls_ws(results["trades"])
    return {
        'pls': pls,
        'wr': wr,
        'return_ratio': return_ratio,
        'annual_return_ratio': annual_return_ratio,
        'beta': beta,
        'alpha': alpha,
        'sharp_ratio': sharp_ratio,
        'return_volatility': return_volatility,
        'max_drawdown': max_drawdown,
    }
Exemple #6
0
def create_perf_attrib_stats(perf_attrib, risk_exposures):
    """
    Takes perf attribution data over a period of time and computes annualized
    multifactor alpha, multifactor sharpe, risk exposures.
    """
    summary = OrderedDict()
    total_returns = perf_attrib['total_returns']
    specific_returns = perf_attrib['specific_returns']
    common_returns = perf_attrib['common_returns']

    summary['Annualized Specific Return'] =\
        ep.annual_return(specific_returns, annualization=APPROX_BDAYS_PER_YEAR)
    summary['Annualized Common Return'] =\
        ep.annual_return(common_returns, annualization=APPROX_BDAYS_PER_YEAR)
    summary['Annualized Total Return'] =\
        ep.annual_return(total_returns, annualization=APPROX_BDAYS_PER_YEAR)

    summary['Specific Sharpe Ratio'] =\
        ep.sharpe_ratio(specific_returns, annualization=APPROX_BDAYS_PER_YEAR)

    summary['Cumulative Specific Return'] =\
        ep.cum_returns_final(specific_returns)
    summary['Cumulative Common Return'] =\
        ep.cum_returns_final(common_returns)
    summary['Total Returns'] =\
        ep.cum_returns_final(total_returns)

    summary = pd.Series(summary, name='')

    annualized_returns_by_factor = [
        ep.annual_return(perf_attrib[c], annualization=APPROX_BDAYS_PER_YEAR)
        for c in risk_exposures.columns
    ]
    cumulative_returns_by_factor = [
        ep.cum_returns_final(perf_attrib[c]) for c in risk_exposures.columns
    ]

    risk_exposure_summary = pd.DataFrame(
        data=OrderedDict([
            ('Average Risk Factor Exposure', risk_exposures.mean(axis='rows')),
            ('Annualized Return', annualized_returns_by_factor),
            ('Cumulative Return', cumulative_returns_by_factor),
        ]),
        index=risk_exposures.columns,
    )

    return summary, risk_exposure_summary
Exemple #7
0
def create_perf_attrib_stats(perf_attrib, risk_exposures):
    """
    Takes perf attribution data over a period of time and computes annualized
    multifactor alpha, multifactor sharpe, risk exposures.
    """
    summary = OrderedDict()
    total_returns = perf_attrib['total_returns']
    specific_returns = perf_attrib['specific_returns']
    common_returns = perf_attrib['common_returns']

    summary['Annualized Specific Return'] =\
        ep.annual_return(specific_returns)
    summary['Annualized Common Return'] =\
        ep.annual_return(common_returns)
    summary['Annualized Total Return'] =\
        ep.annual_return(total_returns)

    summary['Specific Sharpe Ratio'] =\
        ep.sharpe_ratio(specific_returns)

    summary['Cumulative Specific Return'] =\
        ep.cum_returns_final(specific_returns)
    summary['Cumulative Common Return'] =\
        ep.cum_returns_final(common_returns)
    summary['Total Returns'] =\
        ep.cum_returns_final(total_returns)

    summary = pd.Series(summary, name='')

    annualized_returns_by_factor = [ep.annual_return(perf_attrib[c])
                                    for c in risk_exposures.columns]
    cumulative_returns_by_factor = [ep.cum_returns_final(perf_attrib[c])
                                    for c in risk_exposures.columns]

    risk_exposure_summary = pd.DataFrame(
        data=OrderedDict([
            (
                'Average Risk Factor Exposure',
                risk_exposures.mean(axis='rows')
            ),
            ('Annualized Return', annualized_returns_by_factor),
            ('Cumulative Return', cumulative_returns_by_factor),
        ]),
        index=risk_exposures.columns,
    )

    return summary, risk_exposure_summary
def get_performance_summary(returns):
    stats = {'annualized_returns': ep.annual_return(returns),
             'cumulative_returns': ep.cum_returns_final(returns),
             'annual_volatility': ep.annual_volatility(returns),
             'sharpe_ratio': ep.sharpe_ratio(returns),
             'sortino_ratio': ep.sortino_ratio(returns),
             'max_drawdown': ep.max_drawdown(returns)}
    return pd.Series(stats)
Exemple #9
0
def create_perf_attrib_stats(perf_attrib, risk_exposures):
    """
    Takes perf attribution data over a period of time and computes annualized
    multifactor alpha, multifactor sharpe, risk exposures.
    """
    summary = OrderedDict()
    total_returns = perf_attrib['total_returns']
    specific_returns = perf_attrib['specific_returns']
    common_returns = perf_attrib['common_returns']

    summary['年化特定收益率'] =\
        ep.annual_return(specific_returns)
    summary['年化共同收益率'] =\
        ep.annual_return(common_returns)
    summary['年化总收益率'] =\
        ep.annual_return(total_returns)

    summary['特定夏普比率'] =\
        ep.sharpe_ratio(specific_returns)

    summary['累积特定收益率'] =\
        ep.cum_returns_final(specific_returns)
    summary['累积共同收益率'] =\
        ep.cum_returns_final(common_returns)
    summary['总收益率'] =\
        ep.cum_returns_final(total_returns)

    summary = pd.Series(summary, name='')

    annualized_returns_by_factor = [
        ep.annual_return(perf_attrib[c]) for c in risk_exposures.columns
    ]
    cumulative_returns_by_factor = [
        ep.cum_returns_final(perf_attrib[c]) for c in risk_exposures.columns
    ]

    risk_exposure_summary = pd.DataFrame(
        data=OrderedDict([
            ('因子平均风险敞口', risk_exposures.mean(axis='rows')),
            ('年化收益率', annualized_returns_by_factor),
            ('累积收益率', cumulative_returns_by_factor),
        ]),
        index=risk_exposures.columns,
    )

    return summary, risk_exposure_summary
def create_perf_attrib_stats(perf_attrib, risk_exposures):
    """
    Takes perf attribution data over a period of time and computes annualized
    multifactor alpha, multifactor sharpe, risk exposures.
    """
    summary = OrderedDict()
    total_returns = perf_attrib["total_returns"]
    specific_returns = perf_attrib["specific_returns"]
    common_returns = perf_attrib["common_returns"]

    summary["Annualized Specific Return"] = ep.annual_return(specific_returns)
    summary["Annualized Common Return"] = ep.annual_return(common_returns)
    summary["Annualized Total Return"] = ep.annual_return(total_returns)

    summary["Specific Sharpe Ratio"] = ep.sharpe_ratio(specific_returns)

    summary["Cumulative Specific Return"] = ep.cum_returns_final(
        specific_returns
    )
    summary["Cumulative Common Return"] = ep.cum_returns_final(common_returns)
    summary["Total Returns"] = ep.cum_returns_final(total_returns)

    summary = pd.Series(summary, name="")

    annualized_returns_by_factor = [
        ep.annual_return(perf_attrib[c]) for c in risk_exposures.columns
    ]
    cumulative_returns_by_factor = [
        ep.cum_returns_final(perf_attrib[c]) for c in risk_exposures.columns
    ]

    risk_exposure_summary = pd.DataFrame(
        data=OrderedDict(
            [
                (
                    "Average Risk Factor Exposure",
                    risk_exposures.mean(axis="rows"),
                ),
                ("Annualized Return", annualized_returns_by_factor),
                ("Cumulative Return", cumulative_returns_by_factor),
            ]
        ),
        index=risk_exposures.columns,
    )

    return summary, risk_exposure_summary
Exemple #11
0
def get_all_comp_daily_return():
    '''
    得到所有基金公司日收益率
    '''
    all_df = utils.get_all_funds()
    comps = all_df['mgrcomp'].unique()
    dic = {}
    for c in comps:
        print c
        df = all_df[all_df['mgrcomp'] == c]
        df = df[df['investtype'].str.contains(u'股')]
        daily_return = get_comp_daily_return(c, df['wind_code'].tolist())
        if daily_return is None:
            continue
        dic[c] = daily_return
        print empyrical.cum_returns_final(
            daily_return[daily_return.index >= '2019-01-01'])
    df = pd.DataFrame(dic)
    df.to_excel('%s/comp_ret.xlsx' % (const.FOF_DIR), encoding='utf-8')
Exemple #12
0
def _get_backtest_performance_metrics(ret, benchmark_ret):
    metrics = {
        'alpha': empyrical.alpha(ret, benchmark_ret),
        'beta': empyrical.beta(ret, benchmark_ret),
        'return': empyrical.cum_returns_final(ret),
        'cagr': empyrical.cagr(ret),
        'sharpe': empyrical.sharpe_ratio(ret),
        'max_drawdown': empyrical.max_drawdown(ret),
        'var': empyrical.value_at_risk(ret),
        'volatility': empyrical.annual_volatility(ret),
    }

    return metrics
Exemple #13
0
def create_perf_attrib_stats(perf_attrib):
    """
    Takes perf attribution data over a period of time and computes annualized
    multifactor alpha, multifactor sharpe, risk exposures.
    """
    summary = {}
    specific_returns = perf_attrib['specific_returns']
    common_returns = perf_attrib['common_returns']

    summary['Annual multi-factor alpha'] =\
        ep.annual_return(specific_returns)

    summary['Multi-factor sharpe'] =\
        ep.sharpe_ratio(specific_returns)

    summary['Cumulative specific returns'] =\
        ep.cum_returns_final(specific_returns)
    summary['Cumulative common returns'] =\
        ep.cum_returns_final(common_returns)
    summary['Total returns'] =\
        ep.cum_returns_final(perf_attrib['total_returns'])

    summary = pd.Series(summary)
    return summary
Exemple #14
0
def performance(ret, benchmark, rf=0.04):
    #计算评价指标
    import empyrical
    max_drawdown = empyrical.max_drawdown(ret)
    total_return = empyrical.cum_returns_final(ret)
    annual_return = empyrical.annual_return(ret)

    sharpe_ratio = empyrical.sharpe_ratio(ret,
                                          risk_free=((1 + rf)**(1 / 252) - 1))
    alpha, beta = empyrical.alpha_beta(ret, benchmark)
    return {
        'total_return': total_return,
        'annual_return': annual_return,
        'max_drawdown': max_drawdown,
        'sharpe_ratio': sharpe_ratio,
        'alpha': alpha,
        'beta': beta
    }
Exemple #15
0
def get_performance_summary(returns):
    '''
    Calculate selected performance evaluation metrics using provided returns.
    
    Parameters
    ------------
    returns : pd.Series
        Series of returns we want to evaluate

    Returns
    -----------
    stats : pd.Series
        The calculated performance metrics
        
    '''
    stats = {
        'annualized_returns': ep.annual_return(returns),
        'cumulative_returns': ep.cum_returns_final(returns),
        'annual_volatility': ep.annual_volatility(returns),
        'sharpe_ratio': ep.sharpe_ratio(returns),
        'sortino_ratio': ep.sortino_ratio(returns),
        'max_drawdown': ep.max_drawdown(returns)
    }
    return pd.Series(stats)
Exemple #16
0
    def test_perf_attrib_regression(self):

        positions = pd.read_csv('pyfolio/tests/test_data/positions.csv',
                                index_col=0,
                                parse_dates=True)

        positions.columns = [
            int(col) if col != 'cash' else col for col in positions.columns
        ]

        returns = pd.read_csv('pyfolio/tests/test_data/returns.csv',
                              index_col=0,
                              parse_dates=True,
                              header=None,
                              squeeze=True)

        factor_loadings = pd.read_csv(
            'pyfolio/tests/test_data/factor_loadings.csv',
            index_col=[0, 1],
            parse_dates=True)

        factor_returns = pd.read_csv(
            'pyfolio/tests/test_data/factor_returns.csv',
            index_col=0,
            parse_dates=True)

        residuals = pd.read_csv('pyfolio/tests/test_data/residuals.csv',
                                index_col=0,
                                parse_dates=True)

        residuals.columns = [int(col) for col in residuals.columns]

        intercepts = pd.read_csv('pyfolio/tests/test_data/intercepts.csv',
                                 index_col=0,
                                 header=None,
                                 squeeze=True)

        risk_exposures_portfolio, perf_attrib_output = perf_attrib(
            returns,
            positions,
            factor_returns,
            factor_loadings,
        )

        specific_returns = perf_attrib_output['specific_returns']
        common_returns = perf_attrib_output['common_returns']
        combined_returns = specific_returns + common_returns

        # since all returns are factor returns, common returns should be
        # equivalent to total returns, and specific returns should be 0
        pd.util.testing.assert_series_equal(returns,
                                            common_returns,
                                            check_names=False)

        self.assertTrue(np.isclose(specific_returns, 0).all())

        # specific and common returns combined should equal total returns
        pd.util.testing.assert_series_equal(returns,
                                            combined_returns,
                                            check_names=False)

        # check that residuals + intercepts = specific returns
        self.assertTrue(np.isclose((residuals + intercepts), 0).all())

        # check that exposure * factor returns = common returns
        expected_common_returns = risk_exposures_portfolio.multiply(
            factor_returns, axis='rows').sum(axis='columns')

        pd.util.testing.assert_series_equal(expected_common_returns,
                                            common_returns,
                                            check_names=False)

        # since factor loadings are ones, portfolio risk exposures
        # should be ones
        pd.util.testing.assert_frame_equal(
            risk_exposures_portfolio,
            pd.DataFrame(np.ones_like(risk_exposures_portfolio),
                         index=risk_exposures_portfolio.index,
                         columns=risk_exposures_portfolio.columns))

        perf_attrib_summary, exposures_summary = create_perf_attrib_stats(
            perf_attrib_output, risk_exposures_portfolio)

        self.assertEqual(ep.annual_return(specific_returns),
                         perf_attrib_summary['Annualized Specific Return'])

        self.assertEqual(ep.annual_return(common_returns),
                         perf_attrib_summary['Annualized Common Return'])

        self.assertEqual(ep.annual_return(combined_returns),
                         perf_attrib_summary['Annualized Total Return'])

        self.assertEqual(ep.sharpe_ratio(specific_returns),
                         perf_attrib_summary['Specific Sharpe Ratio'])

        self.assertEqual(ep.cum_returns_final(specific_returns),
                         perf_attrib_summary['Cumulative Specific Return'])

        self.assertEqual(ep.cum_returns_final(common_returns),
                         perf_attrib_summary['Cumulative Common Return'])

        self.assertEqual(ep.cum_returns_final(combined_returns),
                         perf_attrib_summary['Total Returns'])

        avg_factor_exposure = risk_exposures_portfolio.mean().rename(
            'Average Risk Factor Exposure')
        pd.util.testing.assert_series_equal(
            avg_factor_exposure,
            exposures_summary['Average Risk Factor Exposure'])

        cumulative_returns_by_factor = pd.Series(
            [
                ep.cum_returns_final(perf_attrib_output[c])
                for c in risk_exposures_portfolio.columns
            ],
            name='Cumulative Return',
            index=risk_exposures_portfolio.columns)

        pd.util.testing.assert_series_equal(
            cumulative_returns_by_factor,
            exposures_summary['Cumulative Return'])

        annualized_returns_by_factor = pd.Series(
            [
                ep.annual_return(perf_attrib_output[c])
                for c in risk_exposures_portfolio.columns
            ],
            name='Annualized Return',
            index=risk_exposures_portfolio.columns)

        pd.util.testing.assert_series_equal(
            annualized_returns_by_factor,
            exposures_summary['Annualized Return'])
Exemple #17
0
    def create_summary_tearsheet(self, x_performance, y_performance):
        """
        Create a tear sheet of summary shortfall stats in a table.

        Parameters
        ----------
        x_performance : AggregateDailyPerformance, required
            simulated or benchmark aggregate performance results

        y_performance : AggregateDailyPerformance, required
            actual aggregate performance results

        Returns
        -------
        None

        """
        stats = []

        stats.append([
            "Start Date",
            [
                x_performance.returns.index.min().date().isoformat(),
                y_performance.returns.index.min().date().isoformat()
            ]
        ])
        stats.append([
            "End Date",
            [
                x_performance.returns.index.max().date().isoformat(),
                y_performance.returns.index.max().date().isoformat()
            ]
        ])

        stats.append([
            'Total Months',
            [
                round((x_performance.returns.index.max() -
                       x_performance.returns.index.min()) /
                      pd.Timedelta(1, 'M')),
                round(
                    (y_performance.returns.index.max() -
                     y_performance.returns.index.min()) / pd.Timedelta(1, 'M'))
            ]
        ])

        stats.append([" Risk and Returns", ["", ""]])
        stats.append([
            "CAGR",
            [
                "{0}%".format(round(x_performance.cagr * 100, 1)),
                "{0}%".format(round(y_performance.cagr * 100, 1))
            ]
        ])
        stats.append([
            "Sharpe Ratio",
            ['%.2f' % x_performance.sharpe,
             '%.2f' % y_performance.sharpe]
        ])
        stats.append([
            "Max Drawdown",
            [
                "{0}%".format(round(x_performance.max_drawdown * 100, 1)),
                "{0}%".format(round(y_performance.max_drawdown * 100, 1))
            ]
        ])
        stats.append([
            "Cumulative Return",
            [
                "{0}%".format(
                    round(
                        ep.cum_returns_final(x_performance.returns) * 100, 1)),
                "{0}%".format(
                    round(
                        ep.cum_returns_final(y_performance.returns) * 100, 1))
            ]
        ])
        if x_performance.commissions is not None and y_performance.commissions is not None:
            stats.append([
                "Cumulative Commissions",
                [
                    "{0}%".format(
                        round(
                            ep.cum_returns_final(x_performance.commissions) *
                            100, 1)),
                    "{0}%".format(
                        round(
                            ep.cum_returns_final(y_performance.commissions) *
                            100, 1))
                ]
            ])
        stats.append([
            "Annual Volatility",
            [
                "{0}%".format(
                    round(
                        ep.annual_volatility(x_performance.returns) * 100, 1)),
                "{0}%".format(
                    round(
                        ep.annual_volatility(y_performance.returns) * 100, 1))
            ]
        ])
        stats.append([
            "Sortino Ratio",
            [
                '%.2f' % ep.sortino_ratio(x_performance.returns),
                '%.2f' % ep.sortino_ratio(y_performance.returns)
            ]
        ])
        stats.append([
            "Calmar Ratio",
            [
                '%.2f' % ep.calmar_ratio(x_performance.returns),
                '%.2f' % ep.calmar_ratio(y_performance.returns)
            ]
        ])
        stats.append([
            "Skew",
            [
                '%.2f' % scipy.stats.skew(x_performance.returns),
                '%.2f' % scipy.stats.skew(y_performance.returns)
            ]
        ])
        stats.append([
            "Kurtosis",
            [
                '%.2f' % scipy.stats.kurtosis(x_performance.returns),
                '%.2f' % scipy.stats.kurtosis(y_performance.returns)
            ]
        ])

        stats.append([" Positions and Exposure", ["", ""]])

        if x_performance.abs_exposures is not None and y_performance.abs_exposures is not None:
            stats.append([
                "Absolute Exposure (percentage of capital)",
                [
                    "{0}%".format(
                        round(x_performance.abs_exposures.mean() * 100, 1)),
                    "{0}%".format(
                        round(y_performance.abs_exposures.mean() * 100, 1))
                ]
            ])

        if x_performance.net_exposures is not None and y_performance.net_exposures is not None:
            stats.append([
                "Net Exposure (percentage of capital)",
                [
                    "{0}%".format(
                        round(x_performance.net_exposures.mean() * 100, 1)),
                    "{0}%".format(
                        round(y_performance.net_exposures.mean() * 100, 1))
                ]
            ])

        if x_performance.total_holdings is not None and y_performance.total_holdings is not None:
            stats.append([
                "Average Daily Holdings",
                [
                    round(x_performance.total_holdings.mean()),
                    round(y_performance.total_holdings.mean())
                ]
            ])

        if x_performance.turnover is not None and y_performance.turnover is not None:
            stats.append([
                "Average Daily Turnover (percentage of capital)",
                [
                    "{0}%".format(round(x_performance.turnover.mean() * 100,
                                        1)),
                    "{0}%".format(round(y_performance.turnover.mean() * 100,
                                        1))
                ]
            ])

        if x_performance.abs_exposures is not None and y_performance.abs_exposures is not None:
            stats.append([
                "Normalized CAGR (CAGR/Absolute Exposure)",
                [
                    "{0}%".format(
                        round((x_performance.cagr /
                               x_performance.abs_exposures.mean()) * 100, 1)),
                    "{0}%".format(
                        round((y_performance.cagr /
                               y_performance.abs_exposures.mean()) * 100, 1))
                ]
            ])

        with sns.axes_style("white", {'axes.linewidth': 0}):

            fig = plt.figure("Performance Summary", figsize=(6, 6))

            axis = fig.add_subplot(111)
            axis.get_xaxis().set_visible(False)
            axis.get_yaxis().set_visible(False)

            headings, values = zip(*stats)

            table = axis.table(cellText=values,
                               rowLabels=headings,
                               colLabels=[self.x_label, self.y_label],
                               loc="center")
            for (row, col), cell in table.get_celld().items():
                txt = cell.get_text().get_text()
                if row == 0 or txt.startswith(" "):
                    cell.set_text_props(fontproperties=FontProperties(
                        weight='bold'))

            table.scale(1, 2)
            table.set_fontsize("large")
            fig.tight_layout()
Exemple #18
0
def return_calculation(returns):
    """
    Calculates cumulative returns of a portfolio without any annualization
    """
    ending_value = cum_returns_final(returns, starting_value=1)
    return ending_value - 1
Exemple #19
0
    def create_summary_tearsheet(self, performance, agg_performance=None):
        """
        Create a tear sheet of summary performance stats in a table.

        Parameters
        ----------
        performance : DailyPerformance, required
            a DailyPerformance instance

        agg_performance : AggregateDailyPerformance, optional
            an AggregateDailyPerformance instance. Constructed from performance
            if not provided.

        Returns
        -------
        None

        Examples
        --------
        >>> from moonchart import DailyPerformance, Tearsheet
        >>> perf = DailyPerformance.from_moonshot_csv("backtest_results.csv")
        >>> t = Tearsheet()
        >>> t.create_summary_tearsheet(perf)
        """
        if agg_performance is None:
            agg_performance = AggregateDailyPerformance(performance)

        stats = []

        if agg_performance.pnl is not None:
            stats.append(["PNL", round(agg_performance.pnl.sum(), 2)])
        if agg_performance.commission_amounts is not None:
            stats.append([
                "Commissions",
                round(agg_performance.commission_amounts.sum(), 2)
            ])

        stats.append([
            "Start Date",
            agg_performance.returns.index.min().date().isoformat()
        ])
        stats.append([
            "End Date",
            agg_performance.returns.index.max().date().isoformat()
        ])

        stats.append([
            'Total Months',
            round((agg_performance.returns.index.max() -
                   agg_performance.returns.index.min()) / pd.Timedelta(1, 'M'))
        ])

        stats.append(["", " Risk and Returns"])
        stats.append(
            ["CAGR", "{0}%".format(round(agg_performance.cagr * 100, 1))])
        stats.append(["Sharpe Ratio", '%.2f' % agg_performance.sharpe])
        stats.append([
            "Max Drawdown",
            "{0}%".format(round(agg_performance.max_drawdown * 100, 1))
        ])
        stats.append([
            "Cumulative Return", "{0}%".format(
                round(ep.cum_returns_final(agg_performance.returns) * 100, 1))
        ])
        stats.append([
            "Annual Volatility", "{0}%".format(
                round(ep.annual_volatility(agg_performance.returns) * 100, 1))
        ])
        stats.append([
            "Sortino Ratio",
            '%.2f' % ep.sortino_ratio(agg_performance.returns)
        ])
        stats.append([
            "Calmar Ratio",
            '%.2f' % ep.calmar_ratio(agg_performance.returns)
        ])
        stats.append(
            ["Skew",
             '%.2f' % scipy.stats.skew(agg_performance.returns)])
        stats.append([
            "Kurtosis",
            '%.2f' % scipy.stats.kurtosis(agg_performance.returns)
        ])

        if any([
                field is not None for field in (agg_performance.abs_exposures,
                                                agg_performance.net_exposures,
                                                agg_performance.total_holdings,
                                                agg_performance.turnover)
        ]):
            stats.append(["", " Positions and Exposure"])

        if agg_performance.abs_exposures is not None:
            avg_abs_exposures = agg_performance.abs_exposures.mean()
            stats.append([
                "Absolute Exposure (percentage of capital)",
                "{0}%".format(round(avg_abs_exposures * 100, 1))
            ])

        if agg_performance.net_exposures is not None:
            avg_net_exposures = agg_performance.net_exposures.mean()
            stats.append([
                "Net Exposure (percentage of capital)",
                "{0}%".format(round(avg_net_exposures * 100, 1))
            ])

        if agg_performance.total_holdings is not None:
            avg_daily_holdings = agg_performance.total_holdings.mean()
            stats.append(["Average Daily Holdings", round(avg_daily_holdings)])

        if agg_performance.turnover is not None:
            avg_daily_turnover = agg_performance.turnover.mean()
            stats.append([
                "Average Daily Turnover (percentage of capital)",
                "{0}%".format(round(avg_daily_turnover * 100, 1))
            ])

        if agg_performance.abs_exposures is not None:
            norm_cagr = agg_performance.cagr / avg_abs_exposures
            stats.append([
                "Normalized CAGR (CAGR/Absolute Exposure)",
                "{0}%".format(round(norm_cagr * 100, 1))
            ])

        with sns.axes_style("white", {'axes.linewidth': 0}):

            fig = plt.figure("Performance Summary", figsize=(6, 6))

            axis = fig.add_subplot(111)
            axis.get_xaxis().set_visible(False)
            axis.get_yaxis().set_visible(False)

            headings, values = zip(*stats)

            table = axis.table(cellText=[[v] for v in values],
                               rowLabels=headings,
                               colLabels=["Performance Summary"],
                               loc="center")
            for (row, col), cell in table.get_celld().items():
                txt = cell.get_text().get_text()
                if row == 0 or txt.startswith(" "):
                    cell.set_text_props(fontproperties=FontProperties(
                        weight='bold'))

            table.scale(1, 2)
            table.set_fontsize("large")
            fig.tight_layout()
Exemple #20
0
 def total_return(self, daily_change):
     perc = empyrical.cum_returns_final(daily_change) * 100
     return round(perc, 0)
    def test_perf_attrib_regression(self):

        positions = pd.read_csv('pyfolio/tests/test_data/positions.csv',
                                index_col=0, parse_dates=True)

        positions.columns = [int(col) if col != 'cash' else col
                             for col in positions.columns]

        returns = pd.read_csv('pyfolio/tests/test_data/returns.csv',
                              index_col=0, parse_dates=True,
                              header=None, squeeze=True)

        factor_loadings = pd.read_csv(
            'pyfolio/tests/test_data/factor_loadings.csv',
            index_col=[0, 1], parse_dates=True
        )

        factor_returns = pd.read_csv(
            'pyfolio/tests/test_data/factor_returns.csv',
            index_col=0, parse_dates=True
        )

        residuals = pd.read_csv('pyfolio/tests/test_data/residuals.csv',
                                index_col=0, parse_dates=True)

        residuals.columns = [int(col) for col in residuals.columns]

        intercepts = pd.read_csv('pyfolio/tests/test_data/intercepts.csv',
                                 index_col=0, header=None, squeeze=True)

        risk_exposures_portfolio, perf_attrib_output = perf_attrib(
            returns,
            positions,
            factor_returns,
            factor_loadings,
        )

        specific_returns = perf_attrib_output['specific_returns']
        common_returns = perf_attrib_output['common_returns']
        combined_returns = specific_returns + common_returns

        # since all returns are factor returns, common returns should be
        # equivalent to total returns, and specific returns should be 0
        pd.util.testing.assert_series_equal(returns,
                                            common_returns,
                                            check_names=False)

        self.assertTrue(np.isclose(specific_returns, 0).all())

        # specific and common returns combined should equal total returns
        pd.util.testing.assert_series_equal(returns,
                                            combined_returns,
                                            check_names=False)

        # check that residuals + intercepts = specific returns
        self.assertTrue(np.isclose((residuals + intercepts), 0).all())

        # check that exposure * factor returns = common returns
        expected_common_returns = risk_exposures_portfolio.multiply(
            factor_returns, axis='rows'
        ).sum(axis='columns')

        pd.util.testing.assert_series_equal(expected_common_returns,
                                            common_returns,
                                            check_names=False)

        # since factor loadings are ones, portfolio risk exposures
        # should be ones
        pd.util.testing.assert_frame_equal(
            risk_exposures_portfolio,
            pd.DataFrame(np.ones_like(risk_exposures_portfolio),
                         index=risk_exposures_portfolio.index,
                         columns=risk_exposures_portfolio.columns)
        )

        perf_attrib_summary, exposures_summary = create_perf_attrib_stats(
            perf_attrib_output, risk_exposures_portfolio
        )

        self.assertEqual(ep.annual_return(specific_returns),
                         perf_attrib_summary['Annualized Specific Return'])

        self.assertEqual(ep.annual_return(common_returns),
                         perf_attrib_summary['Annualized Common Return'])

        self.assertEqual(ep.annual_return(combined_returns),
                         perf_attrib_summary['Annualized Total Return'])

        self.assertEqual(ep.sharpe_ratio(specific_returns),
                         perf_attrib_summary['Specific Sharpe Ratio'])

        self.assertEqual(ep.cum_returns_final(specific_returns),
                         perf_attrib_summary['Cumulative Specific Return'])

        self.assertEqual(ep.cum_returns_final(common_returns),
                         perf_attrib_summary['Cumulative Common Return'])

        self.assertEqual(ep.cum_returns_final(combined_returns),
                         perf_attrib_summary['Total Returns'])

        avg_factor_exposure = risk_exposures_portfolio.mean().rename(
            'Average Risk Factor Exposure'
        )
        pd.util.testing.assert_series_equal(
            avg_factor_exposure,
            exposures_summary['Average Risk Factor Exposure']
        )

        cumulative_returns_by_factor = pd.Series(
            [ep.cum_returns_final(perf_attrib_output[c])
             for c in risk_exposures_portfolio.columns],
            name='Cumulative Return',
            index=risk_exposures_portfolio.columns
        )

        pd.util.testing.assert_series_equal(
            cumulative_returns_by_factor,
            exposures_summary['Cumulative Return']
        )

        annualized_returns_by_factor = pd.Series(
            [ep.annual_return(perf_attrib_output[c])
             for c in risk_exposures_portfolio.columns],
            name='Annualized Return',
            index=risk_exposures_portfolio.columns
        )

        pd.util.testing.assert_series_equal(
            annualized_returns_by_factor,
            exposures_summary['Annualized Return']
        )
Exemple #22
0
def cumulative_returns(portfolio_daily_returns):
    return ep.cum_returns_final(portfolio_daily_returns)