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 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")
import bt import talib # Construct the signal signal[stock_rsi > 70] = -1 signal[stock_rsi < 30] = 1 signal[(stock_rsi <= 70) & (stock_rsi >= 30)] = 0 # Merge the data combined_df = bt.merge(signal, price_data) combined_df.columns = ['signal', 'Price'] combined_df.plot(secondary_y=['signal']) plt.show() # Define the strategy bt_strategy = bt.Strategy('RSI_MeanReversion', [bt.algos.WeighTarget(signal), bt.algos.Rebalance()]) # Create the backtest and run it bt_backtest = bt.Backtest(bt_strategy, price_data) bt_result = bt.run(bt_backtest) # Plot the backtest result bt_result.plot(title='Backtest result') plt.show()
### Finds optimal SMA cross settings and return percentage # [best_low, best_high, best_percentage] = sma_cross_optimal_values(data, sma_low_bot, sma_low_top, sma_high_bot, sma_high_top, within_percentage) ### Get SMA based on the data # sma_low_plot = pd.rolling_mean(data, best_low) # sma_high_plot = pd.rolling_mean(data, best_high) # # plot = bt.merge(data, sma_low_plot, sma_high_plot).plot() ############################ ### Finds optimal SMA value for price crossing the SMA line # [best_sma, best_percentage] = above_sma_optimal_value(data, 5, sma_high_top, within_percentage) ### Get SMA based on the data # sma_best_plot = pd.rolling_mean(data, best_sma) # Do final test to print full results test = above_sma(data, best_sma) results = bt.run(test) # Display graphical plot of the data plot = bt.merge(data, sma_best_plot).plot() results.plot() results.display_monthly_returns() results.display() # Necessary to show matlibplot graphic produced with res.plot() plt.show() results.values()
#all_loaded_data = load_data('600519,000858,601318,600036,603288,600276,600900,600887', do_normalize_data) all_loaded_data = load_data('600732', do_normalize_data) bench_data = load_data('sh000001', do_normalize_data) start_date = '20210501' end_date = '20210630' print(start_date, end_date) all_data = panel = create_dataframe(all_loaded_data, 'close') bench_data = create_dataframe(bench_data, 'close') panel = filter_dataframe(panel, start_date, end_date) bench_data = filter_dataframe(bench_data, start_date, end_date) bt.merge(panel).plot() plt.show() # create the strategy from strategy.rsi_25_75_talib import create_strategy from strategy.r3 import create_strategy as r3_create_strategy from strategy.sma import above_sma, long_only_ew from strategy.macd_talib import create_strategy as macd_create_strategy from strategy.ibs import create_strategy as ibs_create_strategy from strategy.ibs_rsi import create_strategy as ibs_rsi_create_strategy ss = bt.Strategy('s1', [ bt.algos.RunMonthly(), bt.algos.SelectAll(), bt.algos.WeighEqually(), bt.algos.Rebalance()
import bt import matplotlib.pyplot as plt # Construct the signal signal[EMA_short > EMA_long] = 1 signal[EMA_short < EMA_long] = -1 # Merge the data combined_df = bt.merge(signal, price_data, EMA_short, EMA_long) combined_df.columns = ['Signal', 'Price', 'EMA_short', 'EMA_long'] # Plot the signal, price and MAs combined_df.plot(secondary_y=['Signal']) plt.show() # Define the strategy bt_strategy = bt.Strategy('EMA_crossover', [bt.algos.WeighTarget(signal), bt.algos.Rebalance()]) # Create the backtest and run it bt_backtest = bt.Backtest(bt_strategy, price_data) bt_result = bt.run(bt_backtest) # Plot the backtest result bt_result.plot(title='Backtest result') plt.show()
def rsi_strat(ticker: str, start_date: Union[datetime, str], other_args: List[str]): """Strategy that buys when the stock is less than a threshold and shorts when it exceeds a threshold. Parameters ---------- ticker : str Stock to test start : Union[str, datetime] Backtest start date. Can be either string or datetime other_args : List[str] List of argparse arguments """ parser = argparse.ArgumentParser( add_help=False, formatter_class=argparse.ArgumentDefaultsHelpFormatter, prog="rsi_strat", description="""Strategy that buys when the stock is less than a threshold and shorts when it exceeds a threshold.""", ) parser.add_argument( "-p", "--periods", dest="periods", help="Number of periods for RSI calculation", type=check_positive, default=14, ) parser.add_argument( "-u", "--high", default=70, dest="high", type=check_positive, help="High (upper) RSI Level", ) parser.add_argument("-l", "--low", default=30, dest="low", type=check_positive, help="Low RSI Level") parser.add_argument( "--spy", action="store_true", default=False, help="Flag to add spy hold comparison", dest="spy", ) parser.add_argument( "--no_bench", action="store_true", default=False, help="Flag to not show buy and hold comparison", dest="no_bench", ) parser.add_argument( "--no_short", action="store_false", default=True, dest="shortable", help="Flag that disables the short sell", ) try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return if ns_parser.high < ns_parser.low: print("Low RSI value is higher than Low RSI value\n") return ticker = ticker.lower() # prices = bt.get(ticker, start=start_date) prices = get_data(ticker, start_date) rsi = pd.DataFrame(ta.rsi(prices[ticker], ns_parser.periods)) rsi.columns = [ticker] signal = 0 * rsi.copy() signal[rsi > ns_parser.high] = -1 signal[rsi < ns_parser.low] = 1 signal[rsi.isnull()] = 0 merged_data = bt.merge(signal, prices) merged_data.columns = ["signal", "price"] bt_strategy = bt.Strategy( "RSI Reversion", [bt.algos.WeighTarget(signal), bt.algos.Rebalance()]) bt_backtest = bt.Backtest(bt_strategy, prices) if ns_parser.spy: spy_bt = buy_and_hold("spy", start_date, "SPY Hold") if ns_parser.no_bench: res = bt.run(bt_backtest, spy_bt) else: stock_bt = buy_and_hold(ticker, start_date, ticker.upper() + " Hold") res = bt.run(bt_backtest, spy_bt, stock_bt) else: if ns_parser.no_bench: res = bt.run(bt_backtest) else: stock_bt = buy_and_hold(ticker, start_date, ticker.upper() + " Hold") res = bt.run(bt_backtest, stock_bt) plot_bt(res, f"RSI Strategy between ({ns_parser.low}, {ns_parser.high})") print(res.display(), "\n") except Exception as e: print(e, "\n")
def ema_cross(ticker: str, start_date: Union[str, datetime], other_args: List[str]): """Strategy where we go long/short when EMA(short) is greater than/less than EMA(short) Parameters ---------- ticker : str Stock to test start : Union[str, datetime] Backtest start date. Can be either string or datetime other_args : List[str] List of argparse arguments """ parser = argparse.ArgumentParser( add_help=False, formatter_class=argparse.ArgumentDefaultsHelpFormatter, prog="ema_cross", description= "Cross between a long and a short Exponential Moving Average.", ) parser.add_argument( "-l", "--long", default=50, dest="long", type=check_positive, help="Long EMA period", ) parser.add_argument( "-s", "--short", default=20, dest="short", type=check_positive, help="Short EMA period", ) parser.add_argument( "--spy", action="store_true", default=False, help="Flag to add spy hold comparison", dest="spy", ) parser.add_argument( "--no_bench", action="store_true", default=False, help="Flag to not show buy and hold comparison", dest="no_bench", ) parser.add_argument( "--no_short", action="store_false", default=True, dest="shortable", help="Flag that disables the short sell", ) try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return if ns_parser.long < ns_parser.short: print("Short EMA period is longer than Long EMA period\n") return ticker = ticker.lower() # prices = bt.get(ticker, start=start_date) prices = get_data(ticker, start_date) short_ema = pd.DataFrame(ta.ema(prices[ticker], ns_parser.short)) short_ema.columns = [ticker] long_ema = pd.DataFrame(ta.ema(prices[ticker], ns_parser.long)) long_ema.columns = [ticker] # signals signals = long_ema.copy() signals[short_ema > long_ema] = 1.0 signals[short_ema <= long_ema] = -1.0 * ns_parser.shortable signals[long_ema.isnull()] = 0.0 combined_data = bt.merge(signals, prices, short_ema, long_ema) combined_data.columns = ["signal", "price", "ema_short", "ema_long"] bt_strategy = bt.Strategy( "EMA_Cross", [ bt.algos.WeighTarget(signals), bt.algos.Rebalance(), ], ) bt_backtest = bt.Backtest(bt_strategy, prices) if ns_parser.spy: spy_bt = buy_and_hold("spy", start_date, "SPY Hold") if ns_parser.no_bench: res = bt.run(bt_backtest, spy_bt) else: stock_bt = buy_and_hold(ticker, start_date, ticker.upper() + " Hold") res = bt.run(bt_backtest, spy_bt, stock_bt) else: if ns_parser.no_bench: res = bt.run(bt_backtest) else: stock_bt = buy_and_hold(ticker, start_date, ticker.upper() + " Hold") res = bt.run(bt_backtest, stock_bt) plot_bt(res, f"EMA Cross for EMA({ns_parser.short})/EMA({ns_parser.long})") print(res.display(), "\n") except Exception as e: print(e, "\n")
import bt import matplotlib matplotlib.get_backend() # download data from bt.algos import SelectWhere data = bt.get('aapl,msft', start='2016-01-01') # calculate moving average DataFrame using pandas' rolling_mean import pandas as pd # a rolling mean is a moving average, right? sma = pd.rolling_mean(data, 50) bt.merge(data, sma).plot(figsize=(15, 5)) signal = data > sma # first we create the Strategy s = bt.Strategy('above50sma', [SelectWhere(data > sma), bt.algos.WeighEqually(), bt.algos.Rebalance()]) # now we create the Backtest t = bt.Backtest(s, data) # and let's run it! res = bt.run(t) res.plot('d') print(type(res)) res.display()
name, [bt.algos.WeighTarget(tw), bt.algos.Rebalance()]) # Set up the backtest uvxy_dynamic = bt.Backtest(strategy_4_uvxy, strategy_4_data[['UVXY']], integer_positions=False) # Why integer positions? See UVXY head data print(strategy_4_data['UVXY'].head(10)) # Run the backtest res = bt.run(uvxy_dynamic, benchmark_test) # Once we ran the previous backtest, we can extract the prices data to create synthetic securities synthetic = bt.merge(res['uvxy_dynamic'].prices, res['long_spy'].prices) # This is our new data, which is essentially the equity curve of each sub-strategy we tested. # We can use this data to test our final strategy, just as before. strategy_4 = bt.Strategy('combined_uvxy_spy', [ bt.algos.SelectAll(), bt.algos.WeighSpecified(uvxy_dynamic=0.5, long_spy=0.5), bt.algos.Rebalance() ]) # Create and run t = bt.Backtest(strategy_4, synthetic, integer_positions=False) res = bt.run(t, benchmark_test) # Display summary statistics and plot the weights res.display()
if __name__ == "__main__": # 获取数据 # data = getData() #data = bt.get("spy", start = "2010-01-01") #print(data.head()) #print(data.describe()) # SMA(data) #SMA_cross(data) t1 = sma_cross("aapl", name = "aapl_mass_cross") t2 = sma_cross("msft", name = "msft_mass_cross") res = bt.run(t1, t2) data = bt.merge(res["aapl_mass_cross"].prices, res["msft_mass_cross"].prices) s = bt.Strategy('s', [bt.algos.SelectAll(), bt.algos.WeighInvVol(), bt.algos.Rebalance() ]) t = bt.Backtest(s, data) res = bt.run(t) res.display() res.plot() plt.savefig("multi_smacross.png") res.plot_weights() plt.savefig("multi_smacross_weights.png")
def rsi_strategy( ticker: str, df_stock: pd.DataFrame, periods: int, low_rsi: int, high_rsi: int, spy_bt: bool = True, no_bench: bool = False, shortable: bool = True, ) -> bt.backtest.Result: """Perform backtest for simple EMA strategy. Buys when price>EMA(l) Parameters ---------- ticker : str Stock ticker df_stock : pd.DataFrame Dataframe of prices periods : int Number of periods for RSI calculati low_rsi : int Low RSI value to buy hirh_rsi : int High RSI value to sell spy_bt : bool Boolean to add spy comparison no_bench : bool Boolean to not show buy and hold comparison shortable : bool Flag to disable the ability to short sell Returns ------- Result Backtest results """ ticker = ticker.lower() start_date = df_stock.index[0] prices = pd.DataFrame(df_stock["Adj Close"]) prices.columns = [ticker] rsi = pd.DataFrame(ta.rsi(prices[ticker], periods)) rsi.columns = [ticker] signal = 0 * rsi.copy() signal[rsi > high_rsi] = -1 * shortable signal[rsi < low_rsi] = 1 signal[rsi.isnull()] = 0 merged_data = bt.merge(signal, prices) merged_data.columns = ["signal", "price"] bt_strategy = bt.Strategy( "RSI Reversion", [bt.algos.WeighTarget(signal), bt.algos.Rebalance()]) bt_backtest = bt.Backtest(bt_strategy, prices) bt_backtest = bt.Backtest(bt_strategy, prices) backtests = [bt_backtest] if spy_bt: spy_bt = buy_and_hold("spy", start_date, "SPY Hold") backtests.append(spy_bt) if not no_bench: stock_bt = buy_and_hold(ticker, start_date, ticker.upper() + " Hold") backtests.append(stock_bt) res = bt.run(*backtests) return res
def ema_cross_strategy( ticker: str, df_stock: pd.DataFrame, short_length: int, long_length: int, spy_bt: bool = True, no_bench: bool = False, shortable: bool = True, ) -> bt.backtest.Result: """Perform backtest for simple EMA strategy. Buys when price>EMA(l) Parameters ---------- ticker : str Stock ticker df_stock : pd.DataFrame Dataframe of prices short_length : int Length of short ema window long_length : int Length of long ema window spy_bt : bool Boolean to add spy comparison no_bench : bool Boolean to not show buy and hold comparison shortable : bool Boolean to allow for selling of the stock at cross Returns ------- Result Backtest results """ ticker = ticker.lower() start_date = df_stock.index[0] prices = pd.DataFrame(df_stock["Adj Close"]) prices.columns = [ticker] short_ema = pd.DataFrame(ta.ema(prices[ticker], short_length)) short_ema.columns = [ticker] long_ema = pd.DataFrame(ta.ema(prices[ticker], long_length)) long_ema.columns = [ticker] # signals signals = long_ema.copy() signals[short_ema > long_ema] = 1.0 signals[short_ema <= long_ema] = -1.0 * shortable signals[long_ema.isnull()] = 0.0 combined_data = bt.merge(signals, prices, short_ema, long_ema) combined_data.columns = ["signal", "price", "ema_short", "ema_long"] bt_strategy = bt.Strategy( "EMA_Cross", [ bt.algos.WeighTarget(signals), bt.algos.Rebalance(), ], ) bt_backtest = bt.Backtest(bt_strategy, prices) backtests = [bt_backtest] if spy_bt: spy_bt = buy_and_hold("spy", start_date, "SPY Hold") backtests.append(spy_bt) if not no_bench: stock_bt = buy_and_hold(ticker, start_date, ticker.upper() + " Hold") backtests.append(stock_bt) res = bt.run(*backtests) return res
import bt import matplotlib matplotlib.get_backend() # download data from bt.algos import SelectWhere data = bt.get('aapl,msft', start='2016-01-01') # calculate moving average DataFrame using pandas' rolling_mean import pandas as pd # a rolling mean is a moving average, right? sma = pd.rolling_mean(data, 50) bt.merge(data, sma).plot(figsize=(15, 5)) signal = data > sma # first we create the Strategy s = bt.Strategy( 'above50sma', [SelectWhere(data > sma), bt.algos.WeighEqually(), bt.algos.Rebalance()]) # now we create the Backtest t = bt.Backtest(s, data) # and let's run it! res = bt.run(t) res.plot('d')
# save in temp - this will be used by the weighing algo target.temp['selected'] = selected # return True because we want to keep on moving down the stack return True data = bt.get('aapl,msft,c,gs,ge', start='2010-01-01') # calculate moving average DataFrame using pandas' rolling_mean import pandas as pd # a rolling mean is a moving average, right? sma = pd.rolling_mean(data, 50) # let's see what the data looks like - this is by no means a pretty chart, but it does the job tmp = bt.merge(data, sma).asfreq('m', 'ffill').rebase() plot = tmp.plot(figsize=(15, 5)) signal = data > sma # first we create the Strategy s = bt.Strategy('above50sma', [SelectWhere(data > sma), bt.algos.WeighEqually(), bt.algos.Rebalance()]) # now we create the Backtest t = bt.Backtest(s, data) # and let's run it! res = bt2.run(t)