16 KiB
16 KiB
Basic RSI strategy¶
Single backtest¶
In [ ]:
from vectorbtpro import * # whats_imported() vbt.settings.set_theme('dark')
In [ ]:
data = vbt.BinanceData.pull('BTCUSDT') data
In [ ]:
data.data['BTCUSDT'].vbt.ohlcv.plot().show_svg()
In [ ]:
data.data['BTCUSDT'].info()
In [ ]:
open_price = data.get('Open') close_price = data.get('Close')
In [ ]:
vbt.IF.list_indicators("RSI*")
In [ ]:
vbt.indicator("talib:RSI")
In [ ]:
vbt.RSI
In [ ]:
vbt.talib('RSI')
In [ ]:
vbt.ta('RSIIndicator')
In [ ]:
vbt.pandas_ta('RSI')
In [ ]:
print(vbt.format_func(vbt.RSI.run))
In [ ]:
rsi = vbt.RSI.run(open_price) rsi
In [ ]:
rsi.rsi
In [ ]:
entries = rsi.rsi.vbt.crossed_below(30) entries
In [ ]:
exits = rsi.rsi.vbt.crossed_above(70) exits
In [ ]:
entries = rsi.rsi_crossed_below(30) exits = rsi.rsi_crossed_above(70)
In [ ]:
def plot_rsi(rsi, entries, exits): fig = rsi.plot() entries.vbt.signals.plot_as_entries(rsi.rsi, fig=fig) exits.vbt.signals.plot_as_exits(rsi.rsi, fig=fig) return fig
In [ ]:
plot_rsi(rsi, entries, exits).show_svg()
In [ ]:
clean_entries, clean_exits = entries.vbt.signals.clean(exits) plot_rsi(rsi, clean_entries, clean_exits).show_svg()
In [ ]:
clean_entries.vbt.signals.total()
In [ ]:
clean_exits.vbt.signals.total()
In [ ]:
ranges = clean_entries.vbt.signals.between_ranges(target=clean_exits) ranges.duration.mean(wrap_kwargs=dict(to_timedelta=True))
In [ ]:
pf = vbt.Portfolio.from_signals( close=close_price, entries=clean_entries, exits=clean_exits, size=100, size_type='value', init_cash='auto' ) pf
In [ ]:
pf.stats()
In [ ]:
pf.plot(settings=dict(bm_returns=False)).show_svg()
Multiple backtests¶
Using for-loop¶
In [ ]:
def test_rsi(window=14, wtype="wilder", lower_th=30, upper_th=70): rsi = vbt.RSI.run(open_price, window=window, wtype=wtype) entries = rsi.rsi_crossed_below(lower_th) exits = rsi.rsi_crossed_above(upper_th) pf = vbt.Portfolio.from_signals( close=close_price, entries=entries, exits=exits, size=100, size_type='value', init_cash='auto') return pf.stats([ 'total_return', 'total_trades', 'win_rate', 'expectancy' ])
In [ ]:
test_rsi()
In [ ]:
test_rsi(lower_th=20, upper_th=80)
In [ ]:
from itertools import product lower_ths = range(20, 31) upper_ths = range(70, 81) th_combs = list(product(lower_ths, upper_ths)) len(th_combs)
In [ ]:
comb_stats = [ test_rsi(lower_th=lower_th, upper_th=upper_th) for lower_th, upper_th in th_combs ]
In [ ]:
comb_stats_df = pd.DataFrame(comb_stats) print(comb_stats_df)
In [ ]:
comb_stats_df.index = pd.MultiIndex.from_tuples( th_combs, names=['lower_th', 'upper_th']) print(comb_stats_df)
In [ ]:
comb_stats_df['Expectancy'].vbt.heatmap().show_svg()
Using columns¶
In [ ]:
windows = list(range(8, 21)) wtypes = ["simple", "exp", "wilder"] lower_ths = list(range(20, 31)) upper_ths = list(range(70, 81))
In [ ]:
rsi = vbt.RSI.run( open_price, window=windows, wtype=wtypes, param_product=True) rsi.rsi.columns
In [ ]:
lower_ths_prod, upper_ths_prod = zip(*product(lower_ths, upper_ths)) len(lower_ths_prod)
In [ ]:
len(upper_ths_prod)
In [ ]:
lower_th_index = vbt.Param(lower_ths_prod, name='lower_th') entries = rsi.rsi_crossed_below(lower_th_index) entries.columns
In [ ]:
upper_th_index = vbt.Param(upper_ths_prod, name='upper_th') exits = rsi.rsi_crossed_above(upper_th_index) exits.columns
In [ ]:
pf = vbt.Portfolio.from_signals( close=close_price, entries=entries, exits=exits, size=100, size_type='value', init_cash='auto' ) pf
In [ ]:
stats_df = pf.stats([ 'total_return', 'total_trades', 'win_rate', 'expectancy' ], agg_func=None) print(stats_df)
In [ ]:
>>> print(pf.getsize())
In [ ]:
>>> np.product(pf.wrapper.shape) * 8 / 1024 / 1024
In [ ]:
stats_df['Expectancy'].groupby('rsi_window').mean()
In [ ]:
print(stats_df.sort_values(by='Expectancy', ascending=False).head())
In [ ]:
pf[(22, 80, 20, "wilder")].plot_value().show_svg()
In [ ]:
data = vbt.BinanceData.pull(['BTCUSDT', 'ETHUSDT'])
In [ ]:
open_price = data.get('Open') close_price = data.get('Close')
In [ ]:
rsi = vbt.RSI.run( open_price, window=windows, wtype=wtypes, param_product=True) entries = rsi.rsi_crossed_below(lower_th_index) exits = rsi.rsi_crossed_above(upper_th_index) pf = vbt.Portfolio.from_signals( close=close_price, entries=entries, exits=exits, size=100, size_type='value', init_cash='auto' ) stats_df = pf.stats([ 'total_return', 'total_trades', 'win_rate', 'expectancy' ], agg_func=None)
In [ ]:
stats_df.index
In [ ]:
eth_mask = stats_df.index.get_level_values('symbol') == 'ETHUSDT' btc_mask = stats_df.index.get_level_values('symbol') == 'BTCUSDT' pd.DataFrame({ 'ETHUSDT': stats_df[eth_mask]['Expectancy'].values, 'BTCUSDT': stats_df[btc_mask]['Expectancy'].values }).vbt.histplot(xaxis=dict(title="Expectancy")).show_svg()
In [ ]: