Example #1
0
File: port.py Project: x829901/tia
    def __call__(self, port, analyze_fct=None):
        """  analyze_fct: fct(port) which can return Series, or map of key to Series. If key to series, then
        the key is used as an additional index value.

        :param port: Portfolio or dict of key->Portfolio
        :param analyze_fct:
        :return:
        """
        iter_fcts = self.iter_fcts
        lvls = len(iter_fcts)

        analyze_fct = self.analyze_returns if analyze_fct is None else analyze_fct

        def _iter_all_lvls(lvl, keys, parent, results):
            if lvl < (lvls - 1):
                # exhaust combinations
                for key, child in iter_fcts[lvl](parent):
                    _iter_all_lvls(lvl + 1, keys + [key], child, results)
            else:
                # at the bottom
                for key, child in iter_fcts[lvl](parent):
                    idx_names = ['lvl{0}'.format(i + 1) for i in range(lvls)]
                    idx_vals = [[k] for k in keys + [key]]
                    idx = pd.MultiIndex.from_arrays(idx_vals, names=idx_names)
                    res = analyze_fct(child)
                    if isinstance(res, pd.Series):
                        res = res.to_frame().T
                        res.index = idx
                        results.append(res)
                    else:
                        for k, v in res.items():
                            # prepend current levels to key name
                            v = v.to_frame().T
                            idx = pd.MultiIndex.from_arrays(idx_vals + [k], names=idx_names + ['lvl%s' % lvls])
                            v.index = idx
                            results.append(v)

        if lvls == 0:
            def _get_res(p):
                res = analyze_fct(p)
                return res.to_frame().T if isinstance(res, pd.Series) else res

            if hasattr(port, 'iteritems'):
                pieces = []
                for k, p in port.items():
                    res = _get_res(p)
                    defidx = res.index.nlevels == 1 and (res.index == 0).all()
                    res = insert_level(res, k, axis=1, level_name='lvl1')
                    if defidx:
                        res.index = res.index.droplevel(1)
                    pieces.append(res)
                return pd.concat(pieces)
            else:
                return _get_res(port)
        else:
            if hasattr(port, 'iteritems'):
                pieces = []
                for k, p in port.items():
                    results = []
                    _iter_all_lvls(0, [], p, results)
                    tmp = pd.concat(results)
                    tmp.index.names = ['lvl%s' % (i + 2) for i in range(len(tmp.index.names))]
                    tmp = insert_level(tmp, k, level_name='lvl1', axis=1)
                    pieces.append(tmp)
                return pd.concat(pieces)
            else:
                results = []
                _iter_all_lvls(0, [], port, results)
                return pd.concat(results)
