Пример #1
0
def get_period_rets(returns, period='monthly'):
    """
    将原始的日度收益率序列压缩成指定周期的收益率序列,周期可选参数包括:周度、月度、年度
    
    Parameters
    ----------
    returns : pd.Series
              原始日度收益率序列
              
    period : str, optional
              周期("weekly","monthly","yearly")
              
    Returns
    ----------
    pd.Series or pd.DataFrame
        period_rets
    """
    if period=="weekly":
        weekly_ret_table = ep.aggregate_returns(returns, 'weekly')
        weekly_ret_table = weekly_ret_table.unstack().round(3)
        return weekly_ret_table
    elif period=="monthly":
        monthly_ret_table = ep.aggregate_returns(returns, 'monthly')
        monthly_ret_table = monthly_ret_table.unstack().round(3) 
        return monthly_ret_table
    else:
        ann_ret_series = pd.DataFrame(ep.aggregate_returns(returns,'yearly'),
                                      columns=['Annual Return'])
        return ann_ret_series
Пример #2
0
def plot_return_quantiles(returns, live_start_date=None, **kwargs):
    """
    Creates a box plot of daily, weekly, and monthly return
    distributions.

    Parameters
    ----------
    returns : pd.Series
        Daily returns of the strategy, noncumulative.
         - See full explanation in tears.create_full_tear_sheet.
    live_start_date : datetime, optional
        The point in time when the strategy began live trading, after
        its backtest period.
    **kwargs, optional
        Passed to seaborn plotting function.

    Returns
    -------
    ax : matplotlib.Axes
        The axes that were plotted on.
    """

    is_returns = returns if live_start_date is None \
        else returns.loc[returns.index < live_start_date]
    is_weekly = ep.aggregate_returns(is_returns, 'weekly')
    is_monthly = ep.aggregate_returns(is_returns, 'monthly')

    if live_start_date is not None:
        oos_returns = returns.loc[returns.index >= live_start_date]
        oos_weekly = ep.aggregate_returns(oos_returns, 'weekly')
        oos_monthly = ep.aggregate_returns(oos_returns, 'monthly')
        return [is_returns, is_weekly, is_monthly, oos_returns, oos_weekly, oos_monthly]

    return {"is_returns": is_returns, "is_weekly": is_weekly, "is_monthly": is_monthly}
Пример #3
0
def compute_stats(portfolio, benchmark):
    '''Compute statistics for the current portfolio'''
    stats = {}

    grp_by_year = portfolio.groupby(lambda x: x.year)
    stats['1yr_highest'] = grp_by_year.max().iloc[-1]
    stats['1yr_lowest'] = grp_by_year.min().iloc[-1]

    portfolio_return = simple_returns(portfolio)
    # benchmark_return = simple_returns(benchmark)
    
    stats['wtd_return'] = aggregate_returns(portfolio_return, 'weekly').iloc[-1]
    stats['mtd_return'] = aggregate_returns(portfolio_return, 'monthly').iloc[-1]
    stats['ytd_return'] = aggregate_returns(portfolio_return, 'yearly').iloc[-1]
    stats['max_drawdown'] = max_drawdown(portfolio_return)
    # stats['annual_return'] = annual_return(portfolio_return, period='daily')
    stats['annual_volatility'] = annual_volatility(portfolio_return, period='daily', alpha=2.0)
    # stats['calmar_ratio'] = calmar_ratio(portfolio_return, period='daily')
    # stats['omega_ratio'] = omega_ratio(portfolio_return, risk_free=0.0)
    stats['sharpe_ratio_1yr'] = sharpe_ratio(portfolio_return, risk_free=0.0, period='daily')
    # stats['alpha'], stats['beta'] = alpha_beta(portfolio_return, benchmark_return, 
    #                                            risk_free=0.0, period='daily')
    stats['tail_ratio'] = tail_ratio(portfolio_return)
    # stats['capture_ratio'] = capture(portfolio_return, benchmark_return, period='daily')

    return stats
Пример #4
0
def holding_period_map(returns):
    """
    Display holding period returns in a table.
    length of returns should be 30 or less, otherwise the output
    will be jumbled
    """

    year = em.aggregate_returns(returns.pct_change(), 'yearly')
    returns = pd.DataFrame(columns=range(1, len(year)+1), index=year.index)

    year_start = 0

    table = "<table class='table table-hover table-condensed table-striped'>"
    table += "<tr><th>Years</th>"

    for i in range(len(year)):
        table += "<th>{}</th>".format(i+1)
    table += "</tr>"

    for the_year, value in year.iteritems(): # Iterates years
        table += "<tr><th>{}</th>".format(the_year) # New table row

        for years_held in (range(1, len(year)+1)): # Iterates years held
            if years_held <= len(year[year_start:year_start + years_held]):
                ret = em.annual_return(year[year_start:year_start + years_held], 'yearly' )
                table += "<td>{:.0f}</td>".format(ret * 100)
        table += "</tr>"
        year_start+=1
    display(HTML(table))
Пример #5
0
def portfolioAnalysis(return_data):
    non_cum_return = getNonCumReturn(return_data)
    #计算年化收益:
    annual_return = empyrical.annual_return(non_cum_return, period='daily')
    #计算年化波动率:
    annual_volatility = empyrical.annual_volatility(non_cum_return,
                                                    period='daily')
    #计算最大回撤
    max_drawdown = empyrical.max_drawdown(non_cum_return)
    #计算夏普比率:
    sharpe_ratio = empyrical.sharpe_ratio(
        non_cum_return,
        risk_free=math.pow(1 + 0.03, 1 / 250) - 1,
        period='daily')
    #分年统计
    aggr_returns = empyrical.aggregate_returns(non_cum_return,
                                               convert_to="yearly")

    print("年化收益:%f" % (annual_return))
    print("年化波动率:%f" % (annual_volatility))
    print("最大回撤:%f" % (max_drawdown))
    print("夏普比率:%f" % (sharpe_ratio))
    print("分年统计收益率:")
    print(aggr_returns)
    data = [annual_return, annual_volatility, max_drawdown, sharpe_ratio]
    return pd.Series(data, index=["年化收益率", "年化波动率", "最大回撤", "夏普比率"])
