def test_backtest_2strats(cerebro: bt.Cerebro): cerebro.addstrategy(bt.strategies.MA_CrossOver) cerebro.addstrategy(ToggleStrategy) cerebro.run() b = Bokeh(style='bar', output_mode=_output_mode) figs = cerebro.plot(b) assert len(figs) == 2 assert_num_tabs(figs, 3, 3) assert_num_figures(figs, 4, 3)
def test_std_backtest_volume_subplot(cerebro: bt.Cerebro): cerebro.addstrategy(bt.strategies.MA_CrossOver) cerebro.run() s = backtrader_plotting.schemes.Blackly() s.voloverlay = False b = Bokeh(style='bar', scheme=s, output_mode=_output_mode) figs = cerebro.plot(b) assert len(figs) == 1 assert_num_tabs(figs, 3) assert_num_figures(figs, 5)
def test_optimize_2strat(cerebro: bt.Cerebro): cerebro.optstrategy(bt.strategies.MA_CrossOver, slow=[5, 10, 20], fast=[5, 10, 20]) cerebro.optstrategy(ToggleStrategy, modbuy=[12, 15], modsell=[17, 19]) res = cerebro.run() b = Bokeh(style='bar', output_mode=_output_mode) browser = OptBrowser(b, res) with pytest.raises(RuntimeError): browser.build_optresult_model()
def test_std_backtest_ind_on_line(cerebro: bt.Cerebro): '''In the past it crashed when creating indicators with specific lines case LineSeriesStub was not handled correctly''' class TestStrategy(bt.Strategy): def __init__(self): self._sma = bt.indicators.SMA(self.data.close) cerebro.addstrategy(TestStrategy) cerebro.run() s = backtrader_plotting.schemes.Blackly() b = Bokeh(style='bar', scheme=s, output_mode=_output_mode) figs = cerebro.plot(b) assert len(figs) == 1 assert_num_tabs(figs, 3) assert_num_figures(figs, 3)
def test_github_issue36(): cerebro = bt.Cerebro() cerebro.addstrategy(MyStrategy) filedir = os.path.dirname(os.path.abspath(__file__)) df = pd.read_csv(os.path.join(filedir, "datas/NQ.csv"), index_col=0) df.index = pd.DatetimeIndex(df.index) data = bt.feeds.PandasData(dataname=df, name='NQ', timeframe=bt.TimeFrame.Minutes) cerebro.adddata(data) cerebro.resampledata(data, name='NQ_5min', timeframe=bt.TimeFrame.Minutes, compression=5) cerebro.addanalyzer(bt.analyzers.SharpeRatio) cerebro.run() b = Bokeh(filename='chart.html', style='bar', plot_mode="single", scheme=Tradimo(), output_mode='memory') cerebro.plot(b)
def test_std_backtest_ind_subplot(cerebro: bt.Cerebro): cerebro.addstrategy(bt.strategies.MA_CrossOver) cerebro.run() plotconfig = { '#:i-0': { 'subplot': True, } } s = backtrader_plotting.schemes.Blackly() b = Bokeh(style='bar', scheme=s, output_mode=_output_mode, plotconfig=plotconfig) figs = cerebro.plot(b) assert_num_tabs(figs, 3) assert_num_figures(figs, 5)
def trade_run(): cerebro = bt.Cerebro() data = DBDataFeed( # 本地postgresql数据库 db_uri=ConfigUtils.get_mysql('engine'), dataname="sh.600004", fromdate=datetime.date(2010, 1, 1), ) cerebro.adddata(data) cerebro.addstrategy(SMACross) cerebro.addsizer(bt.sizers.AllInSizerInt) cerebro.broker.set_cash(100000) cerebro.addanalyzer(bt.analyzers.AnnualReturn, _name="annual_returns") cerebro.addanalyzer(bt.analyzers.DrawDown, _name="draw_down") cerebro.addanalyzer(bt.analyzers.Transactions, _name="transactions") results = cerebro.run() # 打印Analyzer结果到日志 for result in results: annual_returns = result.analyzers.annual_returns.get_analysis() log.info("annual returns:") for year, ret in annual_returns.items(): log.info("\t {} {}%, ".format(year, round(ret * 100, 2))) draw_down = result.analyzers.draw_down.get_analysis() log.info( "drawdown={drawdown}%, moneydown={moneydown}, drawdown len={len}, " "max.drawdown={max.drawdown}, max.moneydown={max.moneydown}, " "max.len={max.len}".format(**draw_down)) transactions = result.analyzers.transactions.get_analysis() log.info("transactions") # 运行结果绘图 # cerebro.plot() b = Bokeh(style="bar", tabs="multi", scheme=Tradimo()) cerebro.plot(b)
def test_std_backtest_2datas(cerebro: bt.Cerebro): datapath = getdatadir('nvda-1999-2014.txt') data = bt.feeds.YahooFinanceCSVData( dataname=datapath, fromdate=datetime.datetime(1998, 1, 1), todate=datetime.datetime(2000, 12, 31), reverse=False, swapcloses=True, ) cerebro.adddata(data) cerebro.addstrategy(bt.strategies.MA_CrossOver) cerebro.run() s = backtrader_plotting.schemes.Blackly() b = Bokeh(style='bar', scheme=s, output_mode=_output_mode, merge_data_hovers=True) figs = cerebro.plot(b) assert len(figs) == 1 assert_num_tabs(figs, 3) assert_num_figures(figs, 5)
def test_optimize(cerebro: bt.Cerebro): cerebro.optstrategy(bt.strategies.MA_CrossOver, slow=[5, 10, 20], fast=[5, 10, 20]) res = cerebro.run(optreturn=True) b = Bokeh(style='bar', output_mode=_output_mode) browser = OptBrowser(b, res) model = browser.build_optresult_model() # browser.start() def count_children(obj): numo = 1 if hasattr(obj, "children"): numo = count_children(obj.children) if hasattr(obj, '__len__'): numo += len(obj) return numo num = count_children(model) assert num == 3
print('最大回撤DW:', results[0].analyzers.DrawDown.get_analysis()) # 选取一只股票进行回测 cerebro2 = bt.Cerebro() baseline = '000300.SH' feed = bt.feeds.PandasData(dataname=get_data(baseline)) cerebro2.adddata(feed, name=baseline) cerebro2.broker.get_notification() # 回测设置 cerebro2.broker.setcash(startcash) # 设置佣金为千分之一 cerebro2.broker.setcommission(commission=0.001) # 添加策略 cerebro2.addstrategy(BaseStrategy, printlog=True) results2 = cerebro2.run() # 获取回测结束后的总资金 portvalue2 = cerebro2.broker.getvalue() pnl2 = portvalue2 - startcash # 打印结果 print(f'沪深300 总资金: {round(portvalue2, 2)}') print(f'沪深300 净收益: {round(pnl2, 2)}') print('沪深300Final Portfolio Value: %.2f' % cerebro2.broker.getvalue()) # 绘制图像 b = Bokeh(style='bar', plot_mode='multi', scheme=Tradimo()) # cerebro.plot(b) # cerebro.plot() plot_result(results, results2, s)
import backtrader from strategies.strategies import TestStrategy import pandas as pd from backtrader_plotting import Bokeh from backtrader_plotting.schemes import Tradimo #pip3 install backtrader_plotting #import matplotlib.pyplot as plt plotconfig = { 'id:ind#0': dict(subplot=True, ), } b = Bokeh(style='bar', plot_mode='single', scheme=Tradimo(), plotconfig=plotconfig) def create_stock_sp500_ratio_csv(stockName): datapath = (rf'Data\{stockName}.csv') dataframeStock = pd.read_csv(datapath) datapath = (rf'Data\SPY.csv') dataframeSPY = pd.read_csv(datapath) #crate copy df = dataframeSPY.copy() for i in range(df.shape[0]): # gives number of row count # df['Date'].iloc[i]-=dataframeStock['Date'].iloc[i] df['Open'].iloc[i] -= dataframeStock['Open'].iloc[i] df['High'].iloc[i] -= -dataframeStock['High'].iloc[i] df['Low'].iloc[i] -= dataframeStock['Low'].iloc[i] df['Close'].iloc[i] -= dataframeStock['Close'].iloc[i] df['Volume'].iloc[i] -= dataframeStock['Volume'].iloc[i]
def bt_run(strat_p_list,df): # Create a cerebro entity try: cerebro = bt.Cerebro(tradehistory=True) cerebro.addanalyzer(bt.analyzers.cmtrans.cmTrans) # cerebro.addwriter(bt.WriterFile, out = 'test.csv', csv=True, rounding=5) data_table_id = strat_p_list[0] scrip_code = strat_p_list[1] strategy = strat_p_list[2] trade_size = strat_p_list[3] start_cash = strat_p_list[4] ex,m_t,t_f = su.parameters_from_data_table_id(data_table_id) # Get Class from strategy Name module = importlib.import_module('spe.strategies.'+strategy) class_name = strategy strategy = getattr(module, class_name) # Add a strategy cerebro.addstrategy(strategy,trade_size=trade_size) # Minimum datalength min_data = strategy.candle_lb() # Add the Data Feed to Cerebro # Returns Cerebro riteith datafeed attached cerebro_w_data = dh.data_feed(scrip_code,ex,m_t,t_f,cerebro,min_data) if cerebro_w_data is None: print('No Data Available') return [] # Set our desired cash start cerebro_w_data.broker.setcash(start_cash) # Set the commission - 0.1% ... divide by 100 to remove the % cerebro_w_data.broker.setcommission(commission=0.000) # cerebro_w_data.addanalyzer(bt.analyzers.TradeAnalyzer, _name="stats") # cerebro_w_data.addanalyzer(bt.analyzers.PositionsValue, _name="an_return") cerebro_w_data.addanalyzer(bt.analyzers.Returns) # cerebro_w_data.addanalyzer(bt.analyzers.PyFolio) # Print out the starting conditions # print('Starting Portfolio Value: %.2f' % cerebro_w_data.broker.getvalue()) # Run over everything strategy = cerebro_w_data.run() b = Bokeh(style='bar', plot_mode='single', scheme=Tradimo()) # cerebro_w_data.plot(b) Strat = strategy[0] # Print out the final result # print('Final Portfolio Value: %.2f' % cerebro_w_data.broker.getvalue()) # Strat.analyzers.stats.print() # Strat.analyzers.an_return.print() # print(f"Norm. Annual Return: {Strat.analyzers.returns.get_analysis()['rnorm100']:.2f}%") # pyfolizer = Strat.analyzers.getbyname('pyfolio') # returns, positions, transactions, gross_lev = pyfolizer.get_pf_items() # pf.create_returns_tear_sheet(returns) df = backtest_out(Strat,df) return Strat,df except Exception as e: # err.error_log(str(e),bt_run.__name__,'bt_run') logging.exception(str(e))
def perform_backtest(params, df, strategy, PandasData_Custom, bokeh=False): curr_result = {} curr_result = params data = PandasData_Custom(dataname=df) cerebro = bt.Cerebro() cerebro.adddata(data) cerebro.addstrategy(strategy, parameters=params) cerebro.addanalyzer(bt.analyzers.SharpeRatio, riskfreerate=0.0, annualize=True, timeframe=bt.TimeFrame.Days) cerebro.addanalyzer(bt.analyzers.Calmar) cerebro.addanalyzer(bt.analyzers.DrawDown) cerebro.addanalyzer(bt.analyzers.Returns) cerebro.addanalyzer(bt.analyzers.TradeAnalyzer) initial_cash = 1000 cerebro.broker = bt.brokers.BackBroker( cash=initial_cash, slip_perc=0.01 / 100, commission=CommInfoFractional(commission=(0.075 * params['mult']) / 100, mult=params['mult']), slip_open=True, slip_out=True) # 0.5% run = cerebro.run() all_logs = run[0].get_logs() portfolio = all_logs[0] trades = all_logs[1] operations = all_logs[2] trades_analysis = trades.merge(operations, on='Date', how='left') trades_analysis = trades_analysis.fillna(method='bfill') trades_analysis['Date'] = pd.to_datetime(trades_analysis['Date']) trades_analysis['Date'] = trades_analysis['Date'] - timedelta(minutes=10) analysis = run[0].analyzers.getbyname('tradeanalyzer').get_analysis() try: curr_result['Total Trades'] = analysis['total']['total'] except: curr_result['Total Trades'] = 0 try: curr_result['Total Profit'] = analysis['won']['total'] curr_result['Avg Profit'] = analysis['won']['pnl']['average'] except: curr_result['Total Profit'] = 0 curr_result['Avg Profit'] = 0 try: curr_result['Total Loss'] = analysis['lost']['total'] curr_result['Average Loss'] = analysis['lost']['pnl']['average'] except: curr_result['Total Loss'] = 0 curr_result['Average Loss'] = 0 try: curr_result['Total Long'] = analysis['long']['total'] curr_result['Average Long'] = analysis['long']['pnl']['average'] except: curr_result['Total Long'] = 0 curr_result['Average Long'] = 0 try: curr_result['Total Short'] = analysis['short']['total'] curr_result['Average Short'] = analysis['short']['pnl']['average'] except: curr_result['Total Short'] = 0 curr_result['Average Short'] = 0 curr_result['Return (%)'] = round( ((portfolio['Value'].iloc[-1] - portfolio['Value'].iloc[0]) / portfolio['Value'].iloc[0]) * 100, 2) curr_result['sharpe'] = run[0].analyzers.getbyname( 'sharperatio').get_analysis()['sharperatio'] portfolio['Date'] = pd.to_datetime(portfolio['Date']) portfolio = portfolio.set_index('Date') daily_portfolio = portfolio.resample('1D').agg( {'Value': lambda x: x.iloc[-1]}) if bokeh == True: b = Bokeh(style='bar', plot_mode='single', scheme=Tradimo()) fig = cerebro.plot(b) s_fig = fig[0][0] bokeh_html = file_html(s_fig.model, CDN, "Backtest Plot") if not os.path.isdir("bokeh/"): os.makedirs("bokeh/") fname = secrets.token_hex(3) + ".html" with open('bokeh/{}'.format(fname), 'w') as file: file.write(bokeh_html) return fname return curr_result
if __name__ == '__main__': cerebro = bt.Cerebro(maxcpus=1) data = bt.feeds.YahooFinanceCSVData( dataname="datas/orcl-1995-2014.txt", fromdate=datetime.datetime(2000, 1, 1), todate=datetime.datetime(2001, 2, 28), ) cerebro.adddata(data) cerebro.addanalyzer(bt.analyzers.TradeAnalyzer) cerebro.optstrategy(MyStrategy, buydate=range(40, 180, 30)) optres = cerebro.run(optreturn=False) def benchmark(optresults): a = [x.analyzers.tradeanalyzer.get_analysis() for x in optresults] return sum([x.pnl.gross.total if 'pnl' in x else 0 for x in a]) result = [ OrderedOptResult.BenchmarkedResult(benchmark(x), x) for x in optres ] ordered_result = sorted(result, key=lambda x: x.benchmark, reverse=True) ordered_result = OrderedOptResult("Profit & Losss", ordered_result) b = Bokeh(style='bar', plot_mode="single", scheme=Tradimo()) b.plot_result(ordered_result)
bt.indicators.RSI() def next(self): pos = len(self.data) if pos == 45 or pos == 145: self.buy(self.datas[0], size=None) if pos == 116 or pos == 215: self.sell(self.datas[0], size=None) if __name__ == '__main__': cerebro = bt.Cerebro() cerebro.addstrategy(MyStrategy) data = bt.feeds.YahooFinanceCSVData( dataname="datas/orcl-1995-2014.txt", fromdate=datetime.datetime(2000, 1, 1), todate=datetime.datetime(2001, 2, 28), reverse=False, swapcloses=True, ) cerebro.adddata(data) cerebro.addanalyzer(bt.analyzers.SharpeRatio) cerebro.run() b = Bokeh(style='bar') cerebro.plot(b)
bt.indicators.RSI() def next(self): pos = len(self.data) if pos == 45 or pos == 145: self.buy(self.datas[0], size=None) if pos == 116 or pos == 215: self.sell(self.datas[0], size=None) if __name__ == '__main__': cerebro = bt.Cerebro() cerebro.addstrategy(MyStrategy) data = bt.feeds.YahooFinanceCSVData( dataname="datas/orcl-1995-2014.txt", fromdate=datetime.datetime(2000, 1, 1), todate=datetime.datetime(2001, 2, 28), reverse=False, swapcloses=True, ) cerebro.adddata(data) cerebro.addanalyzer(bt.analyzers.SharpeRatio) cerebro.run() b = Bokeh(style='bar', tabs='multi') cerebro.plot(b)
cerebro.addstrategy(TestStrategy) # Create a data feed data = bt.feeds.YahooFinanceData(dataname='MSFT', fromdate=datetime.datetime(2019, 1, 1), todate=datetime.datetime(2019, 12, 31)) # Add the Data Feed to Cerebro cerebro.adddata(data) # Set our desired cash start cerebro.broker.setcash(1000.0) # Add a FixedSize sizer according to the stake cerebro.addsizer(bt.sizers.FixedSize, stake=10) # Set the commission cerebro.broker.setcommission(commission=0.0) # Print out the starting conditions #print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) # Run over everything cerebro.run() # Print out the final result #print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue()) # Plot the result b = Bokeh(style='bar', tabs='multi', scheme=Tradimo()) cerebro.plot(b)
sma1 = bt.indicators.SMA(period=11, subplot=True) bt.indicators.SMA(period=17, plotmaster=sma1) bt.indicators.RSI() def next(self): pos = len(self.data) if pos == 45 or pos == 145: self.buy(self.datas[0], size=None) if pos == 116 or pos == 215: self.sell(self.datas[0], size=None) if __name__ == '__main__': cerebro = bt.Cerebro() cerebro.addstrategy(MyStrategy) data = bt.feeds.YahooFinanceCSVData( dataname="datas/orcl-1995-2014.txt", fromdate=datetime.datetime(2000, 1, 1), todate=datetime.datetime(2001, 2, 28), ) cerebro.adddata(data) cerebro.addanalyzer(bt.analyzers.SharpeRatio) cerebro.run() b = Bokeh(style='bar', plot_mode="tabs") cerebro.plot(b)
from datetime import datetime import backtrader as bt class SmaCross(bt.SignalStrategy): def __init__(self): sma1, sma2 = bt.ind.SMA(period=10), bt.ind.SMA(period=30) crossover = bt.ind.CrossOver(sma1, sma2) self.signal_add(bt.SIGNAL_LONG, crossover) cerebro = bt.Cerebro() cerebro.addstrategy(SmaCross) data0 = bt.feeds.YahooFinanceData(dataname='MSFT', fromdate=datetime(2011, 1, 1), todate=datetime(2012, 12, 31)) cerebro.adddata(data0) cerebro.run() from backtrader_plotting import Bokeh, OptBrowser bo = Bokeh() cerebro.plot(bo)
bt.indicators.SMA(period=17, plotmaster=sma1) bt.indicators.RSI() def next(self): pos = len(self.data) if pos == 45 or pos == 145: self.buy(self.datas[0], size=None) if pos == 116 or pos == 215: self.sell(self.datas[0], size=None) if __name__ == '__main__': cerebro = bt.Cerebro() cerebro.addstrategy(MyStrategy) data = bt.feeds.YahooFinanceCSVData( dataname="datas/orcl-1995-2014.txt", fromdate=datetime.datetime(2000, 1, 1), todate=datetime.datetime(2001, 2, 28), reverse=False, ) cerebro.adddata(data) cerebro.addanalyzer(bt.analyzers.SharpeRatio) cerebro.run() b = Bokeh(style='bar', plot_mode="single", scheme=Tradimo()) cerebro.plot(b)
sma1 = bt.indicators.SMA(period=11, subplot=True) bt.indicators.SMA(period=17, plotmaster=sma1) bt.indicators.RSI() def next(self): pos = len(self.data) if pos == 45 or pos == 145: self.buy(self.datas[0], size=None) if pos == 116 or pos == 215: self.sell(self.datas[0], size=None) if __name__ == '__main__': cerebro = bt.Cerebro() cerebro.addstrategy(MyStrategy) data = bt.feeds.YahooFinanceCSVData( dataname="datas/orcl-1995-2014.txt", fromdate=datetime.datetime(2000, 1, 1), todate=datetime.datetime(2001, 2, 28), ) cerebro.adddata(data) cerebro.addanalyzer(bt.analyzers.SharpeRatio) cerebro.run() b = Bokeh(style='bar', plot_mode="single") cerebro.plot(b)
if __name__ == '__main__': cerebro = bt.Cerebro() data = bt.feeds.YahooFinanceCSVData( dataname=getdatadir("20170319-20200319-0388.HK.csv"), fromdata=datetime.datetime( 2020, 2, 19, 0, 0, 0, ), todata=datetime.datetime(2020, 3, 19, 0, 0, 0), reverse=False) cerebro.addobserver(bt.observers.Benchmark, data=data, timeframe=bt.TimeFrame.NoTimeFrame) cerebro.addstrategy(MyStrategy) cerebro.adddata(data) cerebro.addsizer(bt.sizers.AllInSizer) cerebro.broker.setcash(100000) print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) import json strats = cerebro.run()[0] print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue()) bo = Bokeh(style='bar', plot_mode='single', output_mode='memory') cerebro.plot(bo)
bt.indicators.Ichimoku() def next(self): pos = len(self.data) if pos == 45 or pos == 145: self.buy(self.datas[0], size=None) if pos == 116 or pos == 215: self.sell(self.datas[0], size=None) if __name__ == '__main__': cerebro = bt.Cerebro() cerebro.addstrategy(MyStrategy) data = bt.feeds.YahooFinanceCSVData( dataname="datas/orcl-1995-2014.txt", fromdate=datetime.datetime(2000, 1, 1), todate=datetime.datetime(2001, 2, 28), reverse=False, swapcloses=True, ) cerebro.adddata(data) cerebro.addanalyzer(bt.analyzers.SharpeRatio) cerebro.run() b = Bokeh(style='bar', scheme=Tradimo()) cerebro.plot(b)
if pos == self.p.buydate: self.buy(self.datas[0], size=None) if pos == self.p.buydate + self.p.holdtime: self.sell(self.datas[0], size=None) if __name__ == '__main__': cerebro = bt.Cerebro(maxcpus=1) data = bt.feeds.YahooFinanceCSVData( dataname="datas/orcl-1995-2014.txt", fromdate=datetime.datetime(2000, 1, 1), todate=datetime.datetime(2001, 2, 28), ) cerebro.adddata(data) cerebro.addanalyzer(bt.analyzers.TradeAnalyzer) cerebro.optstrategy(MyStrategy, buydate=range(40, 180, 30)) result = cerebro.run(optreturn=False) def get_pnl_gross(strats): a = strats[0].analyzers.tradeanalyzer.get_analysis() return a.pnl.gross.total if 'pnl' in a else 0 columns = dict(pnl=get_pnl_gross) b = Bokeh(style='bar', plot_mode="single", scheme=Tradimo()) b.plot_result(result, columns)
todate=datetime.datetime(2021, 2, 20), #todate = datetime.datetime(2018, 1, 15), nullvalue=0.0, dtformat=('%Y-%m-%d'), datetime=0, open=1, high=2, low=3, close=4, volume=5, openinterest=-1, predict=16, ma5=6) cerebro.adddata(data, name='AAPL') # set principle cerebro.broker.setcash(50000.0) # set commission cerebro.broker.setcommission(commission=0.00025) # set size cerebro.addsizer(bt.sizers.FixedSize, stake=1000) # print out starting capital print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) # start backtesting cerebro.run() #plot b = Bokeh(style='bar', plot_mode='single') cerebro.plot(b) # print out final capital print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
def perform_backtest(symbol_par, n_fast_par, n_slow_par, long_macd_threshold_par, long_per_threshold_par, long_close_threshold_par, short_macd_threshold_par, short_per_threshold_par, short_close_threshold_par, initial_cash=10000, comission=0.1, df=None): ''' Parameter: __________ symbol_par (string): The symbol to use n_fast_par (int): Fast EMA line used during MACD calculation n_slow_par (int): Slower EMA line used during MACD calculation long_macd_threshold_par (int): The threshold of normalized macd, above which we might open a long position long_per_threshold_par (int): The value of percentage change over the last 2 hours above which we might open a long position #Might make this a parameter too long_close_threshold_par (int): Threshold of normalized macd, below which we will close the opened long position short_macd_threshold_par (int): The threshold of normalized macd, below which we might open a short position short_per_threshold_par (int): The value of percentage change over the last 2 hours below which we might open a short position short_close_threshold_par (int): Threshold of normalized macd, above which we will close the opened short position initial_cash (int) (optional): The cash to start from. Initiall 10k comission (int) (option): int fraction value. Defaults to 0.1%. This is much higher than normal. Staying on the safe side. df (Dataframe) (option): Uses df as features dataframe if specified. Otherwise reads the coin folder ''' global n_fast global n_slow global long_macd_threshold global long_per_threshold global long_close_threshold global short_macd_threshold global short_per_threshold global short_close_threshold global symbol n_fast = n_fast_par n_slow = n_slow_par long_macd_threshold = long_macd_threshold_par long_per_threshold = long_per_threshold_par long_close_threshold = long_close_threshold_par short_macd_threshold = short_macd_threshold_par short_per_threshold = short_per_threshold_par short_close_threshold = short_close_threshold_par symbol = symbol_par json_info = {} json_info['n_fast'] = n_fast json_info['n_slow'] = n_slow json_info['long_macd_threshold'] = long_macd_threshold_par json_info['long_per_threshold'] = long_per_threshold_par json_info['long_close_threshold'] = long_close_threshold_par json_info['short_macd_threshold'] = short_macd_threshold_par json_info['short_per_threshold'] = short_per_threshold_par json_info['short_close_threshold'] = short_close_threshold_par json_info['initial_cash'] = initial_cash json_info['comission'] = comission with open(get_root_dir() + "/data/parameters.json", 'w') as f: json.dump(json_info, f) features_file = get_root_dir() + "/data/features/{}.csv".format(symbol) if df is None: df = pd.read_csv(features_file) df['macd'] = ta.trend.macd(df['sentistrength_total'], n_fast=n_fast, n_slow=n_slow, fillna=True) df['macd'] = df['macd'].fillna(0) df['Time'] = pd.to_datetime(df['Time']) json_data = {} json_data['mean'] = df['macd'].mean() json_data['std'] = df['macd'].std() df['macd'] = (df['macd'] - json_data['mean']) / json_data['std'] df = df.dropna(subset=['Time']) curr_dir = get_root_dir() + "/data/backtest/{}".format(symbol) if not os.path.exists(curr_dir): os.makedirs(curr_dir) fig = create_plot(df, 'macd', 'SentiStength') plotly_json = fig.to_json() html = fig.to_html() with open(curr_dir + '/plotly.html', 'w') as file: file.write(html) with open(curr_dir + '/plotly.json', 'w') as file: file.write(plotly_json) df = df[['Time', 'Open', 'High', 'Low', 'Close', 'Volume', 'macd']] df.to_csv(os.path.join(curr_dir, "data.csv"), index=None) data = PandasData_Custom(dataname=df) cerebro = bt.Cerebro(cheat_on_open=True, maxcpus=None) cerebro.adddata(data) cerebro.addstrategy(tradeStrategy) cerebro.addanalyzer(bt.analyzers.SharpeRatio_A) cerebro.addanalyzer(bt.analyzers.Calmar) cerebro.addanalyzer(bt.analyzers.DrawDown) cerebro.addanalyzer(bt.analyzers.Returns) cerebro.addanalyzer(bt.analyzers.TradeAnalyzer) cerebro.broker.setcash(initial_cash) cerebro.broker.setcommission(comission / 100) run = cerebro.run() analysis = run[0].analyzers.getbyname('tradeanalyzer').get_analysis() trade_analyzer = {} trade_analyzer['total'] = analysis['total']['total'] trade_analyzer['open'] = analysis['total']['open'] trade_analyzer['closed'] = analysis['total']['closed'] with open(curr_dir + "/stats.json", 'w') as f: json.dump(trade_analyzer, f) portfolioValue, trades, operations = run[0].get_logs() # fig = cerebro.plot() # figure = fig[0][0] # figure.savefig(curr_dir + "/backtest.png") output_file(curr_dir + "/backtest.html") b = Bokeh(style='bar', plot_mode="tabs", scheme=Tradimo()) b.plot_result(run) df = df.set_index('Time') df = df.resample('1D').apply(resampler) df = df.reset_index() df = df[['Time', 'Open']].merge(portfolioValue, left_on='Time', right_on='Date').drop('Time', axis=1) df['hodl'] = (initial_cash / df['Open'].iloc[0]) * df['Open'] df = df.drop('Open', axis=1) df.to_csv(curr_dir + '/portfolio.csv', index=None) trades.to_csv(curr_dir + '/trades.csv', index=None) operations.to_csv(curr_dir + '/operations.csv', index=None) with open(os.path.join(curr_dir, "data.json"), 'w') as fp: json.dump(json_data, fp)
cerebro.broker.setcommission(commission=0.0025) data = bt.feeds.GenericCSVData( dataname=f'./data/{target_stock}.csv', nullvalue=0.0, dtformat=('%Y-%m-%d'), datetime=0, open=1, high=2, low=3, close=4, volume=6, ) cerebro.adddata(data) cerebro.addstrategy(Buy_and_Hold) cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name='TradeAnalyzer') # 交易分析 (策略勝率) cerebro.addanalyzer(bt.analyzers.PeriodStats, _name='PeriodStats') # 交易基本統計分析 cerebro.addanalyzer(bt.analyzers.DrawDown, _name='DrawDown') # 回落統計 cerebro.addanalyzer(bt.analyzers.SQN, _name='SQN') # 期望獲利/標準差 System Quality Number cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='SharpeRatio') # 夏普指數 print('投資 > 起始資產 %.2f 💲' % cerebro.broker.getvalue()) cerebro.run() print('投資 > 結束資產 %.2f 💲' % cerebro.broker.getvalue()) investment_plot = Bokeh(style='bar', plot_mode='single', scheme=Blackly()) cerebro.plot(investment_plot)
def _create_bokeh(self): return Bokeh( style=self.p.style, scheme=self.p.scheme, **self._bokeh_kwargs ) # get a copy of the scheme so we can modify it per client