financialkit.market_microstructure#
Demsetz’s quoted, effective and realized spreads and the price impact;
the Roll and Corwin-Schultz spread estimators; Lee-Ready trade
classification with the tick test, the quote rule and lagged quotes;
Garman’s Poisson dealer, Ho-Stoll inventory quotes and
Avellaneda-Stoikov market making, simulated around a Brownian mid price
from financialkit.integrators.brownian_increments(); Kyle’s
insider and the Glosten-Milgrom dealer; Hasbrouck’s trade-impact VAR;
PIN by maximum likelihood and VPIN by volume buckets; the square-root
impact law, Bertsimas-Lo dynamic programming and Almgren-Chriss
efficient execution; Amihud illiquidity and Kyle’s lambda by
regression.
financialkit.market_microstructure: spreads, dealers, information, trade impact and execution.
Demsetz’s quoted, effective and realized spreads, and the Roll and
Corwin-Schultz estimators that need no quotes; Lee-Ready trade
classification; Garman’s Poisson dealer, Ho-Stoll inventory quotes and
Avellaneda-Stoikov market making (simulated around a Brownian mid from
financialkit.integrators); Kyle’s insider and Glosten-Milgrom’s
dealer; Hasbrouck’s trade-impact VAR; PIN by maximum likelihood and
VPIN by volume buckets; the square-root impact law, Bertsimas-Lo and
Almgren-Chriss optimal execution; Amihud illiquidity and Kyle’s lambda
by regression. Trade signs are +1 for buys and -1 for sells.
- class financialkit.market_microstructure.AvellanedaStoikov(risk_aversion, sigma, k, T)[source]#
Bases:
QuotingStrategyAvellaneda-Stoikov’s inventory strategy: the optimal spread around the reservation price.
- Parameters:
- class financialkit.market_microstructure.BertsimasLoResult(delta_w, delta_x, a, b, c, d, trades, expected_cost)[source]#
Bases:
objectBertsimas and Lo’s (1998) dynamic-programming execution policy.
Before period
k(0-based) with \(W_k\) shares left and last signal \(X_{k-1}\), the optimal order is \(S_k = \delta_{w,k} W_k + \delta_{x,k} X_{k-1}\), and the expected remaining cost is \(P_{k-1} W_k + a_k W_k^2 + b_k X_{k-1} W_k + c_k X_{k-1}^2 + d_k\).- Parameters:
- class financialkit.market_microstructure.ExecutionResult(times, holdings, trades, expected_cost, variance)[source]#
Bases:
objectAn execution schedule for selling (or buying) a block of shares.
- Parameters:
- class financialkit.market_microstructure.GarmanResult(times, stock, cash, failed, failure_time)[source]#
Bases:
objectGarman’s (1976) dealer under Poisson order flow, simulated.
- class financialkit.market_microstructure.GlostenMilgromResult(bid, ask, belief, trades, informed, v_low, v_high, true_value)[source]#
Bases:
objectA simulated sequence of Glosten-Milgrom trades and quotes.
- Parameters:
- ask: ndarray#
Ask quoted before each trade, \(E[V \mid \text{history}, \text{buy}]\).
- Type:
ndarray, shape (n,)
- belief: ndarray#
Dealer’s probability that the value is high, before and after each trade.
- Type:
ndarray, shape (n + 1,)
- class financialkit.market_microstructure.KyleResult(lam, beta, insider_profit, posterior_variance, sigma_v, sigma_u, p0)[source]#
Bases:
objectKyle’s (1985) single-auction linear equilibrium.
- Parameters:
- insider_profit: float#
Insider’s expected profit \(\sigma_v \sigma_u / 2\), equal to the noise traders’ expected loss.
- lam: float#
price change per unit of order flow.
- Type:
Price impact \(\lambda = \sigma_v / (2\sigma_u)\)
- class financialkit.market_microstructure.MarketMakingResult(times, mid, bid, ask, inventory, cash)[source]#
Bases:
objectA simulated market maker quoting around a Brownian mid price.
- Parameters:
- class financialkit.market_microstructure.PINResult(alpha, delta, mu, eps_b, eps_s, pin, pin_se, loglik)[source]#
Bases:
objectEasley-Kiefer-O’Hara-Paperman model fitted by maximum likelihood.
- Parameters:
- class financialkit.market_microstructure.QuotingStrategy[source]#
Bases:
ABCA market maker’s rule for its bid and ask.
- class financialkit.market_microstructure.SymmetricQuotes(half_spread)[source]#
Bases:
QuotingStrategyQuotes a fixed half-spread either side of the mid, ignoring inventory.
- Parameters:
half_spread (float or callable) – A number, or
f(t)returning one.
- class financialkit.market_microstructure.TradeImpactResult(coef_r, coef_x, impulse, permanent_impact, trade_share, innovation_cov)[source]#
Bases:
objectHasbrouck’s (1991) vector autoregression of quote revisions and trades.
- Parameters:
- coef_r: ndarray#
Return equation, columns
[x_t, r_{t-1..t-p}, x_{t-1..t-p}](no intercept).- Type:
ndarray, shape (1 + 2 * lags,)
- coef_x: ndarray#
Trade equation, columns
[r_{t-1..t-p}, x_{t-1..t-p}].- Type:
ndarray, shape (2 * lags,)
- impulse: ndarray#
Cumulative quote revision after a unit trade innovation.
- Type:
ndarray, shape (horizon + 1,)
- innovation_cov: ndarray#
Covariance of the return and trade innovations.
- Type:
ndarray, shape (2, 2)
- permanent_impact: float#
Long-run price impact of a unit trade innovation, the last entry of
impulse.
Fraction of the efficient price’s variance explained by trades, Hasbrouck’s \(R^2_w\).
- class financialkit.market_microstructure.VPINResult(vpin, buy_volume, sell_volume, bucket_end)[source]#
Bases:
objectVolume-synchronized probability of informed trading.
- financialkit.market_microstructure.align_quotes(trade_times, quote_times, bid, ask, delay=0.0)[source]#
The quotes in force delay time units before each trade.
Lee and Ready (1991) compared each trade with the quote standing five seconds earlier, because quote updates triggered by a trade were often time-stamped before it.
- Parameters:
- Return type:
- Returns:
bid, ask (ndarray, shape (n,)) –
nanwhere no quote had yet been posted.
Examples
>>> b, a = align_quotes([3.0, 7.0], [0.0, 5.0], [10.0, 11.0], [10.2, 11.2], delay=2.5) >>> b.tolist(), a.tolist() ([10.0, 10.0], [10.2, 10.2])
- financialkit.market_microstructure.almgren_chriss(X, T, n_steps, sigma, eta, risk_aversion, gamma=0.0, epsilon=0.0)[source]#
Almgren-Chriss efficient liquidation of X shares over [0, T].
Minimising \(E + \lambda V\) gives
\[x_j = X\,\frac{\sinh(\kappa (T - t_j))}{\sinh(\kappa T)}, \qquad \cosh(\kappa\tau) = 1 + \frac{\lambda\sigma^2\tau^2}{2\tilde\eta},\]so \(1/\kappa\) is the half-life of the trade: a risk-neutral trader (\(\lambda = 0\)) sells evenly, and a very risk-averse one sells almost everything at once.
- Parameters:
X (
float) – Shares to sell.T (
float) – Horizon.n_steps (
int) – Number of trading intervals \(N\).sigma (
float) – Price volatility per unit time (price units).eta (
float) – Temporary impact per unit of trading rate.risk_aversion (
float) – \(\lambda \ge 0\).gamma (
float) – Permanent impact and fixed cost per share.epsilon (
float) – Permanent impact and fixed cost per share.
- Return type:
- Returns:
ExecutionResult
Examples
>>> almgren_chriss(10.0, 1.0, 5, sigma=0.3, eta=0.05, risk_aversion=0.0).holdings.round(6).tolist() [10.0, 8.0, 6.0, 4.0, 2.0, 0.0]
- financialkit.market_microstructure.amihud_illiquidity(returns, dollar_volume, scale=1000000.0)[source]#
Amihud’s ratio \(\frac{1}{D}\sum_d |r_d| / \mathrm{DVol}_d\), over days with trading.
- Parameters:
- Return type:
- Returns:
float
Examples
>>> amihud_illiquidity([0.01, -0.02, 0.0], [2e6, 4e6, 0.0]) 0.005
- financialkit.market_microstructure.avellaneda_stoikov_spread(risk_aversion, sigma, time_left, k)[source]#
Optimal total spread \(\gamma\sigma^2 (T - t) + \frac{2}{\gamma}\ln(1 + \gamma / k)\).
As \(\gamma \to 0\) it tends to \(2/k\), the spread that maximises expected profit from fills at rate \(A e^{-k\delta}\).
- Return type:
- Parameters:
Examples
>>> round(float(avellaneda_stoikov_spread(0.1, 2.0, 1.0, 1.5)), 4) 1.6908
- financialkit.market_microstructure.bertsimas_lo(shares, n_periods, theta, gamma=0.0, rho=0.0, sigma_eta=0.0, x0=0.0, signals=None, p0=0.0)[source]#
Bertsimas and Lo’s optimal schedule for buying shares over n_periods.
The execution price follows \(P_k = P_{k-1} + \theta S_k + \gamma X_k + \varepsilon_k\) with a serially correlated signal \(X_k = \rho X_{k-1} + \eta_k\), and the trader minimises \(E[\sum_k P_k S_k]\) subject to \(\sum_k S_k = \bar S\). The value function is quadratic, and backward induction gives
\[\delta_{w,k} = 1 - \frac{\theta}{2a_{k+1}}, \quad \delta_{x,k} = \frac{\rho b_{k+1}}{2a_{k+1}}, \quad a_k = \theta - \frac{\theta^2}{4a_{k+1}}, \quad b_k = \rho\left(\gamma + \frac{\theta b_{k+1}}{2a_{k+1}}\right),\]from \(a = \theta\), \(b = \gamma\rho\) in the last period. With \(\gamma = 0\) the policy is \(S_k = W_k / (T - k)\), an even split, and the expected cost is \(P_0\bar S + \theta \bar S^2 (T + 1) / (2T)\).
- Parameters:
shares (
float) – \(\bar S\).n_periods (
int) – \(T\).theta (
float) – Permanent impact per share.gamma (
float) – Signal loading, persistence and innovation volatility.rho (
float) – Signal loading, persistence and innovation volatility.sigma_eta (
float) – Signal loading, persistence and innovation volatility.x0 (
float) – Signal observed before the first trade, \(X_{-1}\).signals (
ArrayLike|None) – Realised \(X_{k-1}\) before each trade; the expected path \(\rho^k x_0\) if omitted.p0 (
float) – Price before trading.
- Return type:
- Returns:
BertsimasLoResult
Examples
>>> res = bertsimas_lo(1000.0, 4, theta=1e-4) >>> res.trades.round(9).tolist(), round(res.expected_cost, 6) ([250.0, 250.0, 250.0, 250.0], 62.5)
- financialkit.market_microstructure.bulk_volume_classification(price_changes, volumes, sigma=None)[source]#
Buy volume of each bar by bulk volume classification, \(V \Phi(\Delta P / \sigma_{\Delta P})\).
- Parameters:
- Return type:
- Returns:
ndarray, shape (n,)
Examples
>>> bulk_volume_classification([0.0, 1.0], [100.0, 100.0], sigma=1.0).round(2).tolist() [50.0, 84.13]
- financialkit.market_microstructure.corwin_schultz_spread(high, low, clip=True)[source]#
Corwin-Schultz relative spread from each pair of consecutive days’ highs and lows.
The variance in a day’s high-low range grows with the horizon but the spread does not, so comparing one two-day range with two one-day ranges separates them:
\[\alpha = \frac{\sqrt{2\beta} - \sqrt\beta}{3 - 2\sqrt2} - \sqrt{\frac{\gamma}{3 - 2\sqrt2}}, \qquad S = \frac{2(e^\alpha - 1)}{1 + e^\alpha},\]with \(\beta\) the sum of the two squared daily log ranges and \(\gamma\) the squared two-day log range.
- Parameters:
- Return type:
- Returns:
ndarray, shape (n - 1,) – Average over a month for a monthly estimate.
Examples
>>> corwin_schultz_spread([101.0, 101.2], [99.0, 99.1]).round(4).tolist() [0.0169]
- financialkit.market_microstructure.effective_spread(price, bid, ask, side, relative=False)[source]#
Effective spread \(2 q (p - m)\): twice the premium paid over the midquote.
- Parameters:
- Return type:
- Returns:
ndarray, shape (n,)
Examples
A buy inside the quotes pays less than the quoted spread.
>>> effective_spread([100.03], [99.95], [100.05], [1]).round(6).tolist() [0.06]
- financialkit.market_microstructure.execution_cost(holdings, T, sigma, eta, gamma=0.0, epsilon=0.0)[source]#
Expected shortfall and variance of any schedule in the Almgren-Chriss model.
\[E = \tfrac12\gamma X^2 + \varepsilon\sum|n_k| + \frac{\tilde\eta}{\tau}\sum n_k^2, \qquad V = \sigma^2\tau\sum_{k=1}^N x_k^2, \qquad \tilde\eta = \eta - \tfrac12\gamma\tau.\]- Parameters:
holdings (
ArrayLike) – \(x_0 = X, \dots, x_N = 0\) on an even grid over[0, T].T (
float) – Horizon, price volatility, temporary and permanent impact, and the fixed half-spread cost.sigma (
float) – Horizon, price volatility, temporary and permanent impact, and the fixed half-spread cost.eta (
float) – Horizon, price volatility, temporary and permanent impact, and the fixed half-spread cost.gamma (
float) – Horizon, price volatility, temporary and permanent impact, and the fixed half-spread cost.epsilon (
float) – Horizon, price volatility, temporary and permanent impact, and the fixed half-spread cost.
- Return type:
- Returns:
expected_cost, variance (float)
Examples
>>> execution_cost([10.0, 5.0, 0.0], T=2.0, sigma=1.0, eta=0.1) (5.0, 25.0)
- financialkit.market_microstructure.fit_impact_law(participation, impact)[source]#
Fit \(I = Y q^\delta\) by least squares on logs.
- Parameters:
- Return type:
- Returns:
OLSResult –
coef = [log Y, delta]; the square-root law saysdelta = 0.5.
Examples
>>> q = [0.001, 0.01, 0.1] >>> fit_impact_law(q, square_root_impact(q, 1.0, 1.0, Y=0.7)).coef.round(6).tolist() [-0.356675, 0.5]
- financialkit.market_microstructure.fit_pin(buys, sells)[source]#
Fit the EKOP model by maximum likelihood (
scipy.optimize.minimize()).The probabilities are optimised on the logit scale and the rates on the log scale, from a small grid of starting points as Yan and Zhang (2012) recommend, because the likelihood has local maxima.
- financialkit.market_microstructure.garman_ruin_probability(inventory, buy_rate, sell_rate)[source]#
Probability that Garman’s dealer eventually runs out of stock.
Customers buy (the dealer sells one share) at rate buy_rate and sell at rate sell_rate, so the inventory is a gambler’s-ruin random walk:
\[P(\text{ruin} \mid I_0) = \min\left(1, \left(\lambda_a / \lambda_b\right)^{I_0}\right).\]- Parameters:
- Return type:
- Returns:
ndarray
Examples
>>> garman_ruin_probability([0, 3, 10], 2.0, 3.0).round(4).tolist() [1.0, 0.2963, 0.0173] >>> float(garman_ruin_probability(50, 1.0, 1.0)) 1.0
- financialkit.market_microstructure.glosten_milgrom_quotes(belief, alpha, v_low, v_high, eta=0.5)[source]#
Zero-profit bid and ask when a fraction alpha of traders know the value.
The value is \(V_H\) with probability \(\theta\) (the belief) and \(V_L\) otherwise. An informed trader buys when it is high and sells when it is low; an uninformed one buys with probability \(\eta\). Then
\[a = E[V \mid \text{buy}] = V_L + (V_H - V_L)\, \frac{\theta(\alpha + (1-\alpha)\eta)}{\theta\alpha + (1-\alpha)\eta},\]and the bid is the same with a sell.
- Parameters:
- Return type:
- Returns:
bid, ask (ndarray)
Examples
>>> b, a = glosten_milgrom_quotes(0.5, 0.2, 100.0, 110.0) >>> float(b), float(a) (104.0, 106.0)
- financialkit.market_microstructure.hasbrouck_var(returns, trades, lags=5, horizon=20)[source]#
Fit Hasbrouck’s trade-impact VAR and its cumulative impulse response.
\[\begin{split}r_t &= \sum_{i=1}^p a_i r_{t-i} + \sum_{i=0}^p b_i x_{t-i} + v_{1,t} \\ x_t &= \sum_{i=1}^p c_i r_{t-i} + \sum_{i=1}^p d_i x_{t-i} + v_{2,t}\end{split}\]Each equation is fitted by least squares (
financialkit.time_series.utils.ols()) after demeaning.- Parameters:
- Return type:
- Returns:
TradeImpactResult
- financialkit.market_microstructure.ho_stoll_quotes(value, inventory, alpha, beta, risk_aversion, sigma, tau=1.0)[source]#
Optimal bid and ask of a risk-averse dealer, a one-period Ho-Stoll model.
Orders arrive at \(\lambda = \alpha - \beta\delta\) on each side, \(\delta\) being the distance of the quote from the true value \(p\). The dealer maximises expected trading profit minus \(\tfrac{\gamma}{2}\sigma^2\tau\) times the squared end-of-period inventory. The first-order conditions give Ho and Stoll’s two results:
\[\delta_a + \delta_b = \frac{\alpha}{\beta}, \qquad \frac{a + b}{2} = p - \frac{\kappa I}{2(1 + \kappa\beta)}, \quad \kappa = \gamma\sigma^2\tau:\]the spread does not depend on inventory, and the quotes slide down when the dealer is long.
- Parameters:
value (
ArrayLike) – True value \(p\).inventory (
ArrayLike) – Dealer’s inventory \(I\).alpha (
float) – Intercept and slope of the order-arrival rate.beta (
float) – Intercept and slope of the order-arrival rate.risk_aversion (
float) – \(\gamma \ge 0\).sigma (
float) – Volatility of the value, per unit time.tau (
float) – Holding horizon.
- Return type:
- Returns:
bid, ask (ndarray)
Examples
>>> b, a = ho_stoll_quotes(100.0, [-10, 0, 10], alpha=10.0, beta=20.0, risk_aversion=0.1, sigma=0.2) >>> (a - b).round(6).tolist(), ((a + b) / 2).round(4).tolist() ([0.5, 0.5, 0.5], [100.0185, 100.0, 99.9815])
- financialkit.market_microstructure.kyle_equilibrium(sigma_v, sigma_u, p0=0.0)[source]#
Kyle’s single-auction equilibrium \(\lambda = \sigma_v / (2\sigma_u)\), \(\beta = \sigma_u / \sigma_v\).
The value is \(v \sim N(p_0, \sigma_v^2)\), noise flow \(u \sim N(0, \sigma_u^2)\), the insider submits \(x = \beta(v - p_0)\) and the market maker sets \(p = p_0 + \lambda(x + u)\).
- Parameters:
- Return type:
- Returns:
KyleResult
Examples
Doubling the noise halves the price impact and doubles the insider’s profit.
>>> [(r.lam, r.insider_profit) for r in (kyle_equilibrium(2.0, 1.0), kyle_equilibrium(2.0, 2.0))] [(1.0, 1.0), (0.5, 2.0)]
- financialkit.market_microstructure.kyle_lambda(price_changes, signed_volume)[source]#
Regress price changes on signed order flow, \(\Delta p = c + \lambda y + e\).
- Return type:
- Returns:
OLSResult –
coef = [c, lambda]with standard errors.- Parameters:
price_changes (ArrayLike)
signed_volume (ArrayLike)
Examples
>>> kyle_lambda([0.3, 0.0, 0.5], [2.0, -1.0, 4.0]).coef.round(10).tolist() [0.1, 0.1]
- financialkit.market_microstructure.lee_ready(prices, bid, ask)[source]#
Lee-Ready classification: the quote rule, with the tick test at the midquote.
- Parameters:
- Return type:
- Returns:
ndarray, shape (n,) –
+1buy,-1sell,0if neither rule decides.
Examples
>>> lee_ready([10.05, 10.00, 10.00, 9.95], [9.95] * 4, [10.05] * 4).tolist() [1.0, -1.0, -1.0, -1.0]
- financialkit.market_microstructure.midquote(bid, ask)[source]#
The quote midpoint \((b + a) / 2\), checking the quotes are not crossed.
- Return type:
- Parameters:
bid (ArrayLike)
ask (ArrayLike)
Examples
>>> midquote([99.9, 100.0], [100.1, 100.4]).tolist() [100.0, 100.2]
- financialkit.market_microstructure.pin_loglik(params, buys, sells)[source]#
Log-likelihood of daily buy and sell counts under the EKOP mixture.
- financialkit.market_microstructure.price_impact(bid, ask, later_mid, side)[source]#
Price impact \(2 q (m_{t+\Delta} - m_t)\), so effective = realized + impact.
- Return type:
- Parameters:
bid (ArrayLike)
ask (ArrayLike)
later_mid (ArrayLike)
side (ArrayLike)
Examples
>>> p, b, a, later, q = [100.05], [99.95], [100.05], [100.02], [1] >>> float(effective_spread(p, b, a, q)[0] - realized_spread(p, later, q)[0] - price_impact(b, a, later, q)[0]) == 0.0 True
- financialkit.market_microstructure.quote_rule(prices, bid, ask)[source]#
Quote rule:
+1above the midquote,-1below,0at it.- Return type:
- Parameters:
prices (ArrayLike)
bid (ArrayLike)
ask (ArrayLike)
Examples
>>> quote_rule([10.05, 10.00, 9.96], [9.95, 9.95, 9.95], [10.05, 10.05, 10.05]).tolist() [1.0, 0.0, -1.0]
- financialkit.market_microstructure.quoted_spread(bid, ask, relative=False)[source]#
Quoted spread \(a - b\), or \((a - b) / m\) if relative.
Examples
>>> quoted_spread([99.95], [100.05], relative=True).round(6).tolist() [0.001]
- financialkit.market_microstructure.realized_spread(price, later_mid, side)[source]#
Realized spread \(2 q (p - m_{t+\Delta})\): what the liquidity provider keeps.
- financialkit.market_microstructure.reservation_price(mid, inventory, risk_aversion, sigma, time_left)[source]#
Avellaneda-Stoikov indifference price \(r = s - q\gamma\sigma^2 (T - t)\).
- Return type:
- Parameters:
Examples
>>> reservation_price(100.0, [-2, 0, 2], 0.1, 2.0, 0.5).tolist() [100.4, 100.0, 99.6]
- financialkit.market_microstructure.roll_spread(prices)[source]#
Roll’s estimator \(s = 2\sqrt{-\operatorname{cov}(\Delta p_t, \Delta p_{t-1})}\).
If trades alternate at random between bid and ask around an efficient price, the bounce makes the first-order autocovariance of price changes \(-s^2/4\).
- Parameters:
prices (
ArrayLike) – Transaction prices (or log prices, giving a relative spread).- Return type:
- Returns:
float –
nanwhen the autocovariance is positive, which happens in practice and which the model cannot explain.
Examples
Bounce of 0.1 either side of a constant value:
>>> import numpy as np >>> p = 100.0 + 0.1 * np.random.default_rng(0).choice([-1.0, 1.0], 100_000) >>> round(roll_spread(p), 2) 0.2
- financialkit.market_microstructure.simulate_garman(stock, cash, ask, bid, buy_rate, sell_rate, n_events, n_paths=1, rng=None)[source]#
Simulate Garman’s dealer event by event until stock or cash runs out.
A buy order (rate \(\lambda_a\)) takes one share at the ask; a sell order (rate \(\lambda_b\)) delivers one at the bid. The dealer fails when the stock is zero or the cash cannot pay the bid. Both inventories drift upward only if \(\lambda_b > \lambda_a\) and \(a\lambda_a > b\lambda_b\), which needs \(a > b\): a spread.
- Parameters:
stock (
int) – Starting shares.cash (
float) – Starting cash;np.infisolates the stock inventory.ask (
float) – Fixed quotes.bid (
float) – Fixed quotes.buy_rate (
float) – \(\lambda_a(a)\) and \(\lambda_b(b)\) at those quotes.sell_rate (
float) – \(\lambda_a(a)\) and \(\lambda_b(b)\) at those quotes.n_events (
int) – Orders simulated per path.n_paths (
int)
- Return type:
- Returns:
GarmanResult – Paths are frozen after failure.
- financialkit.market_microstructure.simulate_glosten_milgrom(n_trades, alpha, v_low, v_high, belief0=0.5, eta=0.5, true_value=None, rng=None)[source]#
A sequence of Glosten-Milgrom trades with Bayesian quote updates.
- Parameters:
n_trades (
int)alpha (
float) – As inglosten_milgrom_quotes().v_low (
float) – As inglosten_milgrom_quotes().v_high (
float) – As inglosten_milgrom_quotes().eta (
float) – As inglosten_milgrom_quotes().belief0 (
float) – Prior probability of the high value.true_value (
float|None) –v_loworv_high; drawn from the prior if omitted.
- Return type:
- Returns:
GlostenMilgromResult – After a buy the belief becomes the one that priced the ask, and after a sell the one that priced the bid.
- financialkit.market_microstructure.simulate_kyle(eq, n_auctions, beta=None, rng=None)[source]#
Draw independent single-period Kyle markets.
- Parameters:
- Return type:
- Returns:
value, order_flow, price (ndarray, shape (n_auctions,)) – \(v\), total flow \(x + u\) and the clearing price.
- financialkit.market_microstructure.simulate_market_making(strategy, s0, sigma, T, n_steps, A, k, n_paths=1, rng=None)[source]#
Simulate a market maker as in Avellaneda and Stoikov’s Section 4.
The mid price is arithmetic Brownian motion (increments from
financialkit.integrators.brownian_increments()). In each step of length \(dt\) the ask is lifted with probability \(A e^{-k\delta_a} dt\) and the bid hit with probability \(A e^{-k\delta_b} dt\), one share each.- Parameters:
- Return type:
- Returns:
MarketMakingResult
- financialkit.market_microstructure.simulate_pin(n_days, alpha, delta, mu, eps_b, eps_s, rng=None)[source]#
Daily buy and sell counts from the EKOP model.
- financialkit.market_microstructure.square_root_impact(quantity, daily_volume, sigma, Y=1.0)[source]#
Square-root law \(I = Y \sigma \sqrt{Q / V}\) for the impact of a metaorder.
- Parameters:
- Return type:
- Returns:
ndarray
Examples
Trading 1% of daily volume in a 2%-volatility stock costs about 20 bp.
>>> float(square_root_impact(1e4, 1e6, 0.02)) 0.002
- financialkit.market_microstructure.tick_test(prices)[source]#
Tick test:
+1on an uptick or zero-uptick,-1on a downtick or zero-downtick.- Return type:
- Returns:
ndarray, shape (n,) –
0until the price first changes.- Parameters:
prices (ArrayLike)
Examples
>>> tick_test([10.0, 10.0, 10.1, 10.1, 10.0, 10.0]).tolist() [0.0, 0.0, 1.0, 1.0, -1.0, -1.0]
- financialkit.market_microstructure.trade_signs(side)[source]#
Validate trade signs: every entry must be
+1(buy) or-1(sell).- Return type:
- Parameters:
side (ArrayLike)
Examples
>>> trade_signs([1, -1, 1]).tolist() [1.0, -1.0, 1.0]
- financialkit.market_microstructure.vpin(price_changes, volumes, bucket_volume, window=50, sigma=None)[source]#
Volume-synchronized probability of informed trading.
Bars are classified by
bulk_volume_classification(), their volume is poured into consecutive buckets of size bucket_volume (a bar may straddle buckets), and VPIN is the mean of \(|V^B_\tau - V^S_\tau| / V\) over the last window buckets.- Parameters:
- Return type:
- Returns:
VPINResult