Пример #6
0
 def _agg_ret(factor):
     target_returns = factor.get_data(start_date=start_date,
                                      end_date=end_date).unstack().iloc[:,
                                                                        0]
     agg_target_ret = empyrical.aggregate_returns(target_returns,
                                                  convert_to)
     return agg_target_ret
Пример #7
0
 def test_aggregate_returns(self, returns, convert_to, expected):
     returns = empyrical.aggregate_returns(returns,
                                           convert_to).values.tolist()
     for i, v in enumerate(returns):
         assert_almost_equal(
             v,
             expected[i],
             DECIMAL_PLACES)
    def caculate_performance(self):
        # to daily
        try:
            rets = self._equity.resample('D').last().dropna().pct_change()
            if self._benchmark is not None:
                b_rets = self._df_positions['benchmark'].resample('D').last().dropna().pct_change()
        except:
            rets = self._equity.pct_change()
            if self._benchmark is not None:
                b_rets = self._df_positions['benchmark'].pct_change()

        rets = rets[1:]
        if self._benchmark is not None:
            b_rets = b_rets[1:]
        perf_stats_all = None
        #rets.index = rets.index.tz_localize('UTC')
        #self._df_positions.index = self._df_positions.index.tz_localize('UTC')
        if not self._df_trades.index.empty:
            if self._benchmark is not None:
                # self._df_trades.index = self._df_trades.index.tz_localize('UTC')
                # pf.create_full_tear_sheet(rets, self._df_positions, self._df_trades)
                rets.index = pd.to_datetime(rets.index)
                b_rets.index = rets.index
                # pf.create_returns_tear_sheet(rets,benchmark_rets=b_rets)
                perf_stats_strat = pf.timeseries.perf_stats(rets)
                perf_stats_benchmark = pf.timeseries.perf_stats(b_rets)
                perf_stats_all = pd.concat([perf_stats_strat, perf_stats_benchmark], axis=1)
                perf_stats_all.columns = ['Strategy', 'Benchmark']
            else:
                # self._df_trades.index = self._df_trades.index.tz_localize('UTC')
                # pf.create_full_tear_sheet(rets, self._df_positions, self._df_trades)
                rets.index = pd.to_datetime(rets.index)
                # pf.create_returns_tear_sheet(rets,benchmark_rets=rets)
                perf_stats_all = pf.timeseries.perf_stats(rets)
                perf_stats_all = perf_stats_all.to_frame(name='Strategy')

        drawdown_df = pf.timeseries.gen_drawdown_table(rets, top=5)
        monthly_ret_table = ep.aggregate_returns(rets, 'monthly')
        monthly_ret_table = monthly_ret_table.unstack().round(3)
        ann_ret_df = pd.DataFrame(ep.aggregate_returns(rets, 'yearly'))
        ann_ret_df = ann_ret_df.unstack().round(3)
        return perf_stats_all, drawdown_df, monthly_ret_table, ann_ret_df
Пример #9
0
    def return_quantiles(self, returns, live_start_date=None):
        """
        Daily, weekly, and monthly return series

        Parameters
        ----------
        returns : pd.Series
            Daily returns of the strategy, noncumulative.
             - See full explanation in tears.create_full_tear_sheet.
        live_start_date : datetime, optional
            The point in time when the strategy began live trading, after
            its backtest period.

        Returns
        -------
        Daily, weekly, and monthly return series
        """
        is_returns = returns if live_start_date is None \
            else returns.loc[returns.index < live_start_date]
        is_weekly = empyrical.aggregate_returns(is_returns, 'weekly')
        is_monthly = empyrical.aggregate_returns(is_returns, 'monthly')

        return_quantiles = {
            "is": {
                'Daily': is_returns,
                'Weekly': is_weekly,
                'Monthly': is_monthly
            }
        }
        if live_start_date is not None:
            oos_returns = returns.loc[returns.index >= live_start_date]
            oos_weekly = empyrical.aggregate_returns(oos_returns, 'weekly')
            oos_monthly = empyrical.aggregate_returns(oos_returns, 'monthly')
            return_quantiles["oos"] = {
                'Daily': oos_returns,
                'Weekly': oos_weekly,
                'Monthly': oos_monthly
            }

        return return_quantiles
Пример #10
0
def holding_period_map(dbal):
    """
    Display holding period returns in a table.

    This shows what your annualized return would have been, had you
    started this strategy at the start of a given year, as shown in
    the leftmost column, and held it for a certain number of years.
    Length of returns should be 30 or less, otherwise the output
    will be jumbled.

    Parameters
    ----------
    dbal : pd.Series
        The daily closing balance indexed by date.

    Returns
    -------
    None

    Examples
    --------
    >>> table = holding_period_map(dbal['close'])
    >>> display(HTML(table))
    Years    1   2   3   4   5   6   7   8
    2013    30  20  13  12  13  10  12  12
    2014    11   5   7  10   6  10   9
    ...
    2020     8
    """
    year = em.aggregate_returns(dbal.pct_change(), 'yearly')
    year_start = 0

    table = "<table class='table table-hover table-condensed table-striped'>"
    table += "<tr><th>Years</th>"

    for i in range(len(year)):
        table += "<th>{}</th>".format(i + 1)
    table += "</tr>"

    for the_year, value in year.iteritems():  # Iterates years
        table += "<tr><th>{}</th>".format(the_year)  # New table row

        for years_held in (range(1, len(year) + 1)):  # Iterates years held
            if years_held <= len(year[year_start:year_start + years_held]):
                ret = em.annual_return(
                    year[year_start:year_start + years_held], 'yearly')
                table += "<td>{:.0f}</td>".format(ret * 100)
        table += "</tr>"
        year_start += 1
    display(HTML(table))
