diff --git a/backtest/backtest.py b/backtest/backtest.py index 249405c..bceba15 100644 --- a/backtest/backtest.py +++ b/backtest/backtest.py @@ -23,8 +23,9 @@ def __init__( """ Initialises the backtest. """ + import ipdb; ipdb.set_trace() self.pairs = pairs - self.events = queue.Queue() + self.events = queue.PriorityQueue() self.csv_dir = settings.CSV_DATA_DIR self.ticker = data_handler(self.pairs, self.events, self.csv_dir) self.strategy_params = strategy_params @@ -57,13 +58,13 @@ def _run_backtest(self): self.ticker.stream_next_tick() else: if event is not None: - if event.type == 'TICK': - self.strategy.calculate_signals(event) - self.portfolio.update_portfolio(event) - elif event.type == 'SIGNAL': - self.portfolio.execute_signal(event) - elif event.type == 'ORDER': - self.execution.execute_order(event) + if event[1].type == 'TICK': + self.strategy.calculate_signals(event[1]) + self.portfolio.update_portfolio(event[1]) + elif event[1].type == 'SIGNAL': + self.portfolio.execute_signal(event[1]) + elif event[1].type == 'ORDER': + self.execution.execute_order(event[1]) time.sleep(self.heartbeat) iters += 1 diff --git a/data/price.py b/data/price.py index ec0d32c..ecaa59d 100644 --- a/data/price.py +++ b/data/price.py @@ -138,7 +138,7 @@ def _open_convert_csv_files_for_day(self, date_str): for p in self.pairs: pair_path = os.path.join(self.csv_dir, '%s_%s.csv' % (p, date_str)) self.pair_frames[p] = pd.io.parsers.read_csv( - pair_path, header=True, index_col=0, + pair_path, header=0, index_col=0, parse_dates=True, dayfirst=True, names=("Time", "Ask", "Bid", "AskVolume", "BidVolume") ) @@ -199,4 +199,4 @@ def stream_next_tick(self): # Create the tick event for the queue tev = TickEvent(pair, index, bid, ask) - self.events_queue.put(tev) + self.events_queue.put((30, tev)) diff --git a/data/streaming.py b/data/streaming.py index 3abe7dd..8142fc9 100644 --- a/data/streaming.py +++ b/data/streaming.py @@ -89,4 +89,4 @@ def stream_to_queue(self): self.prices[inv_pair]["ask"] = inv_ask self.prices[inv_pair]["time"] = time tev = TickEvent(instrument, time, bid, ask) - self.events_queue.put(tev) + self.events_queue.put((50, tev)) diff --git a/event/event.py b/event/event.py index 0a7c118..7706b83 100644 --- a/event/event.py +++ b/event/event.py @@ -1,9 +1,16 @@ +from datetime import datetime + + class Event(object): - pass + def __lt__(self, other): + return self.time < other.time class TickEvent(Event): def __init__(self, instrument, time, bid, ask): + ''' + This will have priority value of 30 + ''' self.type = 'TICK' self.instrument = instrument self.time = time @@ -21,6 +28,10 @@ def __repr__(self): class SignalEvent(Event): + ''' + This will have priority value of 20 for buy event + This will have priority value of 20 for sell event + ''' def __init__(self, instrument, order_type, side, time): self.type = 'SIGNAL' self.instrument = instrument @@ -39,12 +50,16 @@ def __repr__(self): class OrderEvent(Event): + ''' + This will have priority value of 10 + ''' def __init__(self, instrument, units, order_type, side): self.type = 'ORDER' self.instrument = instrument self.units = units self.order_type = order_type self.side = side + self.time = datetime.now() def __str__(self): return "Type: %s, Instrument: %s, Units: %s, Order Type: %s, Side: %s" % ( @@ -53,4 +68,4 @@ def __str__(self): ) def __repr__(self): - return str(self) \ No newline at end of file + return str(self) diff --git a/examples/mac.py b/examples/mac.py index 6ebed7f..355b129 100644 --- a/examples/mac.py +++ b/examples/mac.py @@ -26,4 +26,4 @@ Portfolio, SimulatedExecution, equity=settings.EQUITY ) - backtest.simulate_trading() \ No newline at end of file + backtest.simulate_trading() diff --git a/logging.conf b/logging.conf index ee8ec95..0360736 100644 --- a/logging.conf +++ b/logging.conf @@ -2,27 +2,33 @@ keys=root,qsforex.trading.trading [handlers] -keys=consoleHandler +keys=consoleHandler, fileHandler [formatters] keys=simpleFormatter [logger_root] level=DEBUG -handlers=consoleHandler +handlers=consoleHandler,fileHandler [logger_qsforex.trading.trading] level=DEBUG -handlers=consoleHandler +handlers=consoleHandler,fileHandler qualname=qsforex.trading.trading propagate=0 [handler_consoleHandler] class=StreamHandler -level=DEBUG +level=INFO formatter=simpleFormatter args=(sys.stdout,) +[handler_fileHandler] +class=FileHandler +level=DEBUG +formatter=simpleFormatter +args=("output.log",) + [formatter_simpleFormatter] format=%(asctime)s - %(name)s - %(levelname)s - %(message)s datefmt= diff --git a/portfolio/portfolio.py b/portfolio/portfolio.py index c86aafb..6acad15 100644 --- a/portfolio/portfolio.py +++ b/portfolio/portfolio.py @@ -185,9 +185,8 @@ def execute_signal(self, signal_event): add_position_units(currency_pair, units) order = OrderEvent(currency_pair, units, "market", side) - self.events.put(order) + self.events.put((10, order)) self.logger.info("Portfolio Balance: %s" % self.balance) else: self.logger.info("Unable to execute order as price data was insufficient.") - \ No newline at end of file diff --git a/strategy/strategy.py b/strategy/strategy.py index 248e592..f2351fd 100644 --- a/strategy/strategy.py +++ b/strategy/strategy.py @@ -24,11 +24,11 @@ def calculate_signals(self, event): if self.ticks % 5 == 0: if self.invested == False: signal = SignalEvent(self.pairs[0], "market", "buy", event.time) - self.events.put(signal) + self.events.put((20, signal)) self.invested = True else: signal = SignalEvent(self.pairs[0], "market", "sell", event.time) - self.events.put(signal) + self.events.put((20, signal)) self.invested = False self.ticks += 1 @@ -99,4 +99,4 @@ def calculate_signals(self, event): signal = SignalEvent(pair, "market", "sell", event.time) self.events.put(signal) pd["invested"] = False - pd["ticks"] += 1 \ No newline at end of file + pd["ticks"] += 1 diff --git a/trading/trading.py b/trading/trading.py index e418896..6ce3133 100644 --- a/trading/trading.py +++ b/trading/trading.py @@ -31,16 +31,16 @@ def trade(events, strategy, portfolio, execution, heartbeat): pass else: if event is not None: - if event.type == 'TICK': - logger.info("Received new tick event: %s", event) - strategy.calculate_signals(event) - portfolio.update_portfolio(event) - elif event.type == 'SIGNAL': - logger.info("Received new signal event: %s", event) - portfolio.execute_signal(event) - elif event.type == 'ORDER': - logger.info("Received new order event: %s", event) - execution.execute_order(event) + if event[1].type == 'TICK': + logger.info("Received new tick event: %s", event[1]) + strategy.calculate_signals(event[1]) + portfolio.update_portfolio(event[1]) + elif event[1].type == 'SIGNAL': + logger.info("Received new signal event: %s", event[1]) + portfolio.execute_signal(event[1]) + elif event[1].type == 'ORDER': + logger.info("Received new order event: %s", event[1]) + execution.execute_order(event[1]) time.sleep(heartbeat) @@ -53,7 +53,7 @@ def trade(events, strategy, portfolio, execution, heartbeat): getcontext().prec = 2 heartbeat = 0.0 # Time in seconds between polling - events = queue.Queue() + events = queue.PriorityQueue() equity = settings.EQUITY # Pairs to include in streaming data set