def test_run_period(): target = mock.MagicMock() dts = pd.date_range('2010-01-01', periods=35) data = pd.DataFrame(index=dts, columns=['c1', 'c2'], data=100) algo = algos.RunPeriod() # adds the initial day backtest = bt.Backtest( bt.Strategy('', [algo]), data ) target.data = backtest.data dts = target.data.index target.now = None assert not algo(target) # run on first date target.now = dts[0] assert not algo(target) # run on first supplied date target.now = dts[1] assert algo(target) # run on last date target.now = dts[len(dts) - 1] assert not algo(target) algo = algos.RunPeriod( run_on_first_date=False, run_on_end_of_period=True, run_on_last_date=True ) # adds the initial day backtest = bt.Backtest( bt.Strategy('', [algo]), data ) target.data = backtest.data dts = target.data.index # run on first date target.now = dts[0] assert not algo(target) # first supplied date target.now = dts[1] assert not algo(target) # run on last date target.now = dts[len(dts) - 1] assert algo(target) # date not in index target.now = datetime(2009, 2, 15) assert not algo(target)
def abovema_trainandtest(tickers, sma=50, start_train='06-01-2015', end_train='05-31-2017', start_test='06-01-2017', end_test='05-31-2019', name1='above_sma50_train', name2='above_sma50_test'): #training test data_train = bt.get(tickers, start=start_train, end=end_train) sma_train = data_train.rolling(sma).mean() signal = data_train > sma_train s = bt.Strategy(name1, [ bt.algos.SelectWhere(signal), bt.algos.WeighEqually(), bt.algos.Rebalance() ]) #testing set data_test = bt.get(tickers, start=start_test, end=end_test) sma_test = data_test.rolling(sma).mean() signal2 = data_test > sma_test s2 = bt.Strategy(name2, [ bt.algos.SelectWhere(signal2), bt.algos.WeighEqually(), bt.algos.Rebalance() ]) return (bt.Backtest(s, data_train), bt.Backtest(s2, data_test))
def comb_strat_settings_from_ml_prob(test_prob_dict, cut_num_dict, bt_fromdate, df_prc, shift_flag=False, comb_only=False, \ trade_cost=0., ls_target_weight=0.5): weight_sig_data_dict = {} strats = [] fsets = list(test_prob_dict.keys()) weight_divisor = 1. / len(fsets) allidx = list(test_prob_dict[fsets[0]].index) codesToLoad = list(test_prob_dict[fsets[0]].columns) comb_sig = pd.DataFrame(0., index=allidx, columns=codesToLoad).loc[bt_fromdate:] for fset in fsets: print(fset) sig_data = qcut_signal(test_prob_dict[fset], cut_num_dict[fset], test_prob_dict[fset].index[0]) sig_data = sig_data.pivot(index='tdate', columns='code', values='value') sig_data.index = pd.to_datetime(sig_data.index) long_sig = cut_num_dict[fset] * 1. - 1. short_sig = 0. # do below if you want to check lagging effect if shift_flag: sig_data = sig_data.reindex(df_prc.index).shift(1).dropna( axis=0, how='all') weight_sig_data_dict[fset] = sig_data.copy().apply( sig_to_weight, axis=1, args=(long_sig, short_sig, ls_target_weight)).loc[bt_fromdate:] if not comb_only: s = bt.Strategy(fset, [ bt.algos.RunOnDate(*weight_sig_data_dict[fset].index), bt.algos.WeighTarget(weight_sig_data_dict[fset]), bt.algos.Rebalance() ]) strats.append(bt.Backtest(s, df_prc.loc[weight_sig_data_dict[fset].index[0]:].fillna(method='ffill'), initial_capital=10.**9, \ commissions=lambda q, p: abs(q*p)*trade_cost)) tmp_sig_data = weight_sig_data_dict[fset].loc[ bt_fromdate:] * weight_divisor comb_sig = comb_sig.add(tmp_sig_data.fillna(0.), fill_value=0.) weight_sig_data_dict[ 'comb'] = comb_sig #[df_prc.loc[comb_sig.index, comb_sig.columns].notnull()] weight_sig_data_dict['comb'].fillna(0, inplace=True) s = bt.Strategy('comb', [ bt.algos.RunOnDate(*weight_sig_data_dict['comb'].index), bt.algos.WeighTarget(weight_sig_data_dict['comb']), bt.algos.Rebalance() ]) strats.append(bt.Backtest(s, df_prc.loc[weight_sig_data_dict['comb'].index[0]:].fillna(method='ffill').fillna(0), initial_capital=10.**9, \ commissions=lambda q, p: abs(q*p)*trade_cost)) return strats, weight_sig_data_dict
def test_run_yearly(): dts = pd.date_range('2010-01-01', periods=367) data = pd.DataFrame(index=dts, columns=['c1', 'c2'], data=100) target = mock.MagicMock() target.data = data algo = algos.RunYearly() # adds the initial day backtest = bt.Backtest(bt.Strategy('', [algo]), data) target.data = backtest.data # end of year target.now = dts[364] assert not algo(target) # new year target.now = dts[365] assert algo(target) algo = algos.RunYearly(run_on_first_date=False, run_on_end_of_period=True, run_on_last_date=True) # adds the initial day backtest = bt.Backtest(bt.Strategy('', [algo]), data) target.data = backtest.data # end of year target.now = dts[364] assert algo(target) # new year target.now = dts[365] assert not algo(target)
def test_run_quarterly(): dts = pd.date_range('2010-01-01', periods=367) data = pd.DataFrame(index=dts, columns=['c1', 'c2'], data=100) target = mock.MagicMock() target.data = data algo = algos.RunQuarterly() # adds the initial day backtest = bt.Backtest( bt.Strategy('', [algo]), data ) target.data = backtest.data # end of quarter target.now = dts[89] assert not algo(target) # new quarter target.now = dts[90] assert algo(target) algo = algos.RunQuarterly( run_on_first_date=False, run_on_end_of_period=True, run_on_last_date=True ) # adds the initial day backtest = bt.Backtest( bt.Strategy('', [algo]), data ) target.data = backtest.data # end of quarter target.now = dts[89] assert algo(target) # new quarter target.now = dts[90] assert not algo(target) dts = pd.DatetimeIndex([datetime(2016, 1, 3), datetime(2017, 1, 8), datetime(2018, 1, 7)]) data = pd.DataFrame(index=dts, columns=['c1', 'c2'], data=100) # adds the initial day backtest = bt.Backtest( bt.Strategy('', [algo]), data ) target.data = backtest.data # check next year target.now = dts[1] assert algo(target)
def buy_and_hold(ticker: str, start: Union[str, datetime], name: str): """ Generates a backtest object for the given ticker Parameters ---------- ticker: str Stock to test start: Union[str, datetime] Backtest start date. Can be either string or datetime name: Name of the backtest (for labeling purposes) Returns ------- bt.Backtest object for buy and hold strategy """ prices = bt.get(ticker, start=start) bt_strategy = bt.Strategy( name, [ bt.algos.RunOnce(), bt.algos.SelectAll(), bt.algos.WeighEqually(), bt.algos.Rebalance(), ], ) return bt.Backtest(bt_strategy, prices)
def SMA_cross(data): sma50 = data.rolling(50).mean() sma200 = data.rolling(200).mean() tw = sma200.copy() tw[sma50 > sma200] = 1.0 tw[sma50 <= sma200] = -1.0 tw[sma200.isnull()] = 0.0 tmp = bt.merge(tw, data, sma50, sma200) tmp.columns = ["tw", "price", "sma50", "sma200"] # tmp.columns = ['tw', 'price', 'sma50', 'sma200'] ax = tmp.plot(figsize = (15, 5), secondary_y = ["tw"]) plt.savefig("smacross.png") ma_cross = bt.Strategy("ma_cross", [WeighTarget(tw), bt.algos.Rebalance() ]) t = bt.Backtest(ma_cross, data) res = bt.run(t) res.display() res.plot() plt.savefig("smacross_res")
def run(): df_price, df_thred = transfer() signal = df_thred > 0.7 for col in range(signal.shape[1]): eng = 0 for i in range(signal.shape[0]): if signal.iloc[i, col]: eng = 4 elif eng > 0: signal.iloc[i, col] = True eng -= 1 else: pass # first we create the Strategy s = bt.Strategy('above50sma', [SelectWhere(signal), bt.algos.WeighEqually(), bt.algos.Rebalance()]) # now we create the Backtest t = bt.Backtest(s, df_price, initial_capital=9000) # and let's run it! res = bt.run(t) res.plot('d') ser = res._get_series('d').rebase() plot = ser.plot() fig = plot.get_figure() fig.savefig(os.path.join(root, "report", "backtest.png"))
def test_turnover(): dts = pd.date_range('2010-01-01', periods=5) data = pd.DataFrame(index=dts, columns=['a', 'b'], data=100) data['a'][dts[1]] = 105 data['b'][dts[1]] = 95 data['a'][dts[2]] = 110 data['b'][dts[2]] = 90 data['a'][dts[3]] = 115 data['b'][dts[3]] = 85 s = bt.Strategy('s', [bt.algos.SelectAll(), bt.algos.WeighEqually(), bt.algos.Rebalance()]) t = bt.Backtest(s, data, commissions=lambda x, y: 0, progress_bar=False) res = bt.run(t) t = res.backtests['s'] # these numbers were (tediously) calculated in excel assert np.allclose(t.turnover[dts[0]], 0. / 1000000) assert np.allclose(t.turnover[dts[1]], 24985. / 1000000) assert np.allclose(t.turnover[dts[2]], 24970. / 997490) assert np.allclose(t.turnover[dts[3]], 25160. / 992455) assert np.allclose(t.turnover[dts[4]], 76100. / 1015285)
def main(): '''entry point''' # Get Test Data with all fields symbol_list = ['BTC', 'ETH'] history = coinrepo.get_coinhistory(symbol_list) history = history.set_index('Date') # Pivot to have only price as timeseries pricehistory = history.pivot(columns='Symbol')['Price'] # Create the strategy s = bt.Strategy('s1', [ bt.algos.RunMonthly(), bt.algos.SelectAll(), bt.algos.WeighEqually(), bt.algos.Rebalance() ]) # create a backtest and run it test = bt.Backtest(s, pricehistory) res = bt.run(test) res.display() # Save figures plot = pricehistory.plot(figsize=(15, 5)) fig = plot.get_figure() fig.savefig("price.png") plot1 = res.plot_weights(figsize=(15, 5)) fig1 = plot1.get_figure() fig1.savefig("bt_rest.png")
def SMA(data): sma = data.rolling(50).mean() plot = bt.merge(data, sma).plot(figsize=(15, 5)) plt.savefig("sma.png") # 建立策略 s = bt.Strategy("above50sma", [SelectWhere(data > sma), bt.algos.WeighEqually(), bt.algos.Rebalance() ]) # 建立回测 t = bt.Backtest(s, data) # 执行回测 res = bt.run(t) # 输出结果 res.display() res.plot() plt.savefig("sma_result.png") # 多种策略的测试 sma10 = above_sma(data, sma_per = 10, name = "sma10") sma20 = above_sma(data, sma_per = 10, name = "sma20") sma40 = above_sma(data, sma_per = 10, name = "sma40") base_line = baseTest(data) # 一起运行回测 res2 = bt.run(sma10, sma20, sma40, base_line) # 输出结果 res2.display() res2.plot() plt.savefig("sma.png") plt.savefig("multi_sma_result.png")
def run(): """ Run the code that illustrates the pairs trading strategy """ data = make_data() # Define the "entry" strategy of the trade. In this case, we give each asset unit weight and trade it trade_entry = bt.AlgoStack( bt.algos.RunOnce(), WeighPair(1.), bt.algos.Rebalance() ) # Define the "exit" strategy of the trade. Here we exit when we cross either an upper/lower # threshold on the price of the strategy, or hold it for a fixed length of time. trade_exit = bt.AlgoStack( bt.algos.Or( [PriceCompare( 96., is_greater=False ), PriceCompare( 104., is_greater=True), bt.algos.RunAfterDays( 5 ) ] ), ClosePositions() ) # Combine the entry, exit and debug algos for each trade trade_algos = [ bt.algos.Or( [ trade_entry, trade_exit, DebugTradeLevel() ] )] # Define the strategy for the master portfolio. strategy_algos = [ PairsSignal( threshold = 4., indicator_name = 'my_indicator' ), SetupPairsTrades( trade_algos ), SizePairsTrades( pct_of_capital = 0.2 ), DebugPortfolioLevel() ] # Build and run the strategy strategy = bt.Strategy( 'PairsStrategy', strategy_algos ) test = bt.Backtest( strategy, data, additional_data={'my_indicator':data} ) out = bt.run( test ) print(out.stats) return out
def main(): days = 5 change = .02 with open('ticker_sectors.data', 'rb') as f: tickerSectors = pickle.load(f) companies = tickerSectors[0] companyList = 'aos' for i in range(1, 10): companyList = companyList + ',' + companies[i].lower() print(companyList) data = bt.get(companyList, start='2014-01-01') print(data) weights = getPredictions(days, change) print(weights) s = bt.Strategy('s1', [ bt.algos.RunWeekly(), bt.algos.SelectAll(), bt.algos.WeighTarget(weights), bt.algos.Rebalance() ]) test = bt.Backtest(s, data) res = bt.run(test) res.plot() res.display() print("GOOD")
def test_30_min_data(): names = ['foo'] dates = pd.date_range(start='2017-01-01', end='2017-12-31', freq='30min') n = len(dates) rdf = pd.DataFrame(np.zeros((n, len(names))), index=dates, columns=names) np.random.seed(1) rdf[names[0]] = np.random.normal(loc=0.1 / n, scale=0.2 / np.sqrt(n), size=n) pdf = 100 * np.cumprod(1 + rdf) sma50 = pdf.rolling(50).mean() sma200 = pdf.rolling(200).mean() tw = sma200.copy() tw[sma50 > sma200] = 1.0 tw[sma50 <= sma200] = -1.0 tw[sma200.isnull()] = 0.0 ma_cross = bt.Strategy('ma_cross', [bt.algos.WeighTarget(tw), bt.algos.Rebalance()]) t = bt.Backtest(ma_cross, pdf, progress_bar=False) res = bt.run(t) wait = 1
def test_backtest_copies_strategy(): s = mock.MagicMock() data = pd.DataFrame(index=pd.date_range('2010-01-01', periods=5), columns=['a', 'b'], data=100) actual = bt.Backtest(s, data, progress_bar=False) assert id(s) != id(actual.strategy)
def above_sma(data, sma_per = 50, name = "above_sma"): sma = data.rolling(sma_per).mean() s = bt.Strategy(name, [bt.algos.SelectWhere(data > sma), bt.algos.WeighEqually(), bt.algos.Rebalance() ]) return bt.Backtest(s, data)
def baseTest(data): s = bt.Strategy("base_line", [bt.algos.RunOnce(), bt.algos.SelectAll(), bt.algos.WeighEqually(), bt.algos.Rebalance() ]) return bt.Backtest(s, data)
def test_backtest_auto_name(): s = mock.MagicMock() s.name = 's' data = pd.DataFrame(index=pd.date_range('2010-01-01', periods=5), columns=['a', 'b'], data=100) actual = bt.Backtest(s, data, progress_bar=False) assert actual.name == 's'
def test_Results_helper_functions(): names = ['foo', 'bar'] dates = pd.date_range(start='2017-01-01', end='2017-12-31', freq=pd.tseries.offsets.BDay()) n = len(dates) rdf = pd.DataFrame( np.zeros((n, len(names))), index=dates, columns=names ) np.random.seed(1) rdf[names[0]] = np.random.normal(loc=0.1 / n, scale=0.2 / np.sqrt(n), size=n) rdf[names[1]] = np.random.normal(loc=0.04 / n, scale=0.05 / np.sqrt(n), size=n) pdf = 100 * np.cumprod(1 + rdf) # algo to fire on the beginning of every month and to run on the first date runDailyAlgo = bt.algos.RunDaily( run_on_first_date=True ) # algo to set the weights # it will only run when runMonthlyAlgo returns true # which only happens on the first of every month weights = pd.Series([0.6, 0.4], index=rdf.columns) weighSpecifiedAlgo = bt.algos.WeighSpecified(**weights) # algo to rebalance the current weights to weights set by weighSpecified # will only run when weighSpecifiedAlgo returns true # which happens every time it runs rebalAlgo = bt.algos.Rebalance() # a strategy that rebalances monthly to specified weights strat = bt.Strategy('static', [ runDailyAlgo, weighSpecifiedAlgo, rebalAlgo ] ) backtest = bt.Backtest( strat, pdf, integer_positions=False, progress_bar=False ) res = bt.run(backtest) assert(type(res.get_security_weights()) is pd.DataFrame) assert (type(res.get_transactions()) is pd.DataFrame) assert (type(res.get_weights()) is pd.DataFrame)
def make_target_weight_backtest(stock_data, signal, name, progress_bar=True): s = bt.Strategy(name, [ bt.algos.bt.algos.RunOnDate(*signal.index), bt.algos.bt.algos.WeighTarget(signal), bt.algos.Rebalance() ]) return bt.Backtest(s, stock_data, initial_capital=10.**9, progress_bar=progress_bar)
def original_backtest(data, name='original_backtest'): s = bt.Strategy(name, [ bt.algos.RunWeekly(), bt.algos.SelectAll(), bt.algos.SelectMomentum(n=1, lookback=pd.DateOffset(days=1)), bt.algos.WeighEqually(), bt.algos.Rebalance() ]) return bt.Backtest(s, data)
def test_backtest_dates_set(): s = mock.MagicMock() data = pd.DataFrame(index=pd.date_range('2010-01-01', periods=5), columns=['a', 'b'], data=100) actual = bt.Backtest(s, data, progress_bar=False) assert len(actual.dates) == len(data.index) assert actual.dates[0] == data.index[0] assert actual.dates[-1] == data.index[-1]
def run_backtest_from_positions(predictions_df1, predictions_df2, predictions_df3): data = pd.read_excel(r'data.xlsx', index_col = 0) ###ML SOLUTION### #Expand positions_df to daily frequency positions_df1 = pd.DataFrame(index = data.index) positions_df1 = pd.merge(positions_df1, predictions_df1, how = 'left', left_index = True, right_index = True) positions_df1.fillna(method = 'ffill', inplace = True) positions_df1.dropna(inplace=True) positions_df1 = positions_df1.divide(((positions_df1.abs()).sum(axis=1)), axis = 'index') #Match starting date on data_df data1 = data.loc[data.index.isin(positions_df1.index),:].copy() #Create strategy object s1 = bt.Strategy('ML Solution', [bt.algos.WeighTarget(positions_df1), bt.algos.Rebalance()]) t1 = bt.Backtest(s1, data1) ###BASELINE NAIVE### positions_df2 = pd.DataFrame(index = data.index) positions_df2 = pd.merge(positions_df2, predictions_df2, how = 'left', left_index = True, right_index = True) positions_df2.fillna(method = 'ffill', inplace = True) positions_df2.dropna(inplace=True) positions_df2 = positions_df2.divide(((positions_df2.abs()).sum(axis=1)), axis = 'index') #Match starting date on data_df data2 = data.loc[data.index.isin(positions_df2.index),:].copy() #Create strategy object s2 = bt.Strategy('Baseline - Naive', [bt.algos.WeighTarget(positions_df2), bt.algos.Rebalance()]) t2 = bt.Backtest(s2, data2) ###BASELINE QUADRANT### positions_df3 = pd.DataFrame(index = data.index) positions_df3 = pd.merge(positions_df3, predictions_df3, how = 'left', left_index = True, right_index = True) positions_df3.fillna(method = 'ffill', inplace = True) positions_df3.dropna(inplace=True) positions_df3 = positions_df3.divide(((positions_df3.abs()).sum(axis=1)), axis = 'index') #Match starting date on data_df data3 = data.loc[data.index.isin(positions_df3.index),:].copy() #Create strategy object s3 = bt.Strategy('Baseline - Quadrant', [bt.algos.WeighTarget(positions_df3), bt.algos.Rebalance()]) t3 = bt.Backtest(s3, data3) #Run backtest res = bt.run(t1, t2, t3) return res
def strat_settings_from_ml_prob(s_name, test_prob, cut_num, bt_fromdate, df_prc, shift_flag=False, ls_only=False, \ trade_cost=0., target_weight=1.0, ls_target_weight=0.5): sig_data = qcut_signal(test_prob, cut_num, test_prob.index[0]) sig_data = sig_data.pivot(index='tdate', columns='code', values='value') sig_data.index = pd.to_datetime(sig_data.index) long_sig = cut_num * 1. - 1. short_sig = 0. # do below if you want to check lagging effect if shift_flag: sig_data = sig_data.reindex(df_prc.index).shift(1).dropna(axis=0, how='all') strats = [] if not ls_only: for signal in range(0, int(max(long_sig, short_sig)) + 1): weight_sig_data = sig_data.copy().apply( long_only_sig_to_weight, axis=1, args=(signal, target_weight)).loc[bt_fromdate:] s = bt.Strategy(s_name + '_' + str(signal), [ bt.algos.RunOnDate(*weight_sig_data.index), bt.algos.WeighTarget(weight_sig_data), bt.algos.Rebalance() ]) strats.append(bt.Backtest(s, df_prc.loc[weight_sig_data.index[0]:].fillna(method='ffill'), initial_capital=10.**9, \ commissions=lambda q, p: abs(q*p)*trade_cost)) weight_sig_data = sig_data.copy().apply( sig_to_weight, axis=1, args=(long_sig, short_sig, ls_target_weight)).loc[bt_fromdate:] s = bt.Strategy(s_name + '_ls', [ bt.algos.RunOnDate(*weight_sig_data.index), bt.algos.WeighTarget(weight_sig_data), bt.algos.Rebalance() ]) strats.append(bt.Backtest(s, df_prc.loc[weight_sig_data.index[0]:].fillna(method='ffill'), initial_capital=10.**9, \ commissions=lambda q, p: abs(q*p)*trade_cost)) return strats, weight_sig_data
def test_initial_capital_set(): s = mock.MagicMock() data = pd.DataFrame(index=pd.date_range('2010-01-01', periods=5), columns=['a', 'b'], data=100) actual = bt.Backtest(s, data, initial_capital=302, progress_bar=False) actual.run() s = actual.strategy s.adjust.assert_called_with(302)
def make_backtest_by_signal(stock_data, signal, name, progress_bar=False): s = bt.Strategy(name, [ bt.algos.bt.algos.RunOnDate(*signal.index), bt.algos.bt.algos.SelectWhere(signal), bt.algos.WeighEqually(), bt.algos.Rebalance() ]) return bt.Backtest(s, stock_data, initial_capital=10.**9, progress_bar=progress_bar)
def benchmark_cacu(benchmark, name='bench_bitcoin'): s = bt.Strategy(name, [ bt.algos.RunOnce(), bt.algos.SelectAll(), bt.algos.WeighEqually(), bt.algos.Rebalance() ]) data = pd.DataFrame(self.data[benchmark]) print(data.head()) self.benchmark = benchmark return bt.Backtest(s, data)
def buy_and_hold(ticker, name, start='2020-2-1', end='2020-11-1'): # Get the data price_data = bt.get(ticker, start=start, end=end) # Define the benchmark strategy bt_strategy = bt.Strategy(name, [ bt.algos.RunOnce(), bt.algos.SelectAll(), bt.algos.WeighEqually(), bt.algos.Rebalance() ]) # Return the backtest return bt.Backtest(bt_strategy, price_data)
def signal_strategy(ticker, period, name, start='2020-2-1', end='2020-11-1'): # Get the data and calculate SMA price_data = bt.get(ticker, start=start, end=end) sma = price_data.rolling(period).mean() # Define the signal-based trategy bt_strategy = bt.Strategy(name, [ bt.algos.SelectWhere(price_data > sma), bt.algos.WeighEqually(), bt.algos.Rebalance() ]) # Return the backtest return bt.Backtest(bt_strategy, price_data)
def long_only(df, name='long_only'): df_data = df.copy() s = bt.Strategy(name, [ bt.algos.RunOnce(), bt.algos.SelectAll(), bt.algos.WeighEqually(), bt.algos.Rebalance() ]) return bt.Backtest(s, df_data)