Backtesting with tick data and ask/bid prices
-
Hi,
I know similar questions have been already asked in the forums but I just want to make sure I understand everything correctly.
I need to work with historical tick data (every price change) and ask/bid prices.
From what I understand you can use this type of data in your backtests for calculations, resampling etc.
But it's not possible to test solely on tick data because the Broker and the trade functions require close or open prices. When I tried it in practice I was able to read my custom data feed and print the prices. But when I started placing orders I got errors like for example: AttributeError: 'Lines_LineSeries_DataSeries_OHLC_OHLCDateTime_Abst' object has no attribute 'close'
The columns in the feed are just:
datetime, bid, askThank you in advance for any comments on this. I can provide minimum example if needed.
-
First and foremost: backtrader is not a backtesting engine which supports
bid/ask
for execution. In most cases, people use either thebid
,ask
ormidpoint
component to decide what's the current priceWhen you say
@malapija said in Backtesting with tick data and ask/bid prices:
I need to work with historical tick data (every price change) and ask/bid prices.
It would seem you have an extra component besides
bid
andask
@malapija said in Backtesting with tick data and ask/bid prices:
The columns in the feed are just:
datetime, bid, askBut you don't.
@malapija said in Backtesting with tick data and ask/bid prices:
But it's not possible to test solely on tick data because the Broker and the trade functions require close or open prices
And
high
andlow
to make the best possible matching engine withStop
/Limit
(and their combinations) orders.With all that in mind and if you still think you want to use backtrader, you could do the following:
- Decide if you want to use
bid
,ask
ormidpoint
- Load the data feed
- If you are using
bid
, use the value for all componentsopen
,high
,low
andclose
- If you are using
ask
, use the value for all componentsopen
,high
,low
andclose
- If you have chosen
midpoint
, you may placebid
inopen
andask in
close`- Add a
Filter
which averages both theopen
and theclose
and uses the result to replace the values of the OHLC components
- Add a
- If you are using
Now you are ready to go.
- Decide if you want to use
-
Thank you for the quick reply!
@backtrader said in Backtesting with tick data and ask/bid prices:
It would seem you have an extra component besides
bid
andask
Indeed. I wanted to keep the example simple because I think if I can make this simple version work I'll be able to figure out the rest. But in fact I have a market depth with n-prices and n-volumes for multiple assets. I'm exploring triangular arbitrage in illiquid markets.
Thank you for pointing me to the Filter. As I understand it you can use it to modify the incoming data feed. What complicates it in my case is that I sometimes need to use ask and sometimes bid based on the currently opened positions and the current arbitrage opportunity which is calculated in the strategy on each incoming tick.
Concrete (simplified) example: Let's say we have two assets: A1, A2 with bid/ask prices A1.b, A1.a, A2.b, A2.a. An arbitrage opportunity between A1 and A2 appears and we need to go long on A1, short on A2. Therefore we need to use A1.a for entering the long position and A2.b for entering the short position (assuming Market orders). The difference between bid and ask is quite important in this case because with arbitrage we're going for tiny market inefficiencies.
My current understanding from what I tried with backtrader and from what you wrote is that this probably won't be possible, right? I also explored all other Python backtesting frameworks you mention in Github README and it seems that none of them will be easily applicable to my use case although I need to explore QSTrader and QTPyLib in more depth.
-
@malapija said in Backtesting with tick data and ask/bid prices:
Concrete (simplified) example: Let's say we have two assets: A1, A2 with bid/ask prices A1.b, A1.a, A2.b, A2.a. An arbitrage opportunity between A1 and A2 appears and we need to go long on A1, short on A2. Therefore we need to use A1.a for entering the long position and A2.b for entering the short position (assuming Market orders). The difference between bid and ask is quite important in this case because with arbitrage we're going for tiny market inefficiencies.
Your problem is that you are expecting an execution which is not part of backtrader. Backtrader works on the principle that a price which has been seen cannot used for matching. If you have seen
A1.a
andA2.b
, the prices are gone. YourMarket
orders will be executed with the next incoming prices.In your case the
cheat-on-close
mode won't help, because forA2.b
you would need to be matched with for example the currentopen
price forA2
which is where you would code that information (A1.a
would be encoded in theclose
price ofA1
)As stated at the beginning: backtrader was not conceived for
bid/ask
execution.@malapija said in Backtesting with tick data and ask/bid prices:
My current understanding from what I tried with backtrader and from what you wrote is that this probably won't be possible, right? I also explored all other Python backtesting frameworks you mention in Github README and it seems that none of them will be easily applicable to my use case although I need to explore QSTrader and QTPyLib in more depth
I don't think they are meant for
bid/ask
execution either, but the platforms (except for 2 or 3) were not explored in full detail.