Пример #11
0
def calc_performance_from_value_history(daily_values: pd.Series) -> dict:
    daily_returns = daily_values.pct_change()
    final_returns = daily_values.iloc[-1] / 100 - 1

    monthly_returns = empyrical.aggregate_returns(daily_returns, "monthly")
    yearly_returns = empyrical.aggregate_returns(daily_returns, "yearly")
    performance_summary = performance_utils.get_performance_summary(
        daily_returns, final_returns)

    annual_std = performance_utils.get_annual_std(daily_returns)
    annual_summary = pd.concat([yearly_returns, annual_std], axis=1)
    annual_summary.columns = ["수익률", "변동성"]

    cumulative_returns = performance_utils.convert_values_to_cumulative_returns(
        daily_values)
    drawdown = performance_utils.get_draw_down(cumulative_returns)

    return {
        "monthly_returns": monthly_returns,
        "yearly_returns": yearly_returns,
        "performance_summary": performance_summary,
        "annual_summary": annual_summary,
        "drawdown": drawdown
    }
Пример #12
0
def compare_strategy_with_benchmark(strategy, benchmark_list: list):
    strategy_performance = strategy.get_result()
    print(strategy_performance["yearly_returns"])

    all_columns = [strategy.name]
    for benchmark in benchmark_list:
        all_columns.append(benchmark.name)

    yearly_returns = strategy_performance["yearly_returns"]
    for benchmark in benchmark_list:
        benchmark_yearly_returns = empyrical.aggregate_returns(benchmark.get_daily_return(), "yearly")
        yearly_returns = pd.concat([yearly_returns, benchmark_yearly_returns], axis=1)

    yearly_returns.columns = all_columns

    print(yearly_returns)
Пример #13
0
    def monthly_returns(self, returns):
        """
        Returns by month.

        Parameters
        ----------
        returns : pd.Series
            Daily returns of the strategy, noncumulative.
             - See full explanation in pyfolio.tears.create_full_tear_sheet.

        Returns
        -------
        monthly_ret_table

        """
        monthly_ret_table = empyrical.aggregate_returns(returns, 'monthly')
        monthly_ret_table = monthly_ret_table.unstack().round(3).fillna(0)
        return monthly_ret_table
Пример #14
0
    def yearly_returns(self, returns):
        """
        Returns by year.

        Parameters
        ----------
        returns : pd.Series
            Daily returns of the strategy, noncumulative.
             - See full explanation in pyfolio.tears.create_full_tear_sheet.

        Returns
        -------
        Returns by year
        """
        ann_ret_df = pd.DataFrame(
            empyrical.aggregate_returns(returns, 'yearly'))
        ann_ret_df.columns = ["annual_returns"]
        return ann_ret_df
Пример #15
0
def aggregate_returns(returns, convert_to):
    """
    Aggregates returns by week, month, or year.

    Parameters
    ----------
    returns : pd.Series
       Daily returns of the strategy, noncumulative.
        - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.
    convert_to : str
        Can be 'weekly', 'monthly', or 'yearly'.

    Returns
    -------
    pd.Series
        Aggregated returns.
    """

    return ep.aggregate_returns(returns, convert_to=convert_to)
Пример #16
0
def aggregate_returns(returns, convert_to):
    """
    Aggregates returns by week, month, or year.

    Parameters
    ----------
    returns : pd.Series
       Daily returns of the strategy, noncumulative.
        - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.
    convert_to : str
        Can be 'weekly', 'monthly', or 'yearly'.

    Returns
    -------
    pd.Series
        Aggregated returns.
    """

    return empyrical.aggregate_returns(returns, convert_to=convert_to)
Пример #17
0
def plot_annual_returns(returns, ax=None, **kwargs):
    """
    Plots a bar graph of returns by year.
    
    Parameters
    ----------
    returns : pd.DataFrame
        Daily returns of the strategy, noncumulative.
         - See full explanation in tears.create_full_tear_sheet.
    ax : matplotlib.Axes, optional
        Axes upon which to plot.
    **kwargs, optional
        Passed to plotting function.
    
    Returns
    -------
    ax : matplotlib.Axes
        The axes that were plotted on.
    """
    plt.style.use("seaborn")

    if ax is None:
        ax = plt.gca()

    ann_ret_df = pd.DataFrame(ep.aggregate_returns(returns, 'yearly'))

    ax.axvline(100 * ann_ret_df.values.mean(),
               color='steelblue',
               linestyle='--',
               lw=4,
               alpha=0.7)
    (100 * ann_ret_df.sort_index(ascending=False)).plot(ax=ax,
                                                        kind='barh',
                                                        alpha=0.70,
                                                        **kwargs)
    ax.axvline(0.0, color='black', linestyle='-', lw=3)

    ax.set_ylabel('Year')
    ax.set_xlabel('Returns')
    ax.set_title("Annual returns")
    ax.legend(['Mean'], frameon=True, framealpha=0.5)
    return ax
Пример #18
0
def plot_monthly_returns_dist(returns, **kwargs):
    """
    Plots a distribution of monthly returns.

    Parameters
    ----------
    returns : pd.Series
        Daily returns of the strategy, noncumulative.
         - See full explanation in tears.create_full_tear_sheet.
    **kwargs, optional
        Passed to plotting function.

    Returns
    -------
    ax : matplotlib.Axes
        The axes that were plotted on.
    """

    monthly_ret_table = ep.aggregate_returns(returns, 'monthly')
    return monthly_ret_table
Пример #19
0
def plot_monthly_returns_heatmap(returns, ax=None, **kwargs):
    """
    Plots a heatmap of returns by month.

    Parameters
    ----------
    returns : pd.Series
        Daily returns of the strategy, noncumulative.
         - See full explanation in tears.create_full_tear_sheet.
    ax : matplotlib.Axes, optional
        Axes upon which to plot.
    **kwargs, optional
        Passed to seaborn plotting function.

    Returns
    -------
    ax : matplotlib.Axes
        The axes that were plotted on.
    """

    if ax is None:
        ax = plt.gca()

    monthly_ret_table = ep.aggregate_returns(returns, 'monthly')
    monthly_ret_table = monthly_ret_table.unstack().round(3)

    sns.heatmap(
        monthly_ret_table.fillna(0) *
        100.0,
        annot=True,
        annot_kws={"size": 9},
        alpha=1.0,
        center=0.0,
        cbar=False,
        cmap=matplotlib.cm.RdYlGn,
        ax=ax, **kwargs)
    ax.set_ylabel('Year')
    ax.set_xlabel('Month')
    ax.set_title("Monthly returns (%)")
    return monthly_ret_table
Пример #20
0
def ReturnStats(returns):
    """
    Return Statistics of Portfolio Return & Risk.

    Parameters
    ----------
    returns : pd.DataFrame
        Daily returns of the strategy, noncumulative.

    Returns
    -------
    stats : pd.DataFrame
        Annual Arithmetic mean, Geometric mean, Standard deviation, Sharpe Ratio, Win Ratio, Max Drawdown.

    """

    temp = ep.aggregate_returns(returns, 'yearly')
    temp_ret = temp
    temp_std = temp

    dd = pd.DataFrame(drawdown(returns))

    Ann_ret_Arith = temp_ret.sum() / len(temp_ret)
    Ann_ret_CAGR = (1 + temp_ret).prod()**(1 / len(temp_ret)) - 1
    Ann_std = temp_std.std()
    Ann_Sharpe = (Ann_ret_CAGR - 0.05) / Ann_std
    Win_Ratio = (returns > 0).sum() / ((returns > 0).sum() +
                                       (returns < 0).sum())
    MDD = dd.min()

    stats = pd.DataFrame(
        [Ann_ret_Arith, Ann_ret_CAGR, Ann_std, Ann_Sharpe, Win_Ratio, MDD],
        index=[
            'Ann_ret (Arith)', 'Ann_ret (CAGR)', 'Ann_std', 'Ann_sharpe',
            'Win_Ratio', 'MDD'
        ])
    stats.columns = returns.columns
    stats = round(stats, 4)
    return stats
Пример #21
0
def value_at_risk(returns, period=None, sigma=2.0):
    """
    Get value at risk (VaR).

    Parameters
    ----------
    returns : pd.Series
        Daily returns of the strategy, noncumulative.
         - See full explanation in tears.create_full_tear_sheet.
    period : str, optional
        Period over which to calculate VaR. Set to 'weekly',
        'monthly', or 'yearly', otherwise defaults to period of
        returns (typically daily).
    sigma : float, optional
        Standard deviations of VaR, default 2.
    """
    if period is not None:
        returns_agg = empyrical.aggregate_returns(returns, period)
    else:
        returns_agg = returns.copy()

    value_at_risk = returns_agg.mean() - sigma * returns_agg.std()
    return value_at_risk
Пример #22
0
def plot_annual_returns(returns, **kwargs):
    """
    Plots a bar graph of returns by year.

    Parameters
    ----------
    returns : pd.Series
        Daily returns of the strategy, noncumulative.
         - See full explanation in tears.create_full_tear_sheet.
    **kwargs, optional
        Passed to plotting function.

    Returns
    -------
    ax : matplotlib.Axes
        The axes that were plotted on.
    """
    ann_ret_df = pd.DataFrame(
        ep.aggregate_returns(
            returns,
            'yearly'))

    return ann_ret_df
Пример #23
0
def value_at_risk(returns, period=None, sigma=2.0):
    """
    Get value at risk (VaR).

    Parameters
    ----------
    returns : pd.Series
        Daily returns of the strategy, noncumulative.
         - See full explanation in tears.create_full_tear_sheet.
    period : str, optional
        Period over which to calculate VaR. Set to 'weekly',
        'monthly', or 'yearly', otherwise defaults to period of
        returns (typically daily).
    sigma : float, optional
        Standard deviations of VaR, default 2.
    """
    if period is not None:
        returns_agg = ep.aggregate_returns(returns, period)
    else:
        returns_agg = returns.copy()

    value_at_risk = returns_agg.mean() - sigma * returns_agg.std()
    return value_at_risk
Пример #24
0
def plot_interactive_monthly_heatmap(returns: pd.Series) -> Chart:
    """
    Plots a heatmap of returns by month.
    """
    monthly_ret_table = ep.aggregate_returns(returns, 'monthly')
    monthly_ret_table = monthly_ret_table.unstack().round(3)

    monthly_ret_table = np.round(monthly_ret_table * 100, 2)
    lim = lim = max(np.max(np.abs(monthly_ret_table)))

    y_axis = [date(1000, i, 1).strftime('%b') for i in range(1, 13)]
    x_axis = [str(y) for y in monthly_ret_table.index.tolist()]
    data = data = [[x_axis[i], y_axis[j], monthly_ret_table.values[i][j]]
                   for i in range(monthly_ret_table.shape[0])
                   for j in range(monthly_ret_table.shape[1])]

    heatmap = HeatMap("Monthly Returns")
    heatmap.add(
        "Monthly Returns",
        x_axis,
        y_axis,
        data,
        is_visualmap=True,
        is_datazoom_show=True,
        datazoom_orient='horizontal',
        datazoom_range=[0, 100],
        visual_range=[-lim, lim],
        visual_text_color="#000",
        visual_range_color=['#D73027', '#FFFFBF', '#1A9641'],
        visual_orient="vertical",
        is_toolbox_show=False,
        is_label_show=True,
        label_pos="inside",
        label_text_color="black",
        tooltip_formatter="{c}%"
    )
    return heatmap