Example #2
0
    def add_portfolio_page(self, result):
        def alpha_beta(p, bm):
            model = pd.ols(x=bm.rets, y=p.rets)
            beta = model.beta[0]
            alpha = p.total_ann - beta * bm.total_ann
            s = pd.Series({'alpha': alpha, 'beta': beta})
            return s

        def rs(port1, port2, kind='dly_ret_stats'):
            stats = getattr(port1, kind)
            ab = alpha_beta(stats, getattr(port2, kind))
            tmp = stats.series.append(ab)
            tmp.name = stats.series.name
            return tmp

        def dofmt(t):
            t.apply_basic_style(cmap=self.table_style)
            [
                row.guess_format(pcts=1, trunc_dot_zeros=1)
                for row in t.cells.iter_rows()
            ]
            ncols = len(t.formatted_values.columns)
            t.set_col_widths(pcts=[1. / ncols] * ncols)

        def do_rename(df):
            d = {
                'consecutive_win_cnt_max': 'win_streak',
                'consecutive_loss_cnt_max': 'lose_streak'
            }
            return df.rename(index=lambda c: d.get(c, c))

        # Build the pdf tables
        pdf = self.pdf
        figures = self.figures
        port = result.port
        buyhold = result.buyhold
        sframe = pd.DataFrame([
            rs(port, buyhold, 'dly_ret_stats'),
            rs(port, buyhold, 'weekly_ret_stats'),
            rs(port, buyhold, 'monthly_ret_stats'),
            rs(port, buyhold, 'quarterly_ret_stats')
        ]).T

        tf = pdf.table_formatter(insert_level(sframe, 'Portfolio', copy=True))
        dofmt(tf)
        stable = tf.build()

        s = PortfolioSummary()
        s.include_long_short().include_win_loss()
        dframe = s(port, PortfolioSummary.analyze_returns).T
        tf = pdf.table_formatter(
            do_rename(insert_level(dframe.ix['port'], 'Portfolio', copy=True)))
        dofmt(tf)
        dtable = tf.build()

        # Return on $1 image
        f, ax = self.create_ax()
        buyhold.plot_ret_on_dollar('B', label='Buy & Hold', ax=ax)
        port.plot_ret_on_dollar('B', label=result.desc, ax=ax, color='k')
        ax.legend(loc='upper left')
        ax.set_title('vs Buy & Hold')
        plt.tight_layout()
        figures.savefig(key='buyhold', clear=1)
        # Drawdown image
        f, ax = self.create_ax()
        port.dly_ret_stats.plot_ltd(ax=ax)
        plt.tight_layout()
        figures.savefig(key='dd', clear=1)
        # Long / Short Returns
        f, ax = self.create_ax()
        port.plot_ret_on_dollar('B', label='All', color='k', ax=ax)
        port.long.plot_ret_on_dollar('B', label='Long', ax=ax)
        port.short.plot_ret_on_dollar('B', label='Short', ax=ax)
        ax.legend(loc='upper left')
        figures.savefig(key='ls', clear=1)
        # Sharpe / Ann Vol
        f, ax = self.create_ax()
        perf.sharpe_annualized(port.monthly_rets,
                               expanding=1).iloc[3:].plot(ax=ax,
                                                          color='k',
                                                          label='sharpe')
        ax.set_ylabel('sharpe ann', color='k')
        ax2 = ax.twinx()
        perf.std_annualized(port.monthly_rets,
                            expanding=1).iloc[3:].plot(ax=ax2,
                                                       label='vol',
                                                       color='b',
                                                       alpha=1)
        ax2.set_ylabel('vol ann', color='b')
        plt.tight_layout()
        figures.savefig(key='sharpe', clear=1)
        # Monthly Returns Bar Chart
        f, ax = self.create_ax()
        tmp = pd.DataFrame({
            'All': port.monthly_rets.to_period('M'),
            'Long': port.long.monthly_rets.to_period('M'),
            'Short': port.short.monthly_rets.to_period('M')
        })
        tmp.plot(kind='bar',
                 ax=ax,
                 color=['k', self.long_color, self.short_color])
        AxesFormat().Y.percent().X.rotate().apply()
        plt.tight_layout()
        ax.set_title('Monthly Returns')
        figures.savefig(key='mrets', clear=1)
        # Monthly Returns Box Plot
        f, ax = self.create_ax()
        sns.boxplot(tmp,
                    ax=ax,
                    color=['gray', self.long_color, self.short_color])
        ax.set_title('Monthly Returns')
        AxesFormat().Y.percent().apply()
        plt.tight_layout()
        figures.savefig(key='mrets_box', clear=1)
        # Build the PDF Page
        toimg = lambda path: rlab.new_dynamic_image(path)
        itms = {
            'F1':
            toimg(figures['buyhold']),
            'F2':
            toimg(figures['dd']),
            'F3':
            toimg(figures['ls']),
            'F4':
            toimg(figures['mrets']),
            'F5':
            toimg(figures['sharpe']),
            'F6':
            toimg(figures['mrets_box']),
            'F7':
            stable,
            'F8':
            dtable,
            'HDR':
            self.title_bar('{0} - {1} - portfolio summary'.format(
                result.sid, result.desc))
        }
        pdf.build_page('portfolio', itms)
