def test_update_fill(self): events_queue = queue.Queue(100) bars = HistoricCSVDataHandler(events_queue, './tests/datasets/', ['BTC_ETC'], ['open', 'high', 'low', 'close']) p = NaivePortfolio(bars, events_queue, datetime(2017, 4, 1, 0, 0, 0), 1000.0) fill_event = FillEvent(datetime.utcnow(), 'BTC_ETC', 'BACKTEST', 1.0, 'BUY', None) bars.update_bars() p.update_fill(fill_event) self.assertEqual( p.current_holdings, { 'BTC_ETC': 0.0025947399999999999, 'cash': 999.99540525999998, 'commission': 0.002, 'total': 999.99540525999998 }) self.assertEqual(p.current_positions, {'BTC_ETC': 1.0}) bars.update_bars() p.update_timeindex(None) self.assertEqual(p.all_positions, [{ 'BTC_ETC': 0, 'datetime': datetime(2017, 4, 1, 0, 0) }, { 'BTC_ETC': 1.0, 'datetime': datetime(2017, 4, 22, 18, 35) }]) print(p.all_holdings) self.assertEqual(p.all_holdings, [{ 'commission': 0.0, 'BTC_ETC': 0.0, 'total': 1000.0, 'datetime': datetime(2017, 4, 1, 0, 0), 'cash': 1000.0 }, { 'commission': 0.002, 'BTC_ETC': 0.00259552, 'total': 999.99800077999998, 'datetime': datetime(2017, 4, 22, 18, 35), 'cash': 999.99540525999998 }])
def test(): events=Queue() csv_dir='/Users/weileizhang/Downloads/' symbol_list=['XOM'] #start_date=datetime.datetime(2013,1,1) #end_date=datetime.datetime(2015,1,5) #bars=HistoricCSVDataHandler(events,csv_dir,symbol_list,start_date,end_date) start_date='2010-1-1' end_date='2015-1-1' bars=DataBaseDataHandler(events,symbol_list,start_date,end_date) # strategy=BuyAndHoldStrategy(bars,events) strategy=MovingAverageCrossStrategy(bars,events,short_window=100,long_window=400) port=NaivePortfolio(bars,events,start_date,initial_capital=100000.0) broker=SimulatedExecutionHandler(events) while True: if bars.continue_backtest==True: bars.update_bars() else: break while True: try: event=events.get(False) except: break else: if event is not None: if event.type=='MARKET': strategy.calculate_signals(event) port.update_timeindex(event) elif event.type=='SIGNAL': port.update_signal(event) elif event.type=='ORDER': broker.execute_order(event) elif event.type=='FILL': port.update_fill(event) port.create_equity_curve_dataframe() stats=port.output_summary_stats() print(stats)
def test_execution_stop_order(self): csv_dir = './tests/datasets/' symbol_list = [ 'BTC_ETC', ] events_queue = queue.Queue(100) bars = HistoricCSVDataHandler(events_queue, csv_dir, symbol_list, ['open', 'high', 'low', 'close']) p = NaivePortfolio(bars, events_queue, datetime(2017, 4, 1, 0, 0, 0), 1000.0) e = SimulatedExecutionHandler(events_queue, portfolio=p) bars.update_bars() oe = OrderEvent('BTC_ETC', 'STP', 300000.0, 'BUY', 0.00259) e.execute_order(oe) self.assertTrue(len(e.stop_orders) > 0) bars.update_bars() ee = events_queue.get(False) e.check_stop_orders(ee) p.update_timeindex(ee) p.create_equity_curve_dataframe() self.assertEqual(p.equity_curve['equity_curve'][-1], 1.0001020000000001)
input() while bars.continue_backtest == True: # print ("Updating Bars.") bars.update_bars() while True: if events.empty(): break else: event = events.get(False) if event is not None: if event.type == 'MARKET': strategy.calculate_signals(event) port.update_timeindex(event) elif event.type == 'SIGNAL': port.update_signal(event) elif event.type == 'ORDER': broker.execute_order(event) elif event.type == 'FILL': port.update_fill(event) time.sleep(0.1) result_stats = port.output_summary_stats() print('==========================================') print(result_stats)
def test_update_fill_all_up(self): events_queue = queue.Queue(100) bars = HistoricCSVDataHandler(events_queue, './tests/datasets/', ['ALL_UP'], ['open', 'high', 'low', 'close']) p = NaivePortfolio(bars, events_queue, datetime(2017, 4, 1, 0, 0, 0), 1000.0) fill_event = FillEvent(datetime.utcnow(), 'ALL_UP', 'BACKTEST', 1.0, 'BUY', None) bars.update_bars() p.update_fill(fill_event) self.assertEqual( p.current_holdings, { 'ALL_UP': 10.0, 'cash': 989.99800000000005, 'commission': 0.002, 'total': 989.99800000000005 }) self.assertEqual(p.current_positions, {'ALL_UP': 1.0}) bars.update_bars() p.update_timeindex(None) self.assertEqual(p.all_positions, [{ 'ALL_UP': 0, 'datetime': datetime(2017, 4, 1, 0, 0) }, { 'ALL_UP': 1.0, 'datetime': datetime(2017, 4, 22, 18, 35) }]) self.assertEqual(p.all_holdings, [{ 'commission': 0.0, 'ALL_UP': 0.0, 'total': 1000.0, 'datetime': datetime(2017, 4, 1, 0, 0), 'cash': 1000.0 }, { 'commission': 0.002, 'ALL_UP': 20.0, 'total': 1009.998, 'datetime': datetime(2017, 4, 22, 18, 35), 'cash': 989.99800000000005 }]) bars.update_bars() p.update_timeindex(None) self.assertEqual(p.all_positions, [ { 'ALL_UP': 0, 'datetime': datetime(2017, 4, 1, 0, 0) }, { 'ALL_UP': 1.0, 'datetime': datetime(2017, 4, 22, 18, 35) }, { 'ALL_UP': 1.0, 'datetime': datetime(2017, 4, 22, 18, 40) }, ]) self.assertEqual(p.all_holdings, [ { 'commission': 0.0, 'ALL_UP': 0.0, 'total': 1000.0, 'datetime': datetime(2017, 4, 1, 0, 0), 'cash': 1000.0 }, { 'commission': 0.002, 'ALL_UP': 20.0, 'total': 1009.998, 'datetime': datetime(2017, 4, 22, 18, 35), 'cash': 989.99800000000005 }, { 'commission': 0.002, 'ALL_UP': 30.0, 'total': 1019.998, 'datetime': datetime(2017, 4, 22, 18, 40), 'cash': 989.99800000000005 }, ]) bars.update_bars() p.update_timeindex(None) self.assertEqual(p.all_positions, [ { 'ALL_UP': 0, 'datetime': datetime(2017, 4, 1, 0, 0) }, { 'ALL_UP': 1.0, 'datetime': datetime(2017, 4, 22, 18, 35) }, { 'ALL_UP': 1.0, 'datetime': datetime(2017, 4, 22, 18, 40) }, { 'ALL_UP': 1.0, 'datetime': datetime(2017, 4, 22, 18, 45) }, ]) self.assertEqual(p.all_holdings, [ { 'commission': 0.0, 'ALL_UP': 0.0, 'total': 1000.0, 'datetime': datetime(2017, 4, 1, 0, 0), 'cash': 1000.0 }, { 'commission': 0.002, 'ALL_UP': 20.0, 'total': 1009.998, 'datetime': datetime(2017, 4, 22, 18, 35), 'cash': 989.99800000000005 }, { 'commission': 0.002, 'ALL_UP': 30.0, 'total': 1019.998, 'datetime': datetime(2017, 4, 22, 18, 40), 'cash': 989.99800000000005 }, { 'commission': 0.002, 'ALL_UP': 5.0, 'total': 994.99800000000005, 'datetime': datetime(2017, 4, 22, 18, 45), 'cash': 989.99800000000005 }, ]) bars.update_bars() p.update_timeindex(None) self.assertEqual(p.all_positions, [ { 'ALL_UP': 0, 'datetime': datetime(2017, 4, 1, 0, 0) }, { 'ALL_UP': 1.0, 'datetime': datetime(2017, 4, 22, 18, 35) }, { 'ALL_UP': 1.0, 'datetime': datetime(2017, 4, 22, 18, 40) }, { 'ALL_UP': 1.0, 'datetime': datetime(2017, 4, 22, 18, 45) }, { 'ALL_UP': 1.0, 'datetime': datetime(2017, 4, 22, 18, 50) }, ]) self.assertEqual(p.all_holdings, [ { 'commission': 0.0, 'ALL_UP': 0.0, 'total': 1000.0, 'datetime': datetime(2017, 4, 1, 0, 0), 'cash': 1000.0 }, { 'commission': 0.002, 'ALL_UP': 20.0, 'total': 1009.998, 'datetime': datetime(2017, 4, 22, 18, 35), 'cash': 989.99800000000005 }, { 'commission': 0.002, 'ALL_UP': 30.0, 'total': 1019.998, 'datetime': datetime(2017, 4, 22, 18, 40), 'cash': 989.99800000000005 }, { 'commission': 0.002, 'ALL_UP': 5.0, 'total': 994.99800000000005, 'datetime': datetime(2017, 4, 22, 18, 45), 'cash': 989.99800000000005 }, { 'commission': 0.002, 'ALL_UP': 50.0, 'total': 1039.998, 'datetime': datetime(2017, 4, 22, 18, 50), 'cash': 989.99800000000005 }, ])
def simulate(): events = queue.Queue() ##Set this directory as the one where you will store the .csv files by ticker symbol ex. FB.csv etc it will be named from root ##so a directory in your home folder might be /home/data where /data is the folder with the files directory = '/twoterradata' ab_path = os.path.abspath(directory) ##Below symbol list for stocks ##Could be modified for Futures symbol_list = ['FB', 'AAPL', 'GOOG'] ##list of thresholds to be set initially for each stock/futures symbols and passed in to the strategy class ##May need to think through whether these can work better with Order types of LMT, Trailing Orders etc for better execution # g_sell_gain_thresh = 0 # g_sell_loss_thresh = 0 # g_buy_thresh = 0 # g_buy_again_thresh = 0 # g_incr is the global_thresholds = { 'g_sell_gain_thresh': 0, 'g_sell_loss_thresh': 0, 'g_buy_thresh': 0, 'g_buy_again_thresh': 0, 'g_incr': 0 } for s in symbol_list: global_symbol_thresholds[s] = global_thresholds ##Futures_list --would have to update code or use the current symbol_list variable modified for Futures ##Define these global thresholds for each value in the symbol ##Ensures person executes this tester on a Linux or Mac or uses a VM if platform.system() not in ['Linux', 'Darwin']: print "Program must run on Linux/Unix system or on Virtual Machine running such a system, please run again" quit() ##ensure you are logged into session at quandl or set the api key, but for WIKI dataset not necessary ##Below URL will be modifed to obtain futures dataset and most likely will be modified with database queries quandl_url = "\'https://www.quandl.com/api/v3/datasets/WIKI/" for s in symbol_list: if os.path.exists(ab_path + '/' + s + '.csv'): days_modified = (calendar.timegm(time.gmtime()) - os.path.getmtime(ab_path + '/' + s + '.csv')) if days_modified > 86400: cmd = "curl " + quandl_url + s + "/data.csv\'" + "> \'" + ab_path + '/' + s + ".csv\'" os.system(cmd) else: cmd = "curl " + quandl_url + s + "/data.csv\'" + "> \'" + ab_path + '/' + s + ".csv\'" os.system(cmd) print global_symbol_thresholds bars = HistoricCSVDataHandler(events, ab_path + '/', symbol_list) ##strategy = BuyAndHoldStrategy(bars, events) ##strategy for simple trends, this variable must be set as a list to test multiple strategies etc. ## Set strategy by modifying here strategy = SimpleTrendsStrategy(bars, events) port = NaivePortfolio(bars, events, "2015-11-18") broker = SimulatedExecutionHandler(events) while True: # Update the bars (specific backtest code, as opposed to live trading) if bars.continue_backtest == True: bars.update_bars() else: break # Handle the events while True: try: event = events.get(False) except queue.Empty: break else: if event is not None: if event.type == 'MARKET': strategy.calculate_signals(event) port.update_timeindex(event) elif event.type == 'SIGNAL': port.update_signal(event) elif event.type == 'ORDER': #event.print_order() broker.execute_order(event) elif event.type == 'FILL': port.update_fill(event) print port.output_summary_stats() print port.all_holdings[-1]
data.update_data() #drip-feed new line of data else: break #inner loop: handles events in the queue. Breaks when the queue is empty to get new data while True: try: event = event_queue.get_nowait() #gets new event but does not wait for queue to fill again if it is empty except: #raises exception if queue is empty break if event is not None: if isinstance(event, MarketEvent): print('market event') portfolio.update_timeindex(event) strategy.calculate_signals(event) #strategy generates signals from market data elif isinstance(event, SignalEvent): #portfolio takes signals as advice on how to trade and generates orders based on these print('signal event') portfolio.update_signal(event) elif isinstance(event, OrderEvent): #executes orders print('order event') broker.execute_order(event) elif isinstance(event, FillEvent): #broker tells the portfolio how much of the order was filled print('fill event') portfolio.update_fill(event) portfolio.update_timeindex(event)
bars.update_bars() else: break # Handle the events while True: try: event = events.get(False) except Queue.Empty: break else: if event is not None: if event.type == 'MARKET': print 'MARKET!' strategy.calculate_signals(event) port.update_timeindex(event) elif event.type == 'SIGNAL': print 'SIGNAL!' port.update_signal(event) elif event.type == 'ORDER': print 'ORDER!' broker.execute_order(event) #problem elif event.type == 'FILL': print 'FILL!' port.update_fill(event) #time.sleep(.1)