Пример #25
0
 def return_each_month(self, daily_change):
     result = empyrical.aggregate_returns(daily_change, 'monthly') * 100
     return result
Пример #26
0
plt.show()
plt.close()

current_max = np.maximum.accumulate(sp500['Cumulative Returns'])
underwater = -100 * ((current_max - sp500['Cumulative Returns']) / current_max)
g = underwater.plot(kind='area', color='tomato', alpha=0.7)
plt.gca().set_yticklabels(
    ['{:.0f}%'.format(x) for x in plt.gca().get_yticks()])
plt.grid(True)
plt.ylabel('Drawdown')
plt.title('Underwater Plot of the S&P500 index')
plt.xlabel('')
plt.savefig('SP500_underwater.pdf')
plt.show()

annual_returns = pd.DataFrame(ep.aggregate_returns(sp500['Returns'], 'yearly'))
ax = plt.gca()
plt.gca().set_yticklabels(
    ['{:.0f}%'.format(x) for x in plt.gca().get_yticks()])
ax.axhline(100 * annual_returns.values.mean(),
           color='gray',
           linestyle='--',
           lw=2,
           alpha=0.7)
(100 * annual_returns.sort_index(ascending=True)).plot(ax=ax,
                                                       kind='bar',
                                                       alpha=1)
ax.axhline(0.0, color='black', linestyle='-', lw=3)
plt.gca().set_yticklabels(
    ['{:.0f}%'.format(x) for x in plt.gca().get_yticks()])