Example #3
0
    def add_position_page(self, result):
        def dofmt(t):
            t.apply_basic_style(cmap=self.table_style)
            [
                row.guess_format(pcts=1, trunc_dot_zeros=1)
                for row in t.cells.iter_rows()
            ]
            ncols = len(t.formatted_values.columns)
            t.set_col_widths(pcts=[1. / ncols] * ncols)
            return t

        def do_rename(df):
            d = {
                'consecutive_win_cnt_max': 'win_streak',
                'consecutive_loss_cnt_max': 'lose_streak'
            }
            return df.rename(index=lambda c: d.get(c, c))

        pdf = self.pdf
        figures = self.figures
        port = result.port
        buyhold = result.buyhold

        sframe = pd.DataFrame({
            'all': port.positions.stats.series,
            'long': port.long.positions.stats.series,
            'short': port.short.positions.stats.series
        })
        tf = pdf.table_formatter(insert_level(sframe, 'Position', copy=True))
        stable = dofmt(tf).build()

        s = PortfolioSummary()
        s.include_long_short().include_win_loss()
        dframe = s(port, PortfolioSummary.analyze_returns).T.ix['pos']
        tf = pdf.table_formatter(
            do_rename(insert_level(dframe, 'Position', copy=True)))
        dtable = dofmt(tf).build()

        # Plot Position Returns
        f, ax = self.create_ax()
        port.positions.plot_rets(ax=ax)
        plt.tight_layout()
        figures.savefig(key='pos_ls', clear=1)
        # Plot Position Ranges
        f, ax = self.create_ax(figsize=(8, 3))
        port.positions.plot_ret_range(ls=1, dur=1, ax=ax)
        plt.tight_layout()
        figures.savefig(key='pos_rng', clear=1)
        # Plot Long Short Positions with regression line
        tmp = port.position_frame[['side', 'ret']].reset_index()
        g = sns.lmplot("pid", "ret", col="side", hue="side", data=tmp, size=3)
        AxesFormat().Y.percent().apply()
        figures.savefig(key='pos_ls', clear=1)
        # Plot Return vs Duration
        tmp = port.position_frame[['ret', 'duration', 'side']]
        diag_kws = {}
        if len(port.position_frame.index) <= 1:
            diag_kws = {'range': (-100, 100)}
        sns.pairplot(tmp, hue="side", size=3, diag_kws=diag_kws)
        figures.savefig(key='pos_pair', clear=1)

        toimg = lambda path: rlab.new_dynamic_image(path)
        itms = {
            'F1':
            toimg(figures['pos_rng']),
            'F3':
            toimg(figures['pos_ls']),
            'F2':
            toimg(figures['pos_pair']),
            'F5':
            stable,
            'F6':
            dtable,
            'HDR':
            self.title_bar('{0} - {1} - position summary'.format(
                result.sid, result.desc))
        }
        pdf.build_page('positions', itms)
Example #4
0
File: port.py Project: Vjp33/tia
    def __call__(self, port, analyze_fct=None):
        """  analyze_fct: fct(port) which can return Series, or map of key to Series. If key to series, then
        the key is used as an additional index value.

        :param port: Portfolio or dict of key->Portfolio
        :param analyze_fct:
        :return:
        """
        iter_fcts = self.iter_fcts
        lvls = len(iter_fcts)

        analyze_fct = self.analyze_returns if analyze_fct is None else analyze_fct

        def _iter_all_lvls(lvl, keys, parent, results):
            if lvl < (lvls - 1):
                # exhaust combinations
                for key, child in iter_fcts[lvl](parent):
                    _iter_all_lvls(lvl + 1, keys + [key], child, results)
            else:
                # at the bottom
                for key, child in iter_fcts[lvl](parent):
                    idx_names = ['lvl{0}'.format(i + 1) for i in range(lvls)]
                    idx_vals = [[k] for k in keys + [key]]
                    idx = pd.MultiIndex.from_arrays(idx_vals, names=idx_names)
                    res = analyze_fct(child)
                    if isinstance(res, pd.Series):
                        res = res.to_frame().T
                        res.index = idx
                        results.append(res)
                    else:
                        for k, v in res.iteritems():
                            # prepend current levels to key name
                            v = v.to_frame().T
                            idx = pd.MultiIndex.from_arrays(idx_vals + [k], names=idx_names + ['lvl%s' % lvls])
                            v.index = idx
                            results.append(v)

        if lvls == 0:
            def _get_res(p):
                res = analyze_fct(p)
                return res.to_frame().T if isinstance(res, pd.Series) else res

            if hasattr(port, 'iteritems'):
                pieces = []
                for k, p in port.iteritems():
                    res = _get_res(p)
                    defidx = res.index.nlevels == 1 and (res.index == 0).all()
                    res = insert_level(res, k, axis=1, level_name='lvl1')
                    if defidx:
                        res.index = res.index.droplevel(1)
                    pieces.append(res)
                return pd.concat(pieces)
            else:
                return _get_res(port)
        else:
            if hasattr(port, 'iteritems'):
                pieces = []
                for k, p in port.iteritems():
                    results = []
                    _iter_all_lvls(0, [], p, results)
                    tmp = pd.concat(results)
                    tmp.index.names = ['lvl%s' % (i + 2) for i in range(len(tmp.index.names))]
                    tmp = insert_level(tmp, k, level_name='lvl1', axis=1)
                    pieces.append(tmp)
                return pd.concat(pieces)
            else:
                results = []
                _iter_all_lvls(0, [], port, results)
                return pd.concat(results)
