The provided trading strategy code models one-way slippage of 3 basis points (see the SLIPPAGE_BPS
parameter). This notebook investigates spreads with more precision, as they vary by leveraged ETF. To do so, we collect 1 month of bid/ask data for the leveraged ETFs and calculate the spreads at 2:15 PM (the time we enter positions).
Spread analysis uses data from Interactive Brokers.
First, create a database for the historical data:
from quantrocket.history import create_ibkr_db
create_ibkr_db("leveraged-etf-quotes-1min",
universes="leveraged-etf",
bar_size="1 min",
bar_type="BID_ASK",
start_date="2019-01-01",
end_date="2019-01-31",
shard="off")
{'status': 'successfully created quantrocket.v2.history.leveraged-etf-quotes-1min.sqlite'}
Then collect the data:
from quantrocket.history import collect_history
collect_history("leveraged-etf-quotes-1min")
{'status': 'the historical data will be collected asynchronously'}
Monitor flightlog for the completion message:
quantrocket.history: INFO [leveraged-etf-quotes-1min] Collecting history from IBKR for 14 securities in leveraged-etf-quotes-1min
quantrocket.history: INFO [leveraged-etf-quotes-1min] Saved 114660 total records for 14 total securities to quantrocket.v2.history.leveraged-etf-quotes-1min.sqlite
Now we can load the bid/ask data and check the spreads.
from quantrocket import get_prices
prices = get_prices("leveraged-etf-quotes-1min", fields=["Open","Close"], times="14:15:00")
For this bar type, the "Open" contains the time-average bid and the "Close" contains the time-average ask.
bids = prices.loc["Open"]
asks = prices.loc["Close"]
Compute the spreads in basis points:
spreads = (asks - bids)
spreads_in_bps = (spreads/bids).astype(float)
Replace sids with symbols for easier readability:
from quantrocket.master import get_securities_reindexed_like
symbols = get_securities_reindexed_like(bids, fields="Symbol").loc["Symbol"]
symbols = symbols.iloc[0].to_dict()
spreads_in_bps = spreads_in_bps.rename(columns=symbols)
Finally, check the spreads at 2:15 PM:
spreads_in_bps.xs("14:15:00", level="Time").mean() * 1e4
Sid SPXL 3.140246 TNA 4.769774 ERX 5.654112 TMF 5.985715 UPRO 4.097632 DRN 70.678831 YINN 5.168800 UDOW 3.957265 URTY 9.336790 FAS 7.547277 EDC 10.734769 RUSL 22.694030 JNUG 10.018724 NUGT 5.738911 dtype: float64
The spreads range from 3 basis points to 70 basis points. Because the strategy enters during the trading session and exits on-the-close, we expect to pay half the spread on our entries but we do not expect to incur any slippage on our exits. Thus, we should average the spread of the securities we intend to trade, then divide by 2 since we only expect to pay half the spread, then divide by 2 again since we only expect to incur slippage on our entries, not our exits.