def run_strategy(self, cash=1000, commission=0.0004, tf=bt.TimeFrame.Minutes, compression=60): cerebro = bt.Cerebro() cerebro.broker.setcommission(commission=commission) cerebro.broker.setcash(cash) data = FinamHLOC(dataname=self.file_data, timeframe=tf, compression=compression) cerebro.addanalyzer(bt.analyzers.TimeReturn, _name='returns') cerebro.adddata(data) cerebro.addstrategy( TrendBreakerPL, pivot_window_len=self.algo_params['pivot_window_len'], history_bars_as_multiple_pwl=self. algo_params['history_bars_as_multiple_pwl'], fixed_tp=self.algo_params['fixed_tp'], fixed_sl_as_multiple_tp=self. algo_params['fixed_sl_as_multiple_tp'], order_full=self.output_settings['order_full'], order_status=self.output_settings['order_status'], trades=self.output_settings['trades']) if self.output_settings['performance']: print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) strats = cerebro.run() first_strat = strats[0] if self.output_settings['performance']: print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue()) od_returns = first_strat.analyzers.getbyname('returns').get_analysis() df_returns = pd.DataFrame(od_returns.items(), columns=['date', 'return']) df_returns = df_returns.set_index('date') self.stability = self.stability_of_timeseries(df_returns['return']) if self.output_settings['performance']: print('Performance:') print('Return: ' + str((cerebro.broker.getvalue() - cash) / cash * 100) + '%') print('Stability:' + str(self.stability)) print('Top-5 Drawdowns:') print(pf.show_worst_drawdown_periods(df_returns['return'], top=5)) if self.output_settings['plot']: # Read Close prices from csv and calculate the returns as a benchmark capital_algo = np.cumprod(1.0 + df_returns['return']) * cash benchmark_df = pd.read_csv(self.file_data) benchmark_returns = benchmark_df['<CLOSE>'].pct_change() capital_benchmark = np.cumprod(1.0 + benchmark_returns) * cash df_returns['benchmark_return'] = benchmark_returns # Plot Capital Curves plt.figure(figsize=(12, 7)) plt.plot(np.array(capital_algo), color='blue') plt.plot(np.array(capital_benchmark), color='red') plt.legend(['Algorithm', 'Buy & Hold']) plt.title('Capital Curve') plt.xlabel('Time') plt.ylabel('Value') plt.show() # Plot Drawdown Underwater plt.figure(figsize=(12, 7)) pf.plot_drawdown_underwater( df_returns['return']).set_xlabel('Time') plt.show() # Plot Top-5 Drawdowns plt.figure(figsize=(12, 7)) pf.plot_drawdown_periods(df_returns['return'], top=5).set_xlabel('Time') plt.show() # Plot Simple Returns plt.figure(figsize=(12, 7)) plt.plot(df_returns['return'], 'blue') plt.title('Returns') plt.xlabel('Time') plt.ylabel('Return') plt.show() # Plot Return Quantiles by Timeframe plt.figure(figsize=(12, 7)) pf.plot_return_quantiles( df_returns['return']).set_xlabel('Timeframe') plt.show() # Plot Monthly Returns Dist plt.figure(figsize=(12, 7)) pf.plot_monthly_returns_dist( df_returns['return']).set_xlabel('Returns') plt.show()
def underwater_plot(returns): fig = plt.figure(facecolor='white') ax = pf.plot_drawdown_underwater(returns) plt.savefig('underwater_plot.png')
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() fig.set_size_inches(15,5) pf.create_interesting_times_tear_sheet(bt_returns)
def show_result(daily_return, period, benchmark_daily_return, benchmark_title): """ plot from daily return of strategy and benchmark input --------------------------- daily_return: daily return of strategy benchmark_daily_return: daily return of benchmark benchmark_title: title of benchmark output --------------------------- return: None """ daily_return.dropna(inplace=True) benchmark_daily_return.dropna(inplace=True) sharpe_ratio, max_drawdown, annual_return, _, total_return = utils.metrics( daily_return, period=period) bench_sharpe, bench_max_drawdown, bench_annual_return, _, bench_total_return = utils.metrics( benchmark_daily_return) metrics_dict = { "sharpe": sharpe_ratio, "max_drawdown": max_drawdown, "annual_return": annual_return, "total_return": total_return, "benchmark_sharpe": bench_sharpe, "benchmark_max_drawdown": bench_max_drawdown, "benchmark_annual_return": bench_annual_return, "benchmark_total_return": bench_total_return } font_size = 15 value_font_size = 12 label_height, value_height = 0.8, 0.6 label_height2, value_height2 = 0.35, 0.15 red = "#aa4643" blue = "#4572a7" black = "#000000" fig_data = [ (0.00, label_height, value_height, "Total Returns", "{0:.3%}".format(metrics_dict["total_return"]), red, black), (0.00, label_height2, value_height2, "Benchmark Total", "{0:.3%}".format(metrics_dict["benchmark_total_return"]), blue, black), (0.25, label_height, value_height, "Annual Returns", "{0:.3%}".format(metrics_dict["annual_return"]), red, black), (0.25, label_height2, value_height2, "Benchmark Annual", "{0:.3%}".format(metrics_dict["benchmark_annual_return"]), blue, black), (0.50, label_height, value_height, "Sharpe", "{0:.4}".format(metrics_dict["sharpe"]), red, black), (0.50, label_height2, value_height2, "Benchmark Sharpe", "{0:.4}".format(metrics_dict["benchmark_sharpe"]), blue, black), (0.75, label_height, value_height, "MaxDrawdown", "{0:.4}".format(metrics_dict["max_drawdown"]), red, black), (0.75, label_height2, value_height2, "Benchmark MaxDrawdown", "{0:.4}".format(metrics_dict["benchmark_max_drawdown"]), blue, black), ] f, (ax1, ax2, ax3) = plt.subplots(3, figsize=(12, 8)) ax1.axis('off') for x, y1, y2, label, value, label_color, value_color in fig_data: ax1.text(x, y1, label, color=label_color, fontsize=font_size) ax1.text(x, y2, value, color=value_color, fontsize=value_font_size) ax2.set_title("Net value") ax2.set_xticklabels('') ax2.plot((1 + benchmark_daily_return).index, (1 + benchmark_daily_return).cumprod(), label=benchmark_title) ax2.plot((1 + daily_return).index, (1 + daily_return).cumprod(), label='Net value') ax2.legend() ax3 = pf.plot_drawdown_underwater(daily_return) plt.show()
############################ 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)
# E. Summary Statistics on performance of strategy xtickrange = pd.date_range(allcumReturns.index[0], end, freq="Q") ytickrange = np.arange(0.75, 1.85, 0.1) ax = allcumReturns.plot(title="Pure and Blended Strategy vs Benchmarks") ax.set(xlabel="Date", ylabel="Cumulative Return", xticks=xtickrange, yticks=ytickrange) ax.yaxis.grid(True) legend = ax.legend(loc="lower right") plt.savefig('Pure and Blended Strategy vs Benchmarks.png', bbox_inches='tight') plt.close() # Drawdown Charts ax1 = pf.plot_drawdown_underwater(benchReturns['Port']) ax1.set(title="Strategy portfolio Drawdowns", xlabel="Date", ylabel="Percentage Down from Peak", xticks=xtickrange) plt.savefig('Strategy Drawdowns.png', bbox_inches='tight') plt.close() ax2 = pf.plot_drawdown_underwater(benchReturns['50/50 SPY Port']) ax2.set(title="Blended portfolio Drawdowns", xlabel="Date", ylabel="Percentage Down from Peak", xticks=xtickrange) plt.savefig('Blended Drawdowns.png', bbox_inches='tight') plt.close()
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)