Example #5
0
    def add_position_page(self, result):
        def dofmt(t):
            t.apply_basic_style(cmap=self.table_style)
            [row.guess_format(pcts=1, trunc_dot_zeros=1) for row in t.cells.iter_rows()]
            ncols = len(t.formatted_values.columns)
            t.set_col_widths(pcts=[1. / ncols] * ncols)
            return t

        def do_rename(df):
            d = {'consecutive_win_cnt_max': 'win_streak', 'consecutive_loss_cnt_max': 'lose_streak'}
            return df.rename(index=lambda c: d.get(c, c))

        pdf = self.pdf
        figures = self.figures
        port = result.port
        buyhold = result.buyhold

        sframe = pd.DataFrame({'all': port.positions.stats.series,
                               'long': port.long.positions.stats.series,
                               'short': port.short.positions.stats.series})
        tf = pdf.table_formatter(insert_level(sframe, 'Position', copy=True))
        stable = dofmt(tf).build()

        s = PortfolioSummary()
        s.include_long_short().include_win_loss()
        dframe = s(port, PortfolioSummary.analyze_returns).T.ix['pos']
        tf = pdf.table_formatter(do_rename(insert_level(dframe, 'Position', copy=True)))
        dtable = dofmt(tf).build()

        # Plot Position Returns
        f, ax = self.create_ax()
        port.positions.plot_rets(ax=ax)
        plt.tight_layout()
        figures.savefig(key='pos_ls', clear=1)
        # Plot Position Ranges
        f, ax = self.create_ax(figsize=(8, 3))
        port.positions.plot_ret_range(ls=1, dur=1, ax=ax)
        plt.tight_layout()
        figures.savefig(key='pos_rng', clear=1)
        # Plot Long Short Positions with regression line
        tmp = port.position_frame[['side', 'ret']].reset_index()
        g = sns.lmplot("pid", "ret", col="side", hue="side", data=tmp, size=3)
        AxesFormat().Y.percent().apply()
        figures.savefig(key='pos_ls', clear=1)
        # Plot Return vs Duration
        tmp = port.position_frame[['ret', 'duration', 'side']]
        diag_kws = {}
        if len(port.position_frame.index) <= 1:
            diag_kws = {'range': (-100, 100)}
        sns.pairplot(tmp, hue="side", size=3, diag_kws=diag_kws)
        figures.savefig(key='pos_pair', clear=1)

        toimg = lambda path: rlab.new_dynamic_image(path)
        itms = {
            'F1': toimg(figures['pos_rng']),
            'F3': toimg(figures['pos_ls']),
            'F2': toimg(figures['pos_pair']),
            'F5': stable,
            'F6': dtable,
            'HDR': self.title_bar('{0} - {1} - position summary'.format(result.sid, result.desc))
        }
        pdf.build_page('positions', itms)
