Package 'bidask'

Title: Efficient Estimation of Bid-Ask Spreads from Open, High, Low, and Close Prices
Description: Implements the efficient estimator of bid-ask spreads from open, high, low, and close prices described in Ardia, Guidotti, & Kroencke (JFE, 2024) <doi:10.1016/j.jfineco.2024.103916>. It also provides an implementation of the estimators described in Roll (JF, 1984) <doi:10.1111/j.1540-6261.1984.tb03897.x>, Corwin & Schultz (JF, 2012) <doi:10.1111/j.1540-6261.2012.01729.x>, and Abdi & Ranaldo (RFS, 2017) <doi:10.1093/rfs/hhx084>.
Authors: Emanuele Guidotti [aut, cre] , David Ardia [ctb] , Tim Kroencke [ctb]
Maintainer: Emanuele Guidotti <[email protected]>
License: MIT + file LICENSE
Version: 2.1.2
Built: 2025-02-14 19:18:04 UTC
Source: https://github.com/eguidotti/bidask

Help Index


Efficient Estimation of Bid-Ask Spreads from Open, High, Low, and Close Prices

Description

Implements the efficient estimator of bid-ask spreads from open, high, low, and close prices described in Ardia, Guidotti, & Kroencke (JFE, 2024): doi:10.1016/j.jfineco.2024.103916

Usage

edge(open, high, low, close, sign = FALSE)

Arguments

open

numeric vector of open prices.

high

numeric vector of high prices.

low

numeric vector of low prices.

close

numeric vector of close prices.

sign

whether to return signed estimates.

Details

Prices must be sorted in ascending order of the timestamp.

Value

The spread estimate. A value of 0.01 corresponds to a spread of 1%.

References

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

Examples

# simulate open, high, low, and close prices with spread 1%
x <- sim(n = 1000, spread = 0.01)

# estimate the spread
edge(x$Open, x$High, x$Low, x$Close)

Expanding Estimates of Bid-Ask Spreads from Open, High, Low, and Close Prices

Description

Implements an expanding window calculation of the efficient estimator of bid-ask spreads from open, high, low, and close prices described in Ardia, Guidotti, & Kroencke (JFE, 2024): doi:10.1016/j.jfineco.2024.103916.

Usage

edge_expanding(open, high, low, close, sign = FALSE, na.rm = TRUE)

Arguments

open

numeric vector of open prices.

high

numeric vector of high prices.

low

numeric vector of low prices.

close

numeric vector of close prices.

sign

whether to return signed estimates.

na.rm

whether to ignore missing values.

Details

Prices must be sorted in ascending order of the timestamp.

Value

Vector of spread estimates. A value of 0.01 corresponds to a spread of 1%. This function always returns a result of the same length as the input prices.

References

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

Examples

# simulate open, high, low, and close prices with spread 1%
x <- sim(n = 1000, spread = 0.01)

# estimate the spread using an expanding window
s <- edge_expanding(x$Open, x$High, x$Low, x$Close)
tail(s)
# equivalent to
s <- edge_rolling(x$Open, x$High, x$Low, x$Close, width = 1:nrow(x), na.rm = TRUE)
tail(s)

Rolling Estimates of Bid-Ask Spreads from Open, High, Low, and Close Prices

Description

Implements a rolling window calculation of the efficient estimator of bid-ask spreads from open, high, low, and close prices described in Ardia, Guidotti, & Kroencke (JFE, 2024): doi:10.1016/j.jfineco.2024.103916.

Usage

edge_rolling(open, high, low, close, width, sign = FALSE, na.rm = FALSE)

Arguments

open

numeric vector of open prices.

high

numeric vector of high prices.

low

numeric vector of low prices.

close

numeric vector of close prices.

width

if an integer, the width of the rolling window. If a vector with the same length of the input prices, the width of the window corresponding to each observation. Otherwise, a vector of endpoints. See examples.

sign

whether to return signed estimates.

na.rm

whether to ignore missing values.

Details

Prices must be sorted in ascending order of the timestamp.

Value

Vector of spread estimates. A value of 0.01 corresponds to a spread of 1%. This function always returns a result of the same length as the input prices.

References

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

Examples

# simulate open, high, low, and close prices with spread 1%
x <- sim(n = 1000, spread = 0.01)

# estimate the spread using a rolling window
s <- edge_rolling(x$Open, x$High, x$Low, x$Close, width = 21)
tail(s)

# estimate the spread using custom endpoints
ep <- c(3, 35, 100)
s <- edge_rolling(x$Open, x$High, x$Low, x$Close, width = ep)
s[c(35, 100)]
# equivalent to
edge(x$Open[3:35], x$High[3:35], x$Low[3:35], x$Close[3:35])
edge(x$Open[35:100], x$High[35:100], x$Low[35:100], x$Close[35:100])

# estimate the spread using an expanding window
s <- edge_rolling(x$Open, x$High, x$Low, x$Close, width = 1:nrow(x))
tail(s)
# equivalent to
s <- edge_expanding(x$Open, x$High, x$Low, x$Close, na.rm = FALSE)
tail(s)

