def cal_alphas(self, expr_ds): # 计算信号 for i in [ 'OpenPrice', 'ClosePrice', 'HighestPrice', 'LowestPrice', 'Volume', 'VWAP', 'Position', 'TurnOver' ]: expr_tmp = expr_ds.values.expr.replace(i, 'self.eod.%s' % i) alphas = eval(expr_tmp) resample_wgts = pd.DataFrame(alphas[:-1] * 1., index=self.eod.dates[1:], columns=self.eod.ticker_names) bt = BackTest(resample_wgts, returns=self.resample_returns, cycle='day', IS_OOS_ratio=None, stat_info=False, plot=False, quintiles=3, turnover=1, cost=0., ticker_names=None, output_dir=None, test_mode=False, signal_name=None) bt.stat_quintiles() bt.stat_quintiles_pnl() bt.stat_alpha_pnl() bt.stat_alpha_sharpe() # 保存信号 print expr_ds.values.id, expr_ds.values.expr, 'sharpe:', bt.alpha_sharpe
def setUp(self): self.sym = "EURUSD" self.aEq = self.assertEqual self.aIn = self.assertIn self.aRaise = self.assertRaises self.aItEq = self.assertItemsEqual self.bt = BackTest()
def should_generate_errors_over_time_for_each_model(self): first_start_datetime = [ '2016-07-16 09:00:00-04:00', '2016-08-16 09:00:00-04:00' ] l1_time = [9, 10] l1_day = [0, 0] schedule_type = [1, 1] start_month = [7, 8] start_year = [2016, 2016] user_tz = ['Brasilia', 'Brasilia'] args = { 'l1_time': l1_time, 'l1_day': l1_day, 'schedule_type': schedule_type, 'first_start_datetime': first_start_datetime, 'start_month': start_month, 'start_year': start_year, 'user_tz': user_tz } summaries = pd.DataFrame(args) summaries['first_start_datetime'] = pd.to_datetime( summaries['first_start_datetime']) bt = BackTest(data=summaries, model=DumbModel, training_data_span_months=1) error = bt.errors() expect('2016-8' in error.index.values).to.equal(True) expect('2016-7' not in error.index.values).to.equal(True) expect('2016-6' not in error.index.values).to.equal(True)
def should_generate_errors_over_time_for_each_model(self): first_start_datetime = ['2016-07-16 09:00:00-04:00', '2016-08-16 09:00:00-04:00'] l1_time = [9,10] l1_day = [0, 0] schedule_type = [1, 1] start_month = [7,8] start_year = [2016,2016] user_tz = ['Brasilia', 'Brasilia'] args = {'l1_time': l1_time, 'l1_day': l1_day, 'schedule_type': schedule_type, 'first_start_datetime': first_start_datetime, 'start_month': start_month, 'start_year': start_year, 'user_tz': user_tz } summaries = pd.DataFrame(args) summaries['first_start_datetime'] = pd.to_datetime(summaries['first_start_datetime']) bt = BackTest(data=summaries, model=DumbModel, training_data_span_months=1) error = bt.errors() expect('2016-8' in error.index.values).to.equal(True) expect('2016-7' not in error.index.values).to.equal(True) expect('2016-6' not in error.index.values).to.equal(True)
def __init__(self,model_name, begin_time, end_time, begin_equity, fee, path, universe,freq,length, lag, short): BackTest.__init__(self,model_name, begin_time, end_time, begin_equity, fee, path, universe,freq,length, lag, short)
from backtest import BackTest import pandas as pd #매일 장이 끝난 후에 이 파일을 돌려야 백테스트를 위한 분봉데이터를 수집할 수 있음. if __name__ == "__main__": #객체 생성 backtest = BackTest() #통신 확인 if backtest.InitPlusCheck() == False: exit() # 전체 코스피, 코스닥 코드 불러오기 entire_code, entire_name = backtest.get_entire_code() # code = backtest.get_yesterday_highest() # # 어제 상한가 종목 및 날짜 불러오기 # date_company = pd.DataFrame([[backtest.today,code]],columns=['내일날짜','상한가다음날']) # # 해당 분봉 데이터 업데이트 # backtest.get_minute_stock(date_company, entire_code, int(backtest.today)) # 특정 날짜 빼먹었을 때 데이터 축적 code = ['A003495'] specific_date = '20201117' date_company = pd.DataFrame([[specific_date, code]], columns=['내일날짜', '상한가다음날']) backtest.get_minute_stock(date_company, entire_code, int(specific_date)) # 긴 기간을 구하고 싶을때 # change = backtest.get_change(entire_code, 100) # date_company = backtest.date_company_extract(change)
def __init__(self,model_name, begin_time, end_time, begin_equity, fee, path, universe,freq,length, lag): BackTest.__init__(self,model_name, begin_time, end_time, begin_equity, fee, path, universe,freq,length, lag)
class TestBackTest(unittest.TestCase): def setUp(self): self.sym = "EURUSD" self.aEq = self.assertEqual self.aIn = self.assertIn self.aRaise = self.assertRaises self.aItEq = self.assertItemsEqual self.bt = BackTest() def tearDown(self): pass def bar_close(self, sym, b): print "bar_close: ", b.date def testAddSym(self): f = "yo" self.bt.add_input(self.sym, f, bartype=Bar) self.aEq([(self.sym, f, Bar)], self.bt.inputs) self.aEq(self.bt.bars.keys(), [self.sym]) def testBuyMarket(self): b1 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9505,0.9506") o1 = Order(self.sym, dir=Order.BUY, type=Order.MARKET, level=0.9508, size=10000) self.bt.book.add(o1) #self.bt.bar_close = self.bar_close self.bt.next_bar(self.sym, b1) #should have an open position self.aEq(len(self.bt.poslist.open), 1) p = self.bt.poslist.open[0] self.aEq(p.order_id, o1.id) self.aEq(p.mark, b1.cl) self.aEq(p.entry, o1.level) def testBuyLimit(self): b1 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9505,0.9506") b2 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9500,0.9506") o1 = Order(self.sym, dir=Order.BUY, type=Order.LIMIT, level=0.9501, size=10000) self.bt.book.add(o1) self.bt.next_bar(self.sym, b1) #should be no fill for b1 self.aEq(len(self.bt.poslist.open), 0) self.bt.next_bar(self.sym, b2) self.aEq(len(self.bt.poslist.open), 1) def testBuyStop(self): b1 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9505,0.9506") b2 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9511,0.9500,0.9506") o1 = Order(self.sym, dir=Order.BUY, type=Order.STOP, level=0.9510, size=10000) self.bt.book.add(o1) self.bt.next_bar(self.sym, b1) self.aEq(len(self.bt.poslist.open), 0) self.bt.next_bar(self.sym, b2) self.aEq(len(self.bt.poslist.open), 1) def testSellLimit(self): b1 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9505,0.9506") b2 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9511,0.9505,0.9506") o1 = Order(self.sym, dir=Order.SELL, type=Order.LIMIT, level=0.9510, size=-10000) self.bt.book.add(o1) self.bt.next_bar(self.sym, b1) self.aEq(len(self.bt.poslist.open), 0) self.bt.next_bar(self.sym, b2) self.aEq(len(self.bt.poslist.open), 1) def testSellStop(self): b1 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9505,0.9506") b2 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9499,0.9506") o1 = Order(self.sym, dir=Order.SELL, type=Order.STOP, level=0.9499, size=-10000) self.bt.book.add(o1) self.bt.next_bar(self.sym, b1) self.aEq(len(self.bt.poslist.open), 0) self.bt.next_bar(self.sym, b2) self.aEq(len(self.bt.poslist.open), 1) def testTP(self): #stop loss/take profit b1 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9505,0.9506") b2 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9511,0.9505,0.9506") #buy order at 9505 o1 = Order(self.sym, dir=Order.BUY, type=Order.MARKET, level=0.9505, size=10000) #stop loss at 9499 sl = Order(self.sym, dir=Order.SELL, type=Order.STOP, level=0.9499, size=-10000) #take profit at 9510 tp = Order(self.sym, dir=Order.SELL, type=Order.LIMIT, level=0.9510, size=-10000) #stop loss hit cancels tp and vice versa Order.OCO(sl, tp) #when the order is filled it activates sl/tp o1.trigger(sl, tp) self.bt.book.add(o1, sl, tp) self.bt.next_bar(self.sym, b1) #the order should be filled self.aEq(len(self.bt.poslist.open), 1) self.aItEq([sl.id, tp.id], self.bt.book.active) self.bt.next_bar(self.sym, b2) self.aEq(len(self.bt.poslist.open), 0) self.aEq(len(self.bt.poslist.closed), 1) self.aEq(len(self.bt.book.active), 0) self.aEq(self.bt.equity, 100005) def testSL(self): #stop loss/take profit b1 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9505,0.9506") b2 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9499,0.9506") #buy order at 9505 o1 = Order(self.sym, dir=Order.BUY, type=Order.MARKET, level=0.9505, size=10000) #stop loss at 9499 sl = Order(self.sym, dir=Order.SELL, type=Order.STOP, level=0.9499, size=-10000) #take profit at 9510 tp = Order(self.sym, dir=Order.SELL, type=Order.LIMIT, level=0.9510, size=-10000) #stop loss hit cancels tp and vice versa Order.OCO(sl, tp) #when the order is filled it activates sl/tp o1.trigger(sl, tp) self.bt.book.add(o1, sl, tp) self.bt.next_bar(self.sym, b1) #the order should be filled self.aEq(len(self.bt.poslist.open), 1) self.aItEq([sl.id, tp.id], self.bt.book.active) self.bt.next_bar(self.sym, b2) self.aEq(len(self.bt.poslist.open), 0) self.aEq(len(self.bt.poslist.closed), 1) self.aEq(len(self.bt.book.active), 0) self.aEq(self.bt.equity, 99994) def testRewind(self): #in this case we have a sl/tp, and get a bar which triggers them both #when this happens, we cancel both the orders and unwind the original position #as if it never happened. If this is happening a lot you need lower time frame data #stop loss/take profit b1 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9509,0.9505,0.9506") b2 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9510,0.9499,0.9506") #buy order at 9505 o1 = Order(self.sym, dir=Order.BUY, type=Order.MARKET, level=0.9505, size=10000) #stop loss at 9499 sl = Order(self.sym, dir=Order.SELL, type=Order.STOP, level=0.9499, size=-10000) #take profit at 9510 tp = Order(self.sym, dir=Order.SELL, type=Order.LIMIT, level=0.9510, size=-10000) #stop loss hit cancels tp and vice versa Order.OCO(sl, tp) #when the order is filled it activates sl/tp o1.trigger(sl, tp) self.bt.book.add(o1, sl, tp) self.bt.next_bar(self.sym, b1) #the order should be filled self.aEq(len(self.bt.poslist.open), 1) self.aItEq([sl.id, tp.id], self.bt.book.active) self.bt.next_bar(self.sym, b2) self.aEq(len(self.bt.poslist.open), 0) self.aEq(len(self.bt.poslist.closed), 0) self.aEq(len(self.bt.poslist.rewinded), 1) self.aEq(len(self.bt.book.active), 0) self.aEq(self.bt.equity, 100000) def testOpenRewind(self): #in this case we have a sl/tp, and get a bar which triggers them both #when this happens, we cancel both the orders and unwind the original position #as if it never happened. If this is happening a lot you need lower time frame data #stop loss/take profit b1 = Bar(self.sym, "20010102-230000,EURUSD,0.9507,0.9510,0.9499,0.9506") #buy order at 9505 o1 = Order(self.sym, dir=Order.BUY, type=Order.MARKET, level=0.9505, size=10000) #stop loss at 9499 sl = Order(self.sym, dir=Order.SELL, type=Order.STOP, level=0.9499, size=-10000) #take profit at 9510 tp = Order(self.sym, dir=Order.SELL, type=Order.LIMIT, level=0.9510, size=-10000) #stop loss hit cancels tp and vice versa Order.OCO(sl, tp) #when the order is filled it activates sl/tp o1.trigger(sl, tp) self.bt.book.add(o1, sl, tp) self.bt.next_bar(self.sym, b1) #the order should be filled self.aEq(len(self.bt.poslist.open), 1) self.aItEq([sl.id, tp.id], self.bt.book.active) self.bt.next_bar(self.sym, b1) self.aEq(len(self.bt.poslist.open), 0) self.aEq(len(self.bt.poslist.closed), 0) self.aEq(len(self.bt.poslist.rewinded), 1) self.aEq(len(self.bt.book.active), 0) self.aEq(self.bt.equity, 100000)
config = ConfigParser() config.read('./config/config-excel.conf') def create_handlers(config, event_queue): """ create data_handler, strategy, portfolio, execution """ data_handler = FileMDEngine(config, event_queue) strategy = ExcelStrategy(config, event_queue, data_handler) execution = ExcelExecution(config, event_queue, data_handler) portfolio = ExcelPortfolio(config, event_queue, data_handler, execution) return data_handler, strategy, portfolio, execution test = BackTest(config, create_handlers) test.run_backtest() metric = PerformanceMetric(test, config) metric.multiplier = 10 metrics = metric.calculate_performance() df1 = metrics.get('data') columns = [ 'close', 'position', 'tradepnl_wo_commission', 'cumpnl_wo_commission' ] df1 = df1[columns] df2 = load_excel_result() df2.columns = columns
if __name__ == '__main__': from talib import SMA import pandas as pd from dataload import get_sample_data from mytrader import HelloWorldTrade from backtest import BackTest from utils.visualize import visuialize_performance df = get_sample_data() trading_data = df[['Close']].rename(columns={'Close': '2380_close'}) indexes = df # we don't use any index to support the strategy in this hello-world trader trader = HelloWorldTrade() back_tester = BackTest(trading_data, indexes) back_tester.evaluate(trader) data_to_plot = trading_data.copy() data_to_plot['13MA'] = SMA(trading_data['2380_close'], 13) data_to_plot['34MA'] = SMA(trading_data['2380_close'], 34) visuialize_performance(back_tester, data_to_plot[['2380_close']], data_to_plot[['13MA']], data_to_plot[['34MA']]) print("see result in output dir!")