Forked from nicklatin/high_low_spread_estimator.py
Created
February 20, 2022 02:48
-
-
Save krishvishal/4bc56c3410e17f16d87fa82f6586028a to your computer and use it in GitHub Desktop.
Revisions
-
nicklatin revised this gist
Dec 23, 2021 . No changes.There are no files selected for viewing
-
nicklatin revised this gist
Dec 23, 2021 . 1 changed file with 24 additions and 20 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,34 +1,36 @@ # high-low spread estimator (hlse) def hlse(ohlc_df, frequency='daily'): """ 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 Parameters ---------- ohlc_df: DataFrame DataFrame with DatetimeIndex and Open, High, Low and Close (OHLC) prices from which to compute the high-low spread estimates. frequency: str, {'daily', 'weekly', 'monthly'}, default 'daily' daily: daily bid-offer spread estimate. weekly: weekly bid-offer spread estimate, resampled over a weekly frequency as the mean of daily estimates. monthly: monthly bid-offer spread estimate, resampled over a monthly frequency as the mean of daily estimates. Returns ------- S: Series Datetimeindex and time series of high-low spread estimates. """ # define vars: mid, 2 day high and 2 day low vars mid, high_2d, low_2d = (ohlc_df.high + ohlc_df.low)/2, ohlc_df.high.rolling(2).max(), ohlc_df.low.rolling(2).min() # compute adjustment for overnight price moves ohlc_df['gap_up'], ohlc_df['gap_down'] = ohlc_df.low - ohlc_df.close.shift(1), ohlc_df.high - ohlc_df.close.shift(1) # adjustment for gap up ohlc_df['high_adj'], ohlc_df['low_adj'] = np.where(ohlc_df.gap_up > 0, ohlc_df.high - ohlc_df.gap_up, ohlc_df.high), np.where(ohlc_df.gap_up > 0, ohlc_df.low - ohlc_df.gap_up, ohlc_df.low) # adjustment for gap down ohlc_df['high_adj'], ohlc_df['low_adj'] = np.where(ohlc_df.gap_down < 0, ohlc_df.high - ohlc_df.gap_down, ohlc_df.high), np.where(ohlc_df.gap_down < 0, ohlc_df.low - ohlc_df.gap_down, ohlc_df.low) # B beta B = (np.log(ohlc_df.high_adj/ohlc_df.low_adj))**2 + (np.log(ohlc_df.high_adj.shift(1)/ohlc_df.low_adj.shift(1)))**2 # G gamma G = (np.log(high_2d/low_2d))**2 # alpha @@ -38,9 +40,11 @@ def hlse(df, frequency='daily'): # 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 == 'weekly': S = S.resample('W').mean() if frequency == 'monthly': S = S.resample('M').mean() # drop NaNs S.dropna(inplace=True) return S -
nicklatin created this gist
Dec 13, 2021 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,46 @@ # 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