Simulation of Open, High, Low, and Close Prices

Description

This function performs simulations consisting of n periods and where each period consists of a given number of trades. For each trade, the actual price PtP_t is simulated as Pt=Pt1eσxP_t = P_{t-1}e^{\sigma x}, where σ\sigma is the standard deviation per trade and xx is a random draw from a unit normal distribution. The standard deviation per trade equals the volatility divided by the square root of the number of trades. Trades are assumed to be observed with a given probability. The bid (ask) for each trade is defined as PtP_t multiplied by one minus (plus) half the spread and we assume a 50% chance that a bid (ask) is observed. High and low prices equal the highest and lowest prices observed during the period. Open and Close prices equal the first and the last price observed in the period. If no trade is observed for a period, then the previous Close is used as the Open, High, Low, and Close prices for that period.

Usage

sim(
  n = 10000,
  trades = 390,
  prob = 1,
  spread = 0.01,
  volatility = 0.03,
  overnight = 0,
  drift = 0,
  units = 1,
  sign = FALSE
)

Arguments

n

the number of periods to simulate.

trades

the number of trades per period.

prob

the probability to observe a trade.

spread

the bid-ask spread.

volatility

the open-to-close volatility.

overnight

the close-to-open volatility.

drift

the expected return per period.

units

the units of the time period. One of: 1, sec, min, hour, day, week, month, year.

sign

whether to return positive prices for buys and negative prices for sells.

Value

A data.frame of open, high, low, and close prices if units=1 (default). Otherwise, an xts object is returned (requires the xts package to be installed).

References

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

Examples

# simulate 10 open, high, low, and close prices with spread 1%
sim(n = 10, spread = 0.01)

Estimation of Bid-Ask Spreads from Open, High, Low, and Close Prices

Description

This function implements several methods to estimate bid-ask spreads from open, high, low, and close prices and it is optimized for fast calculations over rolling and expanding windows.

Usage

spread(x, width = nrow(x), method = "EDGE", sign = FALSE, na.rm = FALSE)

Arguments

x

tabular data with columns named open, high, low, close (case-insensitive).

width

if an integer, the width of the rolling window. If a vector with the same length of the input prices, the width of the window corresponding to each observation. Otherwise, a vector of endpoints. By default, the full sample is used to compute a single spread estimate. See examples.

method

the estimators to use. See details.

sign

whether to return signed estimates.

na.rm

whether to ignore missing values.

Details

The method EDGE implements the Efficient Discrete Generalized Estimator described in Ardia, Guidotti, & Kroencke (JFE, 2024).

The methods OHL, OHLC, CHL, CHLO implement the generalized estimators described in Ardia, Guidotti, & Kroencke (JFE, 2024). They can be combined by concatenating their identifiers, e.g., OHLC.CHLO uses an average of the OHLC and CHLO estimators.

The method AR implements the estimator described in Abdi & Ranaldo (RFS, 2017). AR2 implements their 2-period version.

The method CS implements the estimator described in Corwin & Schultz (JF, 2012). CS2 implements their 2-period version. Both versions are adjusted for overnight (close-to-open) returns as described in the paper.

The method ROLL implements the estimator described in Roll (JF, 1984).

Value

A data.frame of spread estimates, or an xts object if x is of class xts. A value of 0.01 corresponds to a spread of 1%.

References

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

Abdi, F., & Ranaldo, A. (2017). A simple estimation of bid-ask spreads from daily close, high, and low prices. Review of Financial Studies, 30 (12), 4437-4480. doi:10.1093/rfs/hhx084

Corwin, S. A., & Schultz, P. (2012). A simple way to estimate bid-ask spreads from daily high and low prices. Journal of Finance, 67 (2), 719-760. doi:10.1111/j.1540-6261.2012.01729.x

Roll, R. (1984). A simple implicit measure of the effective bid-ask spread in an efficient market. Journal of Finance, 39 (4), 1127-1139. doi:10.1111/j.1540-6261.1984.tb03897.x

Examples

# simulate open, high, low, and close prices with spread 1%
x <- sim(n = 1000, spread = 0.01)

# estimate the spread
spread(x)
# equivalent to
edge(x$Open, x$High, x$Low, x$Close)

# estimate the spread using a rolling window of 21 periods
s <- spread(x, width = 21)
tail(s)
# equivalent to
s <- edge_rolling(x$Open, x$High, x$Low, x$Close, width = 21)
tail(s)

# estimate the spread using an expanding window
s <- spread(x, width = 1:nrow(x))
tail(s)
# equivalent to
s <- edge_expanding(x$Open, x$High, x$Low, x$Close, na.rm = FALSE)
tail(s)

# estimate the spread using custom endpoints
ep <- c(3, 35, 100)
spread(x, width = ep)
# equivalent to
edge(x$Open[3:35], x$High[3:35], x$Low[3:35], x$Close[3:35])
edge(x$Open[35:100], x$High[35:100], x$Low[35:100], x$Close[35:100])

# use multiple estimators
spread(x, method = c("EDGE", "AR", "CS", "ROLL", "OHLC", "OHL.CHL"))