Example #6
0
    def add_portfolio_page(self, result):
        def alpha_beta(p, bm):
            model = pd.ols(x=bm.rets, y=p.rets)
            beta = model.beta[0]
            alpha = p.total_ann - beta * bm.total_ann
            s = pd.Series({'alpha': alpha, 'beta': beta})
            return s

        def rs(port1, port2, kind='dly_ret_stats'):
            stats = getattr(port1, kind)
            ab = alpha_beta(stats, getattr(port2, kind))
            tmp = stats.series.append(ab)
            tmp.name = stats.series.name
            return tmp

        def dofmt(t):
            t.apply_basic_style(cmap=self.table_style)
            [row.guess_format(pcts=1, trunc_dot_zeros=1) for row in t.cells.iter_rows()]
            ncols = len(t.formatted_values.columns)
            t.set_col_widths(pcts=[1. / ncols] * ncols)

        def do_rename(df):
            d = {'consecutive_win_cnt_max': 'win_streak', 'consecutive_loss_cnt_max': 'lose_streak'}
            return df.rename(index=lambda c: d.get(c, c))

        # Build the pdf tables
        pdf = self.pdf
        figures = self.figures
        port = result.port
        buyhold = result.buyhold
        sframe = pd.DataFrame([rs(port, buyhold, 'dly_ret_stats'),
                               rs(port, buyhold, 'weekly_ret_stats'),
                               rs(port, buyhold, 'monthly_ret_stats'),
                               rs(port, buyhold, 'quarterly_ret_stats')]).T

        tf = pdf.table_formatter(insert_level(sframe, 'Portfolio', copy=True))
        dofmt(tf)
        stable = tf.build()

        s = PortfolioSummary()
        s.include_long_short().include_win_loss()
        dframe = s(port, PortfolioSummary.analyze_returns).T
        tf = pdf.table_formatter(do_rename(insert_level(dframe.ix['port'], 'Portfolio', copy=True)))
        dofmt(tf)
        dtable = tf.build()

        # Return on $1 image
        f, ax = self.create_ax()
        buyhold.plot_ret_on_dollar('B', label='Buy & Hold', ax=ax)
        port.plot_ret_on_dollar('B', label=result.desc, ax=ax, color='k')
        ax.legend(loc='upper left')
        ax.set_title('vs Buy & Hold')
        plt.tight_layout()
        figures.savefig(key='buyhold', clear=1)
        # Drawdown image
        f, ax = self.create_ax()
        port.dly_ret_stats.plot_ltd(ax=ax)
        plt.tight_layout()
        figures.savefig(key='dd', clear=1)
        # Long / Short Returns
        f, ax = self.create_ax()
        port.plot_ret_on_dollar('B', label='All', color='k', ax=ax)
        port.long.plot_ret_on_dollar('B', label='Long', ax=ax)
        port.short.plot_ret_on_dollar('B', label='Short', ax=ax)
        ax.legend(loc='upper left')
        figures.savefig(key='ls', clear=1)
        # Sharpe / Ann Vol
        f, ax = self.create_ax()
        perf.sharpe_annualized(port.monthly_rets, expanding=1).iloc[3:].plot(ax=ax, color='k', label='sharpe')
        ax.set_ylabel('sharpe ann', color='k')
        ax2 = ax.twinx()
        perf.std_annualized(port.monthly_rets, expanding=1).iloc[3:].plot(ax=ax2, label='vol', color='b', alpha=1)
        ax2.set_ylabel('vol ann', color='b')
        plt.tight_layout()
        figures.savefig(key='sharpe', clear=1)
        # Monthly Returns Bar Chart
        f, ax = self.create_ax()
        tmp = pd.DataFrame({'All': port.monthly_rets.to_period('M'),
                            'Long': port.long.monthly_rets.to_period('M'),
                            'Short': port.short.monthly_rets.to_period('M')})
        tmp.plot(kind='bar', ax=ax, color=['k', self.long_color, self.short_color])
        AxesFormat().Y.percent().X.rotate().apply()
        plt.tight_layout()
        ax.set_title('Monthly Returns')
        figures.savefig(key='mrets', clear=1)
        # Monthly Returns Box Plot
        f, ax = self.create_ax()
        sns.boxplot(tmp, ax=ax, color=['gray', self.long_color, self.short_color])
        ax.set_title('Monthly Returns')
        AxesFormat().Y.percent().apply()
        plt.tight_layout()
        figures.savefig(key='mrets_box', clear=1)
        # Build the PDF Page
        toimg = lambda path: rlab.new_dynamic_image(path)
        itms = {
            'F1': toimg(figures['buyhold']),
            'F2': toimg(figures['dd']),
            'F3': toimg(figures['ls']),
            'F4': toimg(figures['mrets']),
            'F5': toimg(figures['sharpe']),
            'F6': toimg(figures['mrets_box']),
            'F7': stable,
            'F8': dtable,
            'HDR': self.title_bar('{0} - {1} - portfolio summary'.format(result.sid, result.desc))
        }
        pdf.build_page('portfolio', itms)