ax.set_xlabel('')
Пример #27
0
            bm_ret.index = pd.to_datetime(bm_ret.index)
            # remove tzinfo
            returns.index = returns.index.tz_localize(None)
            bm_ret = bm_ret[returns.index]
            bm_ret.name = 'benchmark'

        perf_stats_strat = pf.timeseries.perf_stats(returns)
        perf_stats_all = perf_stats_strat
        if benchmark:
            perf_stats_bm = pf.timeseries.perf_stats(bm_ret)
            perf_stats_all = pd.concat([perf_stats_strat, perf_stats_bm],
                                       axis=1)
            perf_stats_all.columns = ['Strategy', 'Benchmark']

        drawdown_table = pf.timeseries.gen_drawdown_table(returns, 5)
        monthly_ret_table = ep.aggregate_returns(returns, 'monthly')
        monthly_ret_table = monthly_ret_table.unstack().round(3)
        ann_ret_df = pd.DataFrame(ep.aggregate_returns(returns, 'yearly'))
        ann_ret_df = ann_ret_df.unstack().round(3)
        print('-------------- PERFORMANCE ----------------')
        print(perf_stats_all)
        print('-------------- DRAWDOWN ----------------')
        print(drawdown_table)
        print('-------------- MONTHLY RETURN ----------------')
        print(monthly_ret_table)
        print('-------------- ANNUAL RETURN ----------------')
        print(ann_ret_df)

        pf.create_full_tear_sheet(
            returns,
            benchmark_rets=bm_ret if benchmark else None,
Пример #28
0
def monthly_returns_map(dbal):
    """
    Display per month and per year returns in a table.

    Parameters
    ----------
    dbal : pd.Series
        The daily closing balance indexed by date.

    Returns
    -------
    None

    Examples
    --------
    >>> monthly_returns_map(dbal['close'])
    Year    Jan     Feb     Mar     Apr     May     Jun     Jul ... Year
    1990   -8.5     0.9     2.4    -2.7     9.2    -0.9    -0.5    -8.2
    1991    4.2     6.7     2.2     0.0     3.9    -4.8     4.5    26.3
    """
    monthly_data = em.aggregate_returns(dbal.pct_change(), 'monthly')
    yearly_data = em.aggregate_returns(dbal.pct_change(), 'yearly')

    table_header = """
    <table class='table table-hover table-condensed table-striped'>
    <thead>
    <tr>
    <th style="text-align:right">Year</th>
    <th style="text-align:right">Jan</th>
    <th style="text-align:right">Feb</th>
    <th style="text-align:right">Mar</th>
    <th style="text-align:right">Apr</th>
    <th style="text-align:right">May</th>
    <th style="text-align:right">Jun</th>
    <th style="text-align:right">Jul</th>
    <th style="text-align:right">Aug</th>
    <th style="text-align:right">Sep</th>
    <th style="text-align:right">Oct</th>
    <th style="text-align:right">Nov</th>
    <th style="text-align:right">Dec</th>
    <th style="text-align:right">Year</th>
    </tr>
    </thead>
    <tbody>
    <tr>"""

    first_year = True
    first_month = True
    year = 0
    month = 0
    year_count = 0
    table = ''
    for m, val in monthly_data.iteritems():
        year = m[0]
        month = m[1]

        if first_month:
            if year_count % 15 == 0:
                table += table_header
            table += "<td align='right'><b>{}</b></td>\n".format(year)
            first_month = False

        # Pad empty months for first year if sim doesn't start in Jan.
        if first_year:
            first_year = False
            if month > 1:
                for _ in range(1, month):
                    table += "<td align='right'>-</td>\n"

        table += "<td align='right'>{:.1f}</td>\n".format(val * 100)

        # Check for dec and add yearly.
        if month == 12:
            table += "<td align='right'><b>{:.1f}</b></td>\n".format(
                yearly_data[year] * 100)
            table += '</tr>\n <tr> \n'
            first_month = True
            year_count += 1

    # Add padding for empty months and last year's value.
    if month != 12:
        for i in range(month + 1, 13):
            table += "<td align='right'>-</td>\n"
            if i == 12:
                table += "<td align='right'><b>{:.1f}</b></td>\n".format(
                    yearly_data[year] * 100)
                table += '</tr>\n <tr> \n'
    table += '</tr>\n </tbody> \n </table>'
    display(HTML(table))
Пример #29
0
def monthly_returns_map(returns):
    """ Display per month and per year returns in a table """

    monthly_data = em.aggregate_returns(returns.pct_change(),'monthly')
    yearly_data = em.aggregate_returns(returns.pct_change(),'yearly')

    table_header = """
    <table class='table table-hover table-condensed table-striped'>
    <thead>
    <tr>
    <th style="text-align:right">Year</th>
    <th style="text-align:right">Jan</th>
    <th style="text-align:right">Feb</th>
    <th style="text-align:right">Mar</th>
    <th style="text-align:right">Apr</th>
    <th style="text-align:right">May</th>
    <th style="text-align:right">Jun</th>
    <th style="text-align:right">Jul</th>
    <th style="text-align:right">Aug</th>
    <th style="text-align:right">Sep</th>
    <th style="text-align:right">Oct</th>
    <th style="text-align:right">Nov</th>
    <th style="text-align:right">Dec</th>
    <th style="text-align:right">Year</th>
    </tr>
    </thead>
    <tbody>
    <tr>"""

    first_year = True
    first_month = True
    year = 0
    month = 0
    year_count = 0
    table = ''
    for m, val in monthly_data.iteritems():
        year = m[0]
        month = m[1]

        if first_month:
            if year_count % 15 == 0:
                table += table_header
            table += "<td align='right'><b>{}</b></td>\n".format(year)
            first_month = False

        # pad empty months for first year if sim doesn't start in January
        if first_year:
            first_year = False
            if month > 1:
                for _ in range(1, month):
                    table += "<td align='right'>-</td>\n"

        table += "<td align='right'>{:.1f}</td>\n".format(val * 100)

        # check for dec, add yearly
        if month == 12:
            table += "<td align='right'><b>{:.1f}</b></td>\n".format(
                yearly_data[year] * 100)
            table += '</tr>\n <tr> \n'
            first_month = True
            year_count += 1

    # add padding for empty months and last year's value
    if month != 12:
        for i in range(month+1, 13):
            table += "<td align='right'>-</td>\n"
            if i == 12:
                table += "<td align='right'><b>{:.1f}</b></td>\n".format(
                    yearly_data[year] * 100)
                table += '</tr>\n <tr> \n'
    table += '</tr>\n </tbody> \n </table>'
    display(HTML(table))
Пример #30
0
underwater = -100 * ((current_max - frp_cum_prod) / current_max)
g = underwater.plot(kind='area', color='tomato', alpha=0.7)
plt.gca().set_yticklabels(
    ['{:.0f}%'.format(x) for x in plt.gca().get_yticks()])
plt.grid(True)
plt.ylabel('Drawdown')
plt.legend('')
plt.xlim(dt.datetime(2005, 1, 1), dt.datetime(2020, 1, 1))
plt.title('Underwater Plot of FRP portfolio w/relaxation')
plt.xlabel('')
plt.savefig('Implementation/FRP_underwater.pdf')
plt.show()

import empyrical as ep

annual_returns = pd.DataFrame(ep.aggregate_returns(frp_daily, 'yearly'))
ax = plt.gca()
plt.gca().set_yticklabels(
    ['{:.0f}%'.format(x) for x in plt.gca().get_yticks()])
ax.axhline(100 * annual_returns.values.mean(),
           color='gray',
           linestyle='--',
           lw=2,
           alpha=0.7)
(100 * annual_returns.sort_index(ascending=True)).plot(ax=ax,
                                                       kind='bar',
                                                       alpha=1)
ax.axhline(0.0, color='black', linestyle='-', lw=3)
plt.gca().set_yticklabels(
    ['{:.0f}%'.format(x) for x in plt.gca().get_yticks()])
ax.set_xlabel('')
Пример #31
0
def get_monthly_heatmap(returns,
                        cmap,
                        font_size=10,
                        yr_from=None,
                        yr_to=None,
                        cnvrt='monthly',
                        width=600,
                        plt_type='iplot',
                        filename=None,
                        colors=['white', 'black'],
                        online=False,
                        show_scale=False,
                        height=600,
                        vmin=0,
                        vmax=255):
    """F: to plot heatmap of monthly returns:

    params:

        returns: str, daily or monthly returns, ideally a series with datetime index
        cmap: (optional)str, eg 'RdYlGn'
        font_size: (optional) font_size of annotations
        yr_from: (optional) Heatmap year from
        yr_to: (optional) Heatmap year to
        cnvrt = (optional) str, convert returns to
        """
    cscale = matplotlib_to_plotly(cmap, vmin=vmin, vmax=vmax)
    ##    cscale = plt_cscale(cmap)
    if yr_to is None:
        yr_to = returns.index[-1].year
    if yr_from is None:
        yr_from = returns.index[0].year
    grid = empyrical.aggregate_returns(
        returns, convert_to='monthly').unstack().fillna(0).round(4) * 100
    grid = grid.loc[yr_from:yr_to, :]
    z = grid.as_matrix()
    y = grid.index.values.tolist()
    x = grid.columns.values.tolist()

    z = grid.values.tolist()
    z.reverse()
    z_text = np.round(z, 3)

    fighm = ff.create_annotated_heatmap(z,
                                        x=x,
                                        y=y[::-1],
                                        annotation_text=z_text,
                                        colorscale=cscale,
                                        reversescale=True,
                                        hoverinfo="y+z",
                                        showscale=show_scale,
                                        font_colors=colors)
    for i in range(len(fighm.layout.annotations)):
        fighm.layout.annotations[i].font.size = font_size

    fighm.layout.title = 'Heatmap for {0} from {1} - {2}'.format(
        returns.name, y[0], y[-1])
    fighm['layout']['yaxis']['title'] = 'Years'
    fighm['layout']['yaxis']['dtick'] = 3
    fighm['layout']['yaxis']['tick0'] = 2
    fighm['layout']['width'] = width
    fighm['layout']['height'] = height
    # fighm.layout.xaxis.title = 'Months'
    if online == False:
        if plt_type == 'iplot':
            return iplot(fighm,
                         show_link=False,
                         image_width=width,
                         image_height=900)
        elif plt_type == 'plot':
            return plot(fighm,
                        show_link=False,
                        image_width=width,
                        image_height=900,
                        filename=filename)
    elif online == True:
        return py.iplot(fighm, show_link=False, filename=filename)
    def caculate_performance(self, tearsheet=False):
        # to daily
        try:
            rets = self._equity.resample('D').last().dropna().pct_change()
            if self._benchmark is not None:
                b_rets = self._df_positions['benchmark'].resample('D').last().dropna().pct_change()
        except:
            rets = self._equity.pct_change()
            if self._benchmark is not None:
                b_rets = self._df_positions['benchmark'].pct_change()

        rets = rets[1:]
        if self._benchmark is not None:
            b_rets = b_rets[1:]

        #rets.index = rets.index.tz_localize('UTC')
        #self._df_positions.index = self._df_positions.index.tz_localize('UTC')
        perf_stats_all = None
        if not self._df_trades.index.empty:
            if self._benchmark is not None:
                # self._df_trades.index = self._df_trades.index.tz_localize('UTC')
                # pf.create_full_tear_sheet(rets, self._df_positions, self._df_trades)
                rets.index = pd.to_datetime(rets.index)
                b_rets.index = rets.index

                perf_stats_strat = pf.timeseries.perf_stats(rets)
                perf_stats_benchmark = pf.timeseries.perf_stats(b_rets)
                perf_stats_all = pd.concat([perf_stats_strat, perf_stats_benchmark], axis=1)
                perf_stats_all.columns = ['Strategy', 'Benchmark']
            else:
                # self._df_trades.index = self._df_trades.index.tz_localize('UTC')
                # pf.create_full_tear_sheet(rets, self._df_positions, self._df_trades)
                rets.index = pd.to_datetime(rets.index)
                perf_stats_all = pf.timeseries.perf_stats(rets)
                perf_stats_all = perf_stats_all.to_frame(name='Strategy')

            if tearsheet:            # only plot if not self._df_trades.index.empty
                # pf.create_returns_tear_sheet(rets,benchmark_rets=b_rets)
                pf.create_returns_tear_sheet(rets)
                # pf.create_simple_tear_sheet(rets, benchmark_rets=b_rets)

                # somehow the tearsheet is too crowded.
                fig, ax = plt.subplots(nrows=1, ncols=2)
                if self._benchmark is not None:
                    pf.plot_rolling_returns(rets, factor_returns=b_rets, ax=ax[0])
                    ax[0].set_title('Cumulative returns')
                    ax[1].text(5.0, 9.5, 'Strategy', fontsize=8, fontweight='bold', horizontalalignment='left')
                    ax[1].text(8.0, 9.5, 'Benchmark', fontsize=8, fontweight='bold', horizontalalignment='left')

                    ax[1].text(0.5, 8.5, 'Annual return', fontsize=8, horizontalalignment='left')
                    ax[1].text(6.0, 8.5, round(perf_stats_all.loc['Annual return', 'Strategy'], 4), fontsize=8,
                               horizontalalignment='right')
                    ax[1].text(9.5, 8.5, round(perf_stats_all.loc['Annual return', 'Benchmark'], 4), fontsize=8,
                               horizontalalignment='right')

                    ax[1].text(0.5, 7.5, 'Cumulative returns', fontsize=8, horizontalalignment='left', color='green')
                    ax[1].text(6.0, 7.5, round(perf_stats_all.loc['Cumulative returns', 'Strategy'], 4), fontsize=8,
                               horizontalalignment='right', color='green')
                    ax[1].text(9.5, 7.5, round(perf_stats_all.loc['Cumulative returns', 'Benchmark'], 4), fontsize=8,
                               horizontalalignment='right', color='green')

                    ax[1].text(0.5, 6.5, 'Annual volatility', fontsize=8, horizontalalignment='left')
                    ax[1].text(6.0, 6.5, round(perf_stats_all.loc['Annual volatility', 'Strategy'], 4), fontsize=8,
                              horizontalalignment='right')
                    ax[1].text(9.5, 6.5, round(perf_stats_all.loc['Annual volatility', 'Benchmark'], 4), fontsize=8,
                               horizontalalignment='right')

                    ax[1].text(0.5, 5.5, 'Sharpe ratio', fontsize=8, horizontalalignment='left', color='green')
                    ax[1].text(6.0, 5.5, round(perf_stats_all.loc['Sharpe ratio', 'Strategy'], 4), fontsize=8,
                               horizontalalignment='right', color='green')
                    ax[1].text(9.5, 5.5, round(perf_stats_all.loc['Sharpe ratio', 'Benchmark'], 4), fontsize=8,
                               horizontalalignment='right', color='green')

                    ax[1].text(0.5, 4.5, 'Calmar ratio', fontsize=8, horizontalalignment='left')
                    ax[1].text(6.0, 4.5, round(perf_stats_all.loc['Calmar ratio', 'Strategy'], 4), fontsize=8,
                              horizontalalignment='right')
                    ax[1].text(9.5, 4.5, round(perf_stats_all.loc['Calmar ratio', 'Benchmark'], 4), fontsize=8,
                               horizontalalignment='right')

                    ax[1].text(0.5, 3.5, 'Sortino ratio', fontsize=8, horizontalalignment='left', color='green')
                    ax[1].text(6.0, 3.5, round(perf_stats_all.loc['Sortino ratio', 'Strategy'], 4), fontsize=8,
                               horizontalalignment='right', color='green')
                    ax[1].text(9.5, 3.5, round(perf_stats_all.loc['Sortino ratio', 'Benchmark'], 4), fontsize=8,
                               horizontalalignment='right', color='green')

                    ax[1].text(0.5, 2.5, 'Max drawdown', fontsize=8, horizontalalignment='left')
                    ax[1].text(6.0, 2.5, round(perf_stats_all.loc['Max drawdown', 'Strategy'], 4), fontsize=8,
                               horizontalalignment='right')
                    ax[1].text(9.5, 2.5, round(perf_stats_all.loc['Max drawdown', 'Benchmark'], 4), fontsize=8,
                               horizontalalignment='right')

                    ax[1].text(0.5, 1.5, 'Skew', fontsize=8, horizontalalignment='left', color='green')
                    ax[1].text(6.0, 1.5, round(perf_stats_all.loc['Skew', 'Strategy'], 4), fontsize=8,
                               horizontalalignment='right', color='green')
                    ax[1].text(9.5, 1.5, round(perf_stats_all.loc['Skew', 'Benchmark'], 4), fontsize=8,
                               horizontalalignment='right', color='green')

                    ax[1].text(0.5, 0.5, 'Kurtosis', fontsize=8, horizontalalignment='left')
                    ax[1].text(6.0, 0.5, round(perf_stats_all.loc['Kurtosis', 'Strategy'], 4), fontsize=8,
                               horizontalalignment='right')
                    ax[1].text(9.5, 0.5, round(perf_stats_all.loc['Kurtosis', 'Benchmark'], 4), fontsize=8,
                               horizontalalignment='right')
                else:
                    pf.plot_rolling_returns(rets, ax=ax[0])
                    ax[0].set_title('Cumulative returns')
                    # pf.plotting.plot_monthly_returns_heatmap(rets, ax=ax[1])
                    ax[1].text(0.5, 9.0, 'Annual return', fontsize=8, horizontalalignment='left')
                    ax[1].text(9.5, 9.0, round(perf_stats_all.loc['Annual return', 'Strategy'], 4), fontsize=8,
                               horizontalalignment='right')

                    ax[1].text(0.5, 8.0, 'Cumulative returns', fontsize=8, horizontalalignment='left', color='green')
                    ax[1].text(9.5, 8.0, round(perf_stats_all.loc['Cumulative returns', 'Strategy'], 4), fontsize=8,
                               horizontalalignment='right', color='green')

                    ax[1].text(0.5, 7.0, 'Annual volatility', fontsize=8, horizontalalignment='left')
                    ax[1].text(9.5, 7.0, round(perf_stats_all.loc['Annual volatility', 'Strategy'], 4), fontsize=8,
                               horizontalalignment='right')

                    ax[1].text(0.5, 6.0, 'Sharpe ratio', fontsize=8, horizontalalignment='left', color='green')
                    ax[1].text(9.5, 6.0, round(perf_stats_all.loc['Sharpe ratio', 'Strategy'], 4), fontsize=8,
                               horizontalalignment='right', color='green')

                    ax[1].text(0.5, 5.0, 'Calmar ratio', fontsize=8, horizontalalignment='left')
                    ax[1].text(9.5, 5.0, round(perf_stats_all.loc['Calmar ratio', 'Strategy'], 4), fontsize=8,
                               horizontalalignment='right')

                    ax[1].text(0.5, 4.0, 'Sortino ratio', fontsize=8, horizontalalignment='left', color='green')
                    ax[1].text(9.5, 4.0, round(perf_stats_all.loc['Sortino ratio', 'Strategy'], 4), fontsize=8,
                               horizontalalignment='right', color='green')

                    ax[1].text(0.5, 3.0, 'Max drawdown', fontsize=8, horizontalalignment='left')
                    ax[1].text(9.5, 3.0, round(perf_stats_all.loc['Max drawdown', 'Strategy'], 4), fontsize=8,
                               horizontalalignment='right')

                    ax[1].text(0.5, 2.0, 'Skew', fontsize=8, horizontalalignment='left', color='green')
                    ax[1].text(9.5, 2.0, round(perf_stats_all.loc['Skew', 'Strategy'], 4), fontsize=8,
                               horizontalalignment='right', color='green')

                    ax[1].text(0.5, 1.0, 'Kurtosis', fontsize=8, horizontalalignment='left')
                    ax[1].text(9.5, 1.0, round(perf_stats_all.loc['Kurtosis', 'Strategy'], 4), fontsize=8,
                               horizontalalignment='right')

                ax[1].set_title('Performance', fontweight='bold')
                ax[1].grid(False)
                # ax[1].spines['top'].set_linewidth(2.0)
                # ax[1].spines['bottom'].set_linewidth(2.0)
                ax[1].spines['right'].set_visible(False)
                ax[1].spines['left'].set_visible(False)
                ax[1].get_yaxis().set_visible(False)
                ax[1].get_xaxis().set_visible(False)
                ax[1].set_ylabel('')
                ax[1].set_xlabel('')
                ax[1].axis([0, 10, 0, 10])

                plt.show()

        drawdown_df = pf.timeseries.gen_drawdown_table(rets, top=5)
        monthly_ret_table = ep.aggregate_returns(rets, 'monthly')
        monthly_ret_table = monthly_ret_table.unstack().round(3)
        ann_ret_df = pd.DataFrame(ep.aggregate_returns(rets, 'yearly'))
        ann_ret_df = ann_ret_df.unstack().round(3)
        return perf_stats_all, drawdown_df, monthly_ret_table, ann_ret_df
Пример #33
0
 def return_each_year(self, daily_change):
     result = empyrical.aggregate_returns(daily_change, 'yearly') * 100
     return result