Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save krishvishal/4bc56c3410e17f16d87fa82f6586028a to your computer and use it in GitHub Desktop.

Select an option

Save krishvishal/4bc56c3410e17f16d87fa82f6586028a to your computer and use it in GitHub Desktop.
Computes the high-low spread estimator, an estimate of bid-offer spreads, a measure of liquidity risk. See Corwin & Schultz (2011) for details: https://papers.ssrn.com/sol3/papers.cfm?abstract_id=1106193
# high-low spread estimator (hlse) provides an estimate of bid-offer spreads, a measure of liquidity risk
# described in Corwin and Schultz (2011): https://papers.ssrn.com/sol3/papers.cfm?abstract_id=1106193
def hlse(df, frequency='daily'):
"""
Computes the high-low spread estimator, an estimate of bid-offer spreads, described by Corwin & Schultz (2011)
Parameters
----------
df: DataFrame
dataframe with date, open, high, low and close (OHLC) time series
frequency: str
'daily' for daily bid-offer spread estimate, or 'monthly' for monthly bid-offer spread estimate, defaults to daily
Returns
-------
S: series
time series of high-low spread estimate
"""
# define mid, 2 day high and 2 day low vars
mid, high_2d, low_2d = (df.high + df.low)/2, df.high.rolling(2).max(), df.low.rolling(2).min()
# adjustment for overnight price moves
df['gap_up'], df['gap_down'] = df.low - df.close.shift(1), df.high - df.close.shift(1)
df['high_adj'], df['low_adj'] = np.where(df.gap_up > 0, df.high - df.gap_up, df.high), np.where(df.gap_up > 0, df.low - df.gap_up, df.low)
df['high_adj'], df['low_adj'] = np.where(df.gap_down < 0, df.high - df.gap_down, df.high), np.where(df.gap_down < 0, df.low - df.gap_down, df.low)
# B beta
B = (np.log(df.high_adj/df.low_adj))**2 + (np.log(df.high_adj.shift(1)/df.low_adj.shift(1)))**2
# G gamma
G = (np.log(high_2d/low_2d))**2
# alpha
alpha = ((np.sqrt(2 * B) - np.sqrt(B)) / (3 - 2 * np.sqrt(2))) - (np.sqrt(G/(3 - 2 * np.sqrt(2))))
# replace negative values by 0
alpha = pd.Series(np.where(alpha < 0, 0, alpha), index=alpha.index)
# substitute alpha into equation 14 to get high-low spread estimate S
S = (2 * (np.exp(alpha) - 1)) / (1 + np.exp(alpha))
# resample using daily mean
if frequency == 'monthly':
S = S.resample('M').mean()
# drop NaNs
S.dropna(inplace=True)
return S
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment