def __init__(self, bars=None, strategy=None, port=None, broker=None, start_date=None, end_date=None): if bars is None: bars = CoinDataHandler(self, ['okcoinUSD']) if strategy is None: strategy = BuyAndHoldStrategy(bars, self) if port is None: port = NaivePortfolio(bars, self, '2017-1-1') if broker is None: broker = SimulatedExecutionHandler(self) self.bars = bars self.strategy = strategy self.port = port self.broker = broker self.__event_queue = Queue() self.__thread = Thread(target=self.__run) self.__active = False self.__handlers = { 'MARKET': [self.__filte_market_event], 'SIGNAL': [port.update_signal], 'ORDER': [broker.execute_order], 'FILL': [port.update_fill] } if start_date is not None: try: sd = datetime.datetime.strptime(start_date + " 00:00:00", "%Y-%m-%d %H:%M:%S") except ValueError: print( "Parameter start_date can't be parsed by datetime.strptime," "start_date will equal to None.") sd = None if end_date is not None: try: ed = datetime.datetime.strptime(end_date + " 00:00:00", "%Y-%m-%d %H:%M:%S") except ValueError: print( "Parameter end_date can't be parsed by datetime.strptime," "end_date will equal to None.") ed = None self.__start_date = sd self.__end_date = ed
def test_update_signal(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) bars.update_bars() signal = SignalEvent('BUY_AND_HOLD', 'BTC_ETC', datetime.utcnow(), 'LONG', 1.0) p.update_signal(signal) events_queue.get(False) # MARKET event = events_queue.get(False) # ORDER self.assertEqual(event.type, 'ORDER') self.assertEqual(event.order_type, 'MKT') self.assertEqual(event.direction, 'BUY') self.assertEqual(event.quantity, 1)
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_create(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) self.assertEqual(p.initial_capital, 1000.0) self.assertEqual(p.all_positions, [{ 'datetime': datetime(2017, 4, 1, 0, 0, 0), 'BTC_ETC': 0 }]) self.assertEqual(p.all_holdings, [{ 'datetime': datetime(2017, 4, 1, 0, 0, 0), 'BTC_ETC': 0, 'cash': 1000.0, 'commission': 0, 'total': 1000.0 }])
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)
# for l in [s+10, s+50, s+100, s+200]: # events = queue.Queue() # data = HistoricCSVDataHandler(events, 'csv/', ['OMXS30'], DataSource.NASDAQ) # # data = QuandlDataHandler(events, ['OMXS30'], config.API_KEY) # portfolio = NaivePortfolio(data, events, '', initial_capital=2000) # # strategy = BuyAndHoldStrategy(data, events, portfolio) # # strategy = SellAndHoldStrategy(data, events, portfolio) # # strategy = MovingAveragesLongShortStrategy(data, events, portfolio, 100, 200, version=1) # # strategy = MovingAveragesMomentumStrategy(data, events, portfolio, 100, 200) # # strategy = StopLossStrategy(data, events, portfolio, 0.9) # # strategy = DivideAndConquerStrategy(data, events, portfolio) # strategy = MovingAveragesLongStrategy(data, events, portfolio, s, l, version=2) # portfolio.strategy_name = strategy.name # broker = SimulateExecutionHandler(events) # print('Short: {0}, Long: {1}'.format(s, l)) # backtest(events, data, portfolio, strategy, broker) # print('----------') events = queue.Queue() data = HistoricCSVDataHandler(events, 'csv/', ['OMXS30'], DataSource.NASDAQ) portfolio = NaivePortfolio(data, events, '', initial_capital=2000) strategy = MovingAveragesLongStrategy(data, events, portfolio, 50, 100, version=1) portfolio.strategy_name = strategy.name broker = SimulateExecutionHandler(events) backtest(events, data, portfolio, strategy, broker)
from data import HistoricCSVDataHandler from portfolio import NaivePortfolio from strategy import BuyAndHoldStrategy, StatArbitrageStrategy from execution import SimulatedExecutionHandler events_queue = queue.Queue(100) broker = SimulatedExecutionHandler(events_queue) bars = HistoricCSVDataHandler(events_queue, './datasets/', ['BTC_ETC', 'BTC_LTC'], fields=[ 'open', 'high', 'low', 'close', ]) strategy = StatArbitrageStrategy(bars, events_queue) port = NaivePortfolio(bars, events_queue, None, 1000.0) def run(heartbeat=3): while True: # Update the bars (specific backtest code, as opposed to live trading) if bars.continue_backtest: bars.update_bars() else: break # Handle the events while True: try: event = events_queue.get(False) except queue.Empty:
from queue import Queue import time, datetime from data import MySQLDataHandler from strategy import BuyAndHoldStrategy, DoubleMAStrategy from portfolio import NaivePortfolio from execution import SimulatedExecutionHandler from plot import pyechartsPlotor events = Queue() bars = MySQLDataHandler(events, ['BTC-USDT'], '127.0.0.1', 'root', 'Mouyu0407', 'okex') port = NaivePortfolio(bars, events, datetime.datetime.utcnow(), initial_capital=100000.0) strategy = DoubleMAStrategy(5, 13, bars, events) broker = SimulatedExecutionHandler(bars, events) plotor = pyechartsPlotor(bars, events) while True: # Update the bars (specific backtest code, as opposed to live trading) if bars.continue_backtest: bars.update_bars() else: #port.create_equity_curve_dataframe() #port.output_summary_stats() plotor.update_ma_data(strategy) plotor.process_plot_data() plotor.plot_kline() break # Handle the events while True:
from execution import SimulatedExecutionHandler import queue # Declare event queues events = queue.Queue() # Declare the variables necessary to instantiate the class objects symbol_list = ['AAPL', 'GOOGL'] start_date = '2015-01-01' initial_capital = 100000.0 # Declare the components with respective parameters bars = HistoricQuandlDataHandler(events, symbol_list, start_date) strategy = BuyAndHoldStrategy(bars, events) port = NaivePortfolio(bars, events, start_date, initial_capital=initial_capital) 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:
import pandas as pd import matplotlib.pyplot as plt from data import HistoricCSVDataHandler from execution import SimulatedExecutionHandler from portfolio import NaivePortfolio from strategy import BuyAndHoldStrategy events = queue.Queue() start_date = "2018-01-01" stock_list = list(pd.read_csv("./../sp500.csv").iloc[:5, 0]) bars = HistoricCSVDataHandler(events, './../data', stock_list) strategy = BuyAndHoldStrategy(bars, events) port = NaivePortfolio(bars, events, start_date) broker = SimulatedExecutionHandler(events) while True: # Update the bars (specific backtest code, as opposed to live trading) if bars.continue_backtest: bars.update_bars() else: break # Handle the events while True: try: event = events.get(False) except queue.Empty: break else:
# Declare the components with respective parameters from data import HistoricCSVDataHandler from strategy import BuyAndHoldStrategy from portfolio import NaivePortfolio from execution import SimulatedExecutionHandler import queue from queue import Queue import time if __name__ == '__main__': events = Queue() bars = HistoricCSVDataHandler(events, csv_dir='', symbol_list=['000001']) strategy = BuyAndHoldStrategy(bars, events) port = NaivePortfolio(bars=bars, events=events, start_date='2018-05-01') broker = SimulatedExecutionHandler(events) while True: # Update the bars (specific backtest code, as opposed to live trading) if bars.continue_backtest: bars.update_bars() else: break # Handle the events while True: try: event = events.get(False) except queue.Empty: break else:
from queue import Queue from events import (MarketEvent, SignalEvent, OrderEvent, FillEvent) from data import HistoricCSVDataHandler from strategy import BuyAndHoldStrategy from portfolio import NaivePortfolio from execution import SimulatedExecutionHandler #INSTANTIATIONS event_queue = Queue() CSV_dir = 'INCLUDE DIRECTORY OF CSV FILES HERE' data = HistoricCSVDataHandler(event_queue, CSV_dir, ['AAPL', 'CVX']) #Input a list of stock names here strategy = BuyAndHoldStrategy(data, event_queue) start_date = datetime.date(14, 12, 1) portfolio = NaivePortfolio(event_queue, data, start_date) broker = SimulatedExecutionHandler(event_queue) #outer loop: mimicking the drip-feed of live data while True: if data.continue_backtest is True: 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
import pandas as pd import time from queue import Queue from data import HistoricPDDataHandler from strategy import BuyAndHoldStrategy, MeanReversionStrategy from execution import SimulatedExecutionHandler from portfolio import NaivePortfolio events = Queue() bars = HistoricPDDataHandler(events, "../data", ["fb"]) # strategy = BuyAndHoldStrategy(bars, events) strategy = MeanReversionStrategy(bars, events, short_window=5) # def __init__(self, bars, events, start_date, initial_capital=100000.0): port = NaivePortfolio(bars, events, "2018-10-3", 100000) broker = SimulatedExecutionHandler(events) print("Days: 50, Strategy: Mean-Reversion, Stock: FB") print("Press Enter to Start...") input() while bars.continue_backtest == True: # print ("Updating Bars.") bars.update_bars() while True: if events.empty(): break else:
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]
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 }, ])
except ImportError: import queue # declare events queue events = queue.Queue() # declare start date start_date = datetime.datetime(2015, 5, 6, 0, 0, 0) # Declare the components with respective parameters bars = HistoricCSVDataHandler( events, '/home/chris/github-repos/Enhanced-Event-Driven-Backtester-from-Quantstart/DataHub/', ['AAPL']) strategy = BuyAndHoldStrategy(bars, events) port = NaivePortfolio(bars, events, start_date, 1000000.0) 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
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)
timemodule = BackTestTimeModule(backtestlogger,tradelogger,start,end) timemodule.initTradeDays() # 管理市场信息 market = BackTestMarket(backtestlogger,timemodule,events) market.initdata() # 策略模块 imp_module = __import__(StrategyFile) classname = StrategyName StrategyFunc = getattr(imp_module, classname) strategy = StrategyFunc(backtestlogger,market,events) # 持仓模块 portfolio = NaivePortfolio(backtestlogger,tradelogger,market,events) # 执行模块 excution = SimulatedExecutionHandler(backtestlogger,events) while True: # Update the bars (specific backtest code, as opposed to live trading) market.update() if market.cotinue_backtest == False: break # Handle the events while True: # 获取待处理的事件,如果队列空就结束循环 if events.qsize() == 0: break
import os os.chdir("/home/taylor/backtester/") import Queue import time from data import HistoricCSVDataHandler from strategy import BuyAndHoldStrategy from portfolio import NaivePortfolio from execution import SimulatedExecutionHandler start_date = '2015-03-13' #figure out better solution for this events = Queue.Queue(maxsize=100) bars = HistoricCSVDataHandler(events, "/home/taylor/backtester/csv/", ['yhoo']) strategy = BuyAndHoldStrategy(bars, events) port = NaivePortfolio(bars, events, start_date, initial_capital=100000.) 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