napiod gives a python implementation of the measurement of price impact in order-driven markets introduced in Bellani et al. (2021).
This measurement of price impact quantifies the extent to which price movements are caused by a labelled agent in the market, either by her own market orders (direct impact) or by other market participants reacting to her actions (indirect impact).
In other words, napiod measures the Granger causality between the market orders of a labelled agent and the movements of the mid-price.
The price impact is scenario-specific and depends both on the agent's behaviour and on the market environment.
The measurement of price impact is based on a model that utilises state-dependet Hawkes processes introduced in
Morariu-Patrichi and Pakkanen (2017) and Morariu-Patrichi and Pakkanen (2018), and so napiod depends on mpoints.
The model
We consider five streams of random times:
the stream
$T^{0}_1, T^{0}_2, \dots$
of times when our labelled agent submits market orders;
the stream
$T^{1}_1, T^{1}_2, \dots$
of times when limit orders are executed on the bid side
(equivalently identified with the arrival times of sell market orders);
the stream $T^{2}_1, T^{2}_2, \dots$
of times when limit orders are executed on the ask side
(equivalently identified with arrival times of buy market orders);
the stream
$T^{3}_1, T^{3}_2, \dots$
of times when
either an ask limit order is inserted inside the spread,
or the cancellation of a bid limit order depletes the liquidity available at the first bid level;
the stream
$T^{4}_1, T^{4}_2, \dots$
of times when
either a bid limit order is inserted inside the spread,
or the cancellation of an ask limit order depletes the liquidity available at the first ask level.
The five sequences of random times give rise to a five-dimensional counting process
$N=(N_0, N_1, N_2, N_3, N_4)$
with the following interpretation of its components:
$N_0(t)$ denotes the number of market orders that our labelled agent has submitted before or at time $t$;
$N_1(t)$ denotes the number of seller-initiated trades that happened before or at time $t$
(identified with the number of market orders arrived on the bid side of the order book by time $t$);
$N_2(t)$
denotes the number of buyer-initiated trades that happened before or at time $t$
(identified with the number of market orders arrived on the ask side of the order book by time $t$);
$N_3(t)$ denotes the number of decreases in the mid-price
caused by a limit order insertion or cancellation that happened before or at time $t$;
$N_4(t)$ denotes the number of increases in the mid-price
caused by a limit order insertion or cancellation that happened before or at time $t$
The counting process $N$ is paired with the state variable $X = (X_1, X_2)$.
At time $t$, the state variable $X(t)$ summarises the configuration
of the limit order book at time $t$,
by recording
the variation of the mid-price compared to time $t-$
and
a proxy for the volume imbalance.
More precisely,
$X_1(t) = -1$ if the latest event in the order book has decreased the mid-price;
$X_1(t) = 0$ if the latest event in the order book has left the mid-price unchanged;
$X_1(t) = +1$ if the latest event in the order book has increased the mid-price.
$X_2(t) = -1$ if the volumes imbalance at time $t$ is -33% or more negative;
$X_2(t) = 0$ if the volumes imbalance at time $t$ is between -33% and +33%;
$X_2(t) = +1$ if the volumes imbalance at time $t$ is +33% or more positive;
The pair $(N, X)$ is modelled as a state-dependent Hawkes process.
Each agent's market order $T^{0}_j$ has two effects.
On the one hand, at every $T^{0}_j$ the state variable $X$ is updated, and the mid-price decreases if $X_1(T^{0}_j) = -1$ or it increases if $X_1(T^{0}_j) = +1$.
On the other hand, every $T^{0}_j$ alters the intensity of occurrence of the random times $T^{1}$, $T^2$, $T^3$, $T^4$,
and these in turn will produce updates of the state process $X$.
A quantification of the first effect produces our measurement of direct price impact,
and a quantification of the second effect produces our measurement of indirect price impact.
Direct price impact is non-negative and non-decreasing, and the larger it is the more unfavourably the mid-price moves against the agent.
Indirect impact, instead, can be positive or negative:
it is positive when market participants react to the agent and move the mid-price in a way unfavourable to the agent;
it is negative when market participants react to the agent and move the mid-price in a way favourable to the agent.
For more detail into the model and the measurement of price impact, please consult Bellani et al. (2021).
Installation
pip install napiod
Build from source
Build the wheel using setuptools.
pip install -q build
python -m build
Install in development mode
If you are contributing to napiod, you might want to install it in development mode.
See development-mode
Currently, the method compute_price_impact_profile of the class PriceImpact assumes that the liquidation starts at zero. This entails that the starting sigma algebra $\mathfrak{F} _ 0$ is trivial.
However, the mathematics on which napiod is based does not require this, and price impact profiles can be computed from a point in time $t _ 0$ where the sigma algebra $\mathfrak{F} _ {t_0}$ is non-trivial. In other words, the formulae are capable of accounting for the fact that the limit order book has a history before our labelled agent executes her orders. Moreover, thanks to the use of exponential kernels, accounting for events preceding the agent's actions is not computationally more expensive; mpoints already implements simulation of state-dependent Hawkes processes from a positive start time $t _ 0$.
I would like to extend the method compute_price_impact_profile so that price impact profiles of the agent can be computed starting from a positive time. The method could mirror HybridHawkesExp.simulate and assumes that initial_partial_sums are provided by the user too.
The proposed extension would make interesting analysis possible. For example. one could study how the order flow before the agent interventions is reflected on her own market impact, and cause the price to move more or less unfavourably while she execute her trade. This analysis would be carried out with fixed model parameters, and it would be scenario-specific, making the most out of the scenario-specific measurement of price impact that motivated Bellani et al. (2021).
Currently, the scripts in examples/ demonstrate how to compute price impact profiles starting from simulated data.
It would be great to add a demonstration based on real-world data.
A suggestion would be to use one of the sample files from Lobster. This would require to map event definitions in Lobster to the components of our model.