def add_summary_page(self): """Build a table which is shown on the first page which gives an overview of the portfolios""" s = PortfolioSummary() s.include_long_short() pieces = [] for r in self.results: tmp = s(r.port, PortfolioSummary.analyze_returns) tmp['desc'] = r.desc tmp['sid'] = r.sid tmp = tmp.set_index(['sid', 'desc'], append=1).reorder_levels([2, 1, 0]) pieces.append(tmp) frame = pd.concat(pieces) tf = self.pdf.table_formatter(frame) tf.apply_basic_style(cmap=self.table_style) # [col.guess_format(pcts=1, trunc_dot_zeros=1) for col in tf.cells.iter_cols()] tf.cells.match_column_labels( ['nmonths', 'cnt', 'win cnt', 'lose cnt', 'dur max']).int_format() tf.cells.match_column_labels(['sharpe ann', 'sortino', 'dur avg']).float_format(precision=1) tf.cells.match_column_labels(['maxdd dt']).apply_format( new_datetime_formatter('%d-%b-%y')) tf.cells.match_column_labels([ 'cagr', 'mret avg', 'mret std ann', 'ret std', 'mret avg ann', 'maxdd', 'avg dd', 'winpct', 'ret avg', 'ret min', 'ret max' ]).percent_format() self.pdf.build_page('summary', {'F1': tf.build()})
def add_summary_page(self): """Build a table which is shown on the first page which gives an overview of the portfolios""" s = PortfolioSummary() s.include_long_short() pieces = [] for r in self.results: tmp = s(r.port, PortfolioSummary.analyze_returns) tmp["desc"] = r.desc tmp["sid"] = r.sid tmp = tmp.set_index(["sid", "desc"], append=1).reorder_levels([2, 1, 0]) pieces.append(tmp) frame = pd.concat(pieces) tf = self.pdf.table_formatter(frame) tf.apply_basic_style(cmap=self.table_style) # [col.guess_format(pcts=1, trunc_dot_zeros=1) for col in tf.cells.iter_cols()] tf.cells.match_column_labels( ["nmonths", "cnt", "win cnt", "lose cnt", "dur max"]).int_format() tf.cells.match_column_labels(["sharpe ann", "sortino", "dur avg"]).float_format(precision=1) tf.cells.match_column_labels(["maxdd dt"]).apply_format( new_datetime_formatter("%d-%b-%y")) tf.cells.match_column_labels([ "cagr", "mret avg", "mret std ann", "ret std", "mret avg ann", "maxdd", "avg dd", "winpct", "ret avg", "ret min", "ret max", ]).percent_format() self.pdf.build_page("summary", {"F1": tf.build()})
def add_summary_page(self): """Build a table which is shown on the first page which gives an overview of the portfolios""" s = PortfolioSummary() s.include_long_short() pieces = [] for r in self.results: tmp = s(r.port, PortfolioSummary.analyze_returns) tmp['desc'] = r.desc tmp['sid'] = r.sid tmp = tmp.set_index(['sid', 'desc'], append=1).reorder_levels([2, 1, 0]) pieces.append(tmp) frame = pd.concat(pieces) tf = self.pdf.table_formatter(frame) tf.apply_basic_style(cmap=self.table_style) # [col.guess_format(pcts=1, trunc_dot_zeros=1) for col in tf.cells.iter_cols()] tf.cells.match_column_labels(['nmonths', 'cnt', 'win cnt', 'lose cnt', 'dur max']).int_format() tf.cells.match_column_labels(['sharpe ann', 'sortino', 'dur avg']).float_format(precision=1) tf.cells.match_column_labels(['maxdd dt']).apply_format(new_datetime_formatter('%d-%b-%y')) tf.cells.match_column_labels(['cagr', 'mret avg', 'mret std ann', 'ret std', 'mret avg ann', 'maxdd', 'avg dd', 'winpct', 'ret avg', 'ret min', 'ret max']).percent_format() self.pdf.build_page('summary', {'F1': tf.build()})
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)
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)
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)
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)
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)
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)