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
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}
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
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))
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=["年化收益率", "年化波动率", "最大回撤", "夏普比率"])
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
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
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
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))
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 }
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)
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
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
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)
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)
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
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
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
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
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
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
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
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
def return_each_month(self, daily_change): result = empyrical.aggregate_returns(daily_change, 'monthly') * 100 return result
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('')
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,
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))
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))
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('')
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
def return_each_year(self, daily_change): result = empyrical.aggregate_returns(daily_change, 'yearly') * 100 return result