knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 6, warning = FALSE, message = FALSE )
This vignette illustrates how to estimate bid-ask spreads from open, high, low, and close prices. Let's start by loading the package:
library(bidask)
The package offers two ways to estimate bid-ask spreads:
edge()
: designed for tidy data.spread()
: designed for xts
objects.The function edge()
implements the efficient estimator described in Ardia, Guidotti, & Kroencke (2024). Open, high, low, and close prices are to be passed as separate vectors.
The function spread()
requires an xts
object containing columns named Open
, High
, Low
, Close
and it provides additional functionalities, such as additional estimators and rolling estimates.
An output value of 0.01 corresponds to a spread estimate of 1%.
Examples are provided below.
The function edge()
can be easily used with tidy data and the dplyr
grammar. In the following example, we estimate bid-ask spreads for cryptocurrencies.
Download daily prices for Bitcoin and Ethereum using the crypto2 package:
library(dplyr) library(crypto2) df <- crypto_list(only_active=TRUE) %>% filter(symbol %in% c("BTC", "ETH")) %>% crypto_history(start_date = "20200101", end_date = "20221231")
head(df)
Estimate the spread for each coin in each year:
df %>% mutate(yyyy = format(timestamp, "%Y")) %>% group_by(symbol, yyyy) %>% arrange(timestamp) %>% summarise(EDGE = edge(open, high, low, close))
xts
objectsThe function spread()
provides additional functionalities for xts objects. In the following example, we estimate bid-ask spreads for equities.
Download daily data for Microsoft (MSFT) using the quantmod package:
library(quantmod) x <- getSymbols("MSFT", auto.assign = FALSE, start = "2019-01-01", end = "2022-12-31") head(x)
This is an xts
object:
class(x)
So we can estimate the spread with:
spread(x)
By default, the call above is equivalent to:
edge(open = x[,1], high = x[,2], low = x[,3], close = x[,4])
But spread()
also provides additional functionalities. For instance, estimate the spread for each month and plot the estimates:
sp <- spread(x, width = endpoints(x, on = "months")) plot(sp)
Or estimate the spread using a rolling window of 21 obervations:
sp <- spread(x, width = 21) plot(sp)
To illustrate higher-frequency estimates, we are going to download intraday data from Alpha Vantage. You must register with Alpha Vantage in order to download their data, but the one-time registration is fast and free. Register at https://www.alphavantage.co/ to receive your key. You can set the API key globally as follows:
setDefaults(getSymbols.av, api.key = "<API-KEY>")
Download minute data for Microsoft:
x <- getSymbols( Symbols = "MSFT", auto.assign = FALSE, src = "av", periodicity = "intraday", interval = "1min", output.size = "full")
x <- read.csv(system.file("extdata", "msft.csv", package = "bidask")) x <- xts(x[,-1], order.by = as.POSIXct(x[,1]))
head(x)
Estimate the spread for each day and plot the estimates:
sp <- spread(x, width = endpoints(x, on = "day")) plot(sp)
If you find this package useful, please star the repo!
The repository also contains implementations for Python, C++, MATLAB, and more.
Ardia, D., Guidotti, E., Kroencke, T.A. (2024). Efficient Estimation of Bid-Ask Spreads from Open, High, Low, and Close Prices. Journal of Financial Economics, 161, 103916. doi: 10.1016/j.jfineco.2024.103916
A BibTex entry for LaTeX users is:
@article{edge, title = {Efficient estimation of bid–ask spreads from open, high, low, and close prices}, journal = {Journal of Financial Economics}, volume = {161}, pages = {103916}, year = {2024}, doi = {https://doi.org/10.1016/j.jfineco.2024.103916}, author = {David Ardia and Emanuele Guidotti and Tim A. Kroencke}, }
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.