RealizedSpread#
Description#
RealizedSpread is the part of the effective spread that the liquidity provider
keeps once the price has moved. With the quote-based trade direction (a print
above the mid is a buy, below is a sell), D = sign(price - mid),
realized = 2 * D * (price - mid measured `lag` steps later).
It compares a past trade's price to the mid lag steps afterward. What the
effective spread does not keep, effective - realized, is the price-impact or
adverse-selection component: how far the mid moved in the trade's direction after
it printed. The value at each step references a trade lag steps in the past, so
it is causal (never a future trade). The first lag samples are NaN (warmup).
Examples#
Usage plot#
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from screamer import EffectiveSpread, RealizedSpread
rng = np.random.default_rng(2)
n = 4000
half_spread = 0.10
mid = np.empty(n)
mid[0] = 100.0
price = np.empty(n)
side = rng.choice([-1.0, 1.0], size=n) # trade direction
for t in range(n):
price[t] = mid[t] + side[t] * half_spread # trade at bid/offer
step = rng.standard_normal() * 0.01 + side[t] * 0.02 # adverse drift after the trade
if t + 1 < n:
mid[t + 1] = mid[t] + step
lag = 20
eff = EffectiveSpread()(price, mid)
real = RealizedSpread(lag=lag)(price, mid)
impact = eff - real # price-impact / adverse selection
fig = go.Figure()
labels = ['effective spread', 'realized spread', 'price impact']
series = [eff, real, impact]
colors = ['crimson', 'seagreen', 'steelblue']
for lab, s, c in zip(labels, series, colors):
fig.add_trace(go.Bar(x=[lab], y=[np.nanmean(s)], marker_color=c, name=lab))
fig.update_layout(title='Effective = realized + impact (means, lag=20)',
yaxis_title='spread', showlegend=False,
margin=dict(l=20, r=20, t=60, b=20))
fig.show()