mhallsmoore / qstrader

QuantStart.com - QSTrader backtesting simulation engine.
https://www.quantstart.com/qstrader/
MIT License
2.96k stars 856 forks source link

Bug? Execution Handler in backtests has wrong timestamp #27

Closed ryankennedyio closed 8 years ago

ryankennedyio commented 8 years ago

When doing a backtest, every FillEvent from the backtester has a timestamp of "now".

Haven't yet devoted any thought to working around this, but it definitely would be a nice thing to know when a trade 'would' have been placed in a backtest.

femtotrader commented 8 years ago

This is here:

https://github.com/mhallsmoore/qstrader/blob/master/qstrader/execution_handler/execution_handler.py#L81

mhallsmoore commented 8 years ago

This was a bit of a quick "hack" by me just to get the date in there for backtesting. I think we'll need a more sophisticated approach going forward.

It depends on how realistic we want this to be simulated. The order has to be sent from the trading workstation/server at some point in time. At the moment this is .utcnow(), but it should reference the actual timestamps of the market data.

Then of course there is the timestamp for the FillEvents, which will need to be simulated with some latency (to eventually represent slippage). The latency can be simulated using a random distribution of arrival and execution times. But...this motivates a much more sophisticated approach to slippage, where we give slightly worse bid/ask prices depending upon the market.

Lots to think about!

femtotrader commented 8 years ago

Why not using ?

timestamp  = event.timestamp
mhallsmoore commented 8 years ago

To be honest, I'm not sure! That sounds like an obvious thing to do :-)

Also, I've just noticed that I've hardcoded the exchange (ARCA) into the code as well. This will need some thought. If you look at IB, it tends to respond with different exchanges (ARCA, BATS, "Smart") etc.

femtotrader commented 8 years ago

timestamp attribute doesn't exist for this kind of event

You need (after ticker = event.ticker)

        timestamp = self.price_handler.get_timestamp(ticker)

and create this get_timestamp method in PriceHandler class

https://github.com/mhallsmoore/qstrader/blob/master/qstrader/price_handler/price_handler.py#L11

    def get_timestamp(self, ticker):
        """
        Returns the most recent actual timestamp for a given ticker
        """
        if ticker in self.tickers:
            timestamp = self.tickers[ticker]["timestamp"]
            return timestamp
        else:
            print(
                "Timestamp for ticker %s is not "
                "available from the %s." % (ticker, self.__class__.__name__)
            )
            return None
ryankennedyio commented 8 years ago

I tried a few approaches and also settled on the above by @femtotrader.

I think a live execution handler would very much benefit from using this & tying it in with the response given from the broker. That way it's easy to calculate the total time taken from when a tick was passed through the loop, to an order being confirmed. Would be quite a useful metric.

femtotrader commented 8 years ago

Fixed by https://github.com/mhallsmoore/qstrader/commit/7f38214f6b23f97431772edd4383b9c750aa220b

femtotrader commented 8 years ago

We can probably close this one also