def test_historical_data_handler(self): s = 'BTC_ETC' events_queue = queue.Queue(100) data = HistoricCSVDataHandler( events_queue, './tests/datasets', [s], ['open', 'high', 'low', 'close'] ) self.assertEqual(set(data.symbol_data.keys()), {s}) data.update_bars() d = data.get_latest_bars(s)[0] self.assertEqual(round(d.open, 8), 0.00258999) self.assertEqual(round(d.high, 8), 0.00259506) self.assertEqual(round(d.low, 8), 0.00258998) self.assertEqual(round(d.close, 8), 0.00259474) self.assertEqual(data.get_latest_bars(s)[0], d) self.assertEqual(data.get_latest_bars(s), [d]) self.assertEqual(data.get_latest_bars_values(s, 'datetime')[0], d.datetime) self.assertEqual(round(data.get_latest_bars_values(s, 'open')[0], 8), 0.00258999) values = data.get_latest_bars_values(s, 'open') self.assertEqual(round(values[0], 8), 0.00258999)
def test_bnh_strategy(self): events_queue = queue.Queue(100) bars = HistoricCSVDataHandler( events_queue, './tests/datasets/', ['BTC_ETC'], ['open', 'high', 'low', 'close'] ) strategy = BuyAndHoldStrategy(bars, events_queue) bars.update_bars() event = events_queue.get(False) strategy.calculate_signals(event) signal = events_queue.get(False) self.assertEqual(signal.symbol, 'BTC_ETC') self.assertEqual(signal.strategy_id, 'BUY_AND_HOLD') self.assertEqual(signal.signal_type, 'LONG')
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 "Buy and Hold" we generate a single signal per symbol and then no additional signals. This means we are constantly long the market from the date of strategy initialisation. Parameters event - A MarketEvent object. """ if event.type == 'MARKET': for s in self.symbol_list: bars = self.bars.get_latest_bars(s, N=1) if bars is not None and bars != []: if self.bought[s] == False: # (Symbol, Datetime, Type = LONG, SHORT or EXIT) signal = SignalEvent(bars[0][0], bars[0][1], 'LONG') self.events.put(signal) self.bought[s] = True if __name__ == '__main__': event = Queue() bars = HistoricCSVDataHandler(event, csv_dir='', symbol_list=['000001']) bars.update_bars() strategy = BuyAndHoldStrategy(bars, event) market = MarketEvent() strategy.calculate_signals(market)
# 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)
import time import queue 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:
if __name__ == '__main__': from strategy import BuyAndHoldStrategy from event import * from portfolio import ClainPortfolio import socket events = Queue.Queue() #q.put(MarketEvent()) symbol = 'USDEUR' laptop_dir = '/home/dimitris/gitProjects/fxtrade/data' desktop_dir = '/home/dimitris/workspace/python/PycharmProjects/quant/data' disou_path = 'C:\Users\Dimitris\PycharmProjects\quant\data' if socket.gethostname() == 'laptop': bars = HistoricCSVDataHandler( events, laptop_dir, [f[:-4] for f in os.listdir(laptop_dir) if f.endswith('.csv')]) elif socket.gethostname() == 'desktop': bars = HistoricCSVDataHandler( events, desktop_dir, [f[:-4] for f in os.listdir(desktop_dir) if f.endswith('.csv')]) elif socket.gethostname() == 'Disou_pc': bars = HistoricCSVDataHandler( events, disou_path, [f[:-4] for f in os.listdir(disou_path) if f.endswith('.csv')]) strategy = BuyAndHoldStrategy(bars, events) #strategy = PivotMA(bars,events,plot=False) port = ClainPortfolio(bars, events, '20010103 00:00:00',
import queue import time 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:
import datetime #MYMODULES 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:
#from data import DataHandler #actually a subclass of DataHandler 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)
'Собираем список тикетов, которых нет в каталоге' av_list = [] for symbol in symbol_list: if symbol not in dir_list: av_list.append(symbol) if av_list: AlphaVantage( symbol_list=av_list, key=conf.keys['alpha vantage']['key'], url=conf.keys['alpha vantage']['url']).take_csv(outputsize='full') events = queue.Queue() start_date = conf.values['date']['start_date'] bars = HistoricCSVDataHandler(events, dir_path, symbol_list, start_date) port = NaivePortfolio_add_founds( bars, events, start_date, initial_capital=conf.values['money']['initial_capital'], buy_quantity=10.0, add_funds=conf.values['money']['add_funds']) strategy = BuyAndHoldStrategy(bars, events, port) broker = SimulatedExecutionHandler(events) while True: # Обновляем бары (код для бэктестинга, а не живой торговли) if bars.continue_backtest == True: bars.update_bars() else:
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 }, ])
import datetime try: import Queue as queue 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:
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]
#PYTHON from queue import Queue import time #PROJECT from events import (MarketEvent, SignalEvent, OrderEvent, FillEvent) from data import HistoricCSVDataHandler from strategy import BuyAndHoldStrategy from portfolio import BacktestPortfolio from broker import BacktestBroker #MODULE event_queue = Queue() data = HistoricCSVDataHandler(event_queue, ["AAPL", "BRK-B", "CVX", "KO"]) strategy = BuyAndHoldStrategy(data, event_queue) portfolio = BacktestPortfolio(event_queue, data, "2015-01-01", 10000) broker = BacktestBroker(event_queue) while True: if data.continue_backtest is True: data.update_latest_data() else: break while True: try: event = event_queue.get(block=False) except: break if event is not None:
total_return = self.equity_curve['equity_curve'].iloc[-1] returns = self.equity_curve['returns'] pnl = self.equity_curve['equity_curve'] sharpe_ratio = create_sharpe_ratio(returns, periods=5.75*60*60) drawdown, max_dd, dd_duration = create_drawdowns(pnl) self.equity_curve['drawdown'] = drawdown stats = [("Total Return", "%0.2f%%" % ((total_return - 1.0) * 100.0)), ("Sharpe Ratio", "%0.2f" % sharpe_ratio), ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)), ("Drawdown Duration", "%d" % dd_duration)] self.equity_curve.to_csv('equity.csv') return stats if __name__ == '__main__': data_handler = HistoricCSVDataHandler(events=queue.Queue(), csv_dir='D:\\tick_data\\test_data', symbol_list=['A2001_2019-11-05', 'A2001_2019-11-06']) portfolio = Portfolio(bars=data_handler, events=queue.Queue(), start_date=1) market_event = MarketEvent() i = 0 while i < 5: i += 1 data_handler.update_bars() fill_event = FillEvent(direction='BUY', fill_cost=3, quantity=10, symbol='A2001_2019-11-05', timeindex='09:00:01', exchange='dalian') portfolio.update_fill(fill_event) portfolio.update_timeindex(market_event) # print(portfolio.all_holdings) # print(portfolio.current_holdings)