Example #7
0
    def add_position_page(self, result):
        def dofmt(t):
            t.apply_basic_style(cmap=self.table_style)
            [
                row.guess_format(pcts=1, trunc_dot_zeros=1)
                for row in t.cells.iter_rows()
            ]
            ncols = len(t.formatted_values.columns)
            t.set_col_widths(pcts=[1.0 / ncols] * ncols)
            return t

        def do_rename(df):
            d = {
                "consecutive_win_cnt_max": "win_streak",
                "consecutive_loss_cnt_max": "lose_streak",
            }
            return df.rename(index=lambda c: d.get(c, c))

        pdf = self.pdf
        figures = self.figures
        port = result.port
        buyhold = result.buyhold

        sframe = pd.DataFrame({
            "all": port.positions.stats.series,
            "long": port.long.positions.stats.series,
            "short": port.short.positions.stats.series,
        })
        tf = pdf.table_formatter(insert_level(sframe, "Position", copy=True))
        stable = dofmt(tf).build()

        s = PortfolioSummary()
        s.include_long_short().include_win_loss()
        dframe = s(port, PortfolioSummary.analyze_returns).T.ix["pos"]
        tf = pdf.table_formatter(
            do_rename(insert_level(dframe, "Position", copy=True)))
        dtable = dofmt(tf).build()

        # Plot Position Returns
        f, ax = self.create_ax()
        port.positions.plot_rets(ax=ax)
        plt.tight_layout()
        figures.savefig(key="pos_ls", clear=1)
        # Plot Position Ranges
        f, ax = self.create_ax(figsize=(8, 3))
        port.positions.plot_ret_range(ls=1, dur=1, ax=ax)
        plt.tight_layout()
        figures.savefig(key="pos_rng", clear=1)
        # Plot Long Short Positions with regression line
        tmp = port.position_frame[["side", "ret"]].reset_index()
        g = sns.lmplot("pid", "ret", col="side", hue="side", data=tmp, size=3)
        AxesFormat().Y.percent().apply()
        figures.savefig(key="pos_ls", clear=1)
        # Plot Return vs Duration
        tmp = port.position_frame[["ret", "duration", "side"]]
        diag_kws = {}
        if len(port.position_frame.index) <= 1:
            diag_kws = {"range": (-100, 100)}
        sns.pairplot(tmp, hue="side", size=3, diag_kws=diag_kws)
        figures.savefig(key="pos_pair", clear=1)

        toimg = lambda path: rlab.new_dynamic_image(path)
        itms = {
            "F1":
            toimg(figures["pos_rng"]),
            "F3":
            toimg(figures["pos_ls"]),
            "F2":
            toimg(figures["pos_pair"]),
            "F5":
            stable,
            "F6":
            dtable,
            "HDR":
            self.title_bar("{0} - {1} - position summary".format(
                result.sid, result.desc)),
        }
        pdf.build_page("positions", itms)
