print(ann_ret_df) if run_in_jupyter: pf.create_full_tear_sheet(strat_ret, benchmark_rets=bm_ret, positions=df_positions, transactions=df_trades, round_trips=False) plt.show() else: f1 = plt.figure(1) pf.plot_rolling_returns(strat_ret, factor_returns=bm_ret) f1.show() f2 = plt.figure(2) pf.plot_rolling_volatility(strat_ret, factor_returns=bm_ret) f2.show() f3 = plt.figure(3) pf.plot_rolling_sharpe(strat_ret) f3.show() f4 = plt.figure(4) pf.plot_drawdown_periods(strat_ret) f4.show() f5 = plt.figure(5) pf.plot_monthly_returns_heatmap(strat_ret) f5.show() f6 = plt.figure(6) pf.plot_annual_returns(strat_ret) f6.show() f7 = plt.figure(7) pf.plot_monthly_returns_dist(strat_ret) plt.show()
df_backtest = pd.concat(frames) df_backtest['Forward_ret'] = df_backtest['Close'].shift(-1)/df_backtest['Open'].shift(-1) -1 df_backtest['Costs'] = abs(df_backtest['Signals'] - df_backtest['Signals'].shift(1))*0.0001 df_backtest['Strategy_forward_ret'] = df_backtest['Forward_ret'] *df_backtest['Signals']-df_backtest['Costs'] bt_returns = df_backtest['Strategy_forward_ret'] plt.figure(figsize=(10, 8), dpi= 50) # Cumulative Returns pf.plotting.plot_rolling_returns(bt_returns,live_start_date = df_test.index[0]) plt.show() # Daily, Non-Cumulative Returns plt.figure(figsize=(10, 8), dpi= 50) pf.plot_rolling_sharpe(bt_returns) plt.tight_layout() plt.show() plt.figure(figsize=(10, 8), dpi= 50) pf.plot_drawdown_underwater(bt_returns); plt.show() fig = plt.figure(1) plt.subplot(1,3,1) pf.plot_annual_returns(bt_returns) plt.subplot(1,3,2) pf.plot_monthly_returns_dist(bt_returns) plt.subplot(1,3,3) pf.plot_monthly_returns_heatmap(bt_returns) plt.tight_layout()
ax4 = pf.plot_rolling_returns(benchReturns['50/50 SPY Port'], factor_returns=benchReturns['SPY']) ax4.set(title="Blended vs Benchmark Rolling Returns", xlabel="Date", ylabel="Return in %", xticks=xtickrange) plt.savefig('Blended vs Benchmar Rolling Returns.png') plt.close() ax5 = pf.plot_rolling_volatility(benchReturns['50/50 SPY Port'], factor_returns=benchReturns['SPY']) ax5.set(title="Blended vs Benchmark Rolling Volatiltiy", xlabel="Date", ylabel="One standard deviation in %", xticks=xtickrange) plt.savefig('Blended vs Benchmark Rolling Volatiltiy.png') plt.close() ax6 = pf.plot_rolling_sharpe(benchReturns['50/50 SPY Port'], factor_returns=benchReturns['SPY']) ax6.set(title="Blended vs Benchmark Rolling Sharpe Ratio", xlabel="Date", ylabel="Ratio of Return:Volatility", xticks=xtickrange) plt.savefig('Blended vs Benchmark Rolling Sharpe.png') plt.close() # Summary Table sharpeTable = sharpe(allreturns, 0) sharpeTable.to_csv('Strategy and Blend vs Benchmarks.csv')
############################ pf.plot_return_quantiles(backtest_returns) ############################ # Rolling Plot # # frequency = M/Y # # BETA # ############################ pf.plot_rolling_beta(backtest_returns, benchmark_returns) ############################ # Rolling Plot # # frequency = M/Y # # SHARPE RATIO # ############################ pf.plot_rolling_sharpe(backtest_returns) ############################ # Top 10 Drawdown Periods # # frequency = M/Y # ############################ pf.plot_drawdown_periods(backtest_returns) ############################ # UnderWater Plot # # Drawdown Periods # # frequency = M/Y # # in values of = % # ############################ pf.plot_drawdown_underwater(backtest_returns)
def plot_performance( returns, benchmark_prices, plot_stats=False, startcash=None, log_returns=False, save_dir=None ): """ :param returns: pd.Series, return data :param benchmark_prices: pd.Series, benchmark return data :param startcash: int, rebase the benchmark if provided :return: None """ if save_dir and not os.path.exists(save_dir): os.makedirs(save_dir) # Rebase benchmark prices, the same as portfolio prices if startcash is not None: benchmark_prices = (benchmark_prices / benchmark_prices.iloc[0]) * startcash benchmark_rets = pyp.expected_returns.returns_from_prices(benchmark_prices) if log_returns: portfolio_value = returns.cumsum().apply(np.exp) * startcash else: portfolio_value = (1 + returns).cumprod() * startcash # Performance statistics if plot_stats: pf.show_perf_stats(returns) pf.show_perf_stats(benchmark_rets) # Fig 1: price and return fig, ax = plt.subplots(2, 1, sharex=True, figsize=[14, 8]) portfolio_value.plot(ax=ax[0], label='Portfolio') benchmark_prices.plot(ax=ax[0], label='Benchmark') ax[0].set_ylabel('Price') ax[0].grid(True) ax[0].legend() returns.plot(ax=ax[1], label='Portfolio', alpha=0.5) benchmark_rets.plot(ax=ax[1], label='Benchmark', alpha=0.5) ax[1].set_ylabel('Return') fig.suptitle('Black–Litterman Portfolio Optimization', fontsize=16) plt.grid(True) plt.legend() plt.show() if save_dir: fig.savefig(os.path.join(save_dir, 'price_and_return'), dpi=300) # Fig 2: return performance fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(16, 9), constrained_layout=False) axes = ax.flatten() pf.plot_rolling_beta(returns=returns, factor_returns=benchmark_rets, ax=axes[0]) pf.plot_return_quantiles(returns=returns, ax=axes[1]) pf.plot_annual_returns(returns=returns, ax=axes[2]) pf.plot_monthly_returns_heatmap(returns=returns, ax=axes[3]) axes[0].grid(True) axes[1].grid(True) axes[2].grid(True) fig.suptitle('Return performance', fontsize=16, y=1.0) plt.tight_layout() if save_dir: fig.savefig(os.path.join(save_dir, 'return_performance'), dpi=300) # Fig 3: risk performance fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(14, 8), constrained_layout=False) axes = ax.flatten() pf.plot_drawdown_periods(returns=returns, ax=axes[0]) pf.plot_rolling_volatility(returns=returns, factor_returns=benchmark_rets, ax=axes[1]) pf.plot_drawdown_underwater(returns=returns, ax=axes[2]) pf.plot_rolling_sharpe(returns=returns, ax=axes[3]) axes[0].grid(True) axes[1].grid(True) axes[2].grid(True) axes[3].grid(True) fig.suptitle('Risk performance', fontsize=16, y=1.0) plt.tight_layout() if save_dir: fig.savefig(os.path.join(save_dir, 'risk_performance'), dpi=300)