Example #8
0
    def add_portfolio_page(self, result):
        def alpha_beta(p, bm):
            model = pd.ols(x=bm.rets, y=p.rets)
            beta = model.beta[0]
            alpha = p.total_ann - beta * bm.total_ann
            s = pd.Series({"alpha": alpha, "beta": beta})
            return s

        def rs(port1, port2, kind="dly_ret_stats"):
            stats = getattr(port1, kind)
            ab = alpha_beta(stats, getattr(port2, kind))
            tmp = stats.series.append(ab)
            tmp.name = stats.series.name
            return tmp

        def dofmt(t):
            t.apply_basic_style(cmap=self.table_style)
            [
                row.guess_format(pcts=1, trunc_dot_zeros=1)
                for row in t.cells.iter_rows()
            ]
            ncols = len(t.formatted_values.columns)
            t.set_col_widths(pcts=[1.0 / ncols] * ncols)

        def do_rename(df):
            d = {
                "consecutive_win_cnt_max": "win_streak",
                "consecutive_loss_cnt_max": "lose_streak",
            }
            return df.rename(index=lambda c: d.get(c, c))

        # Build the pdf tables
        pdf = self.pdf
        figures = self.figures
        port = result.port
        buyhold = result.buyhold
        sframe = pd.DataFrame([
            rs(port, buyhold, "dly_ret_stats"),
            rs(port, buyhold, "weekly_ret_stats"),
            rs(port, buyhold, "monthly_ret_stats"),
            rs(port, buyhold, "quarterly_ret_stats"),
        ]).T

        tf = pdf.table_formatter(insert_level(sframe, "Portfolio", copy=True))
        dofmt(tf)
        stable = tf.build()

        s = PortfolioSummary()
        s.include_long_short().include_win_loss()
        dframe = s(port, PortfolioSummary.analyze_returns).T
        tf = pdf.table_formatter(
            do_rename(insert_level(dframe.ix["port"], "Portfolio", copy=True)))
        dofmt(tf)
        dtable = tf.build()

        # Return on $1 image
        f, ax = self.create_ax()
        buyhold.plot_ret_on_dollar("B", label="Buy & Hold", ax=ax)
        port.plot_ret_on_dollar("B", label=result.desc, ax=ax, color="k")
        ax.legend(loc="upper left")
        ax.set_title("vs Buy & Hold")
        plt.tight_layout()
        figures.savefig(key="buyhold", clear=1)
        # Drawdown image
        f, ax = self.create_ax()
        port.dly_ret_stats.plot_ltd(ax=ax)
        plt.tight_layout()
        figures.savefig(key="dd", clear=1)
        # Long / Short Returns
        f, ax = self.create_ax()
        port.plot_ret_on_dollar("B", label="All", color="k", ax=ax)
        port.long.plot_ret_on_dollar("B", label="Long", ax=ax)
        port.short.plot_ret_on_dollar("B", label="Short", ax=ax)
        ax.legend(loc="upper left")
        figures.savefig(key="ls", clear=1)
        # Sharpe / Ann Vol
        f, ax = self.create_ax()
        perf.sharpe_annualized(port.monthly_rets,
                               expanding=1).iloc[3:].plot(ax=ax,
                                                          color="k",
                                                          label="sharpe")
        ax.set_ylabel("sharpe ann", color="k")
        ax2 = ax.twinx()
        perf.std_annualized(port.monthly_rets,
                            expanding=1).iloc[3:].plot(ax=ax2,
                                                       label="vol",
                                                       color="b",
                                                       alpha=1)
        ax2.set_ylabel("vol ann", color="b")
        plt.tight_layout()
        figures.savefig(key="sharpe", clear=1)
        # Monthly Returns Bar Chart
        f, ax = self.create_ax()
        tmp = pd.DataFrame({
            "All": port.monthly_rets.to_period("M"),
            "Long": port.long.monthly_rets.to_period("M"),
            "Short": port.short.monthly_rets.to_period("M"),
        })
        tmp.plot(kind="bar",
                 ax=ax,
                 color=["k", self.long_color, self.short_color])
        AxesFormat().Y.percent().X.rotate().apply()
        plt.tight_layout()
        ax.set_title("Monthly Returns")
        figures.savefig(key="mrets", clear=1)
        # Monthly Returns Box Plot
        f, ax = self.create_ax()
        sns.boxplot(tmp,
                    ax=ax,
                    color=["gray", self.long_color, self.short_color])
        ax.set_title("Monthly Returns")
        AxesFormat().Y.percent().apply()
        plt.tight_layout()
        figures.savefig(key="mrets_box", clear=1)
        # Build the PDF Page
        toimg = lambda path: rlab.new_dynamic_image(path)
        itms = {
            "F1":
            toimg(figures["buyhold"]),
            "F2":
            toimg(figures["dd"]),
            "F3":
            toimg(figures["ls"]),
            "F4":
            toimg(figures["mrets"]),
            "F5":
            toimg(figures["sharpe"]),
            "F6":
            toimg(figures["mrets_box"]),
            "F7":
            stable,
            "F8":
            dtable,
            "HDR":
            self.title_bar("{0} - {1} - portfolio summary".format(
                result.sid, result.desc)),
        }
        pdf.build_page("portfolio", itms)