Associate Professor of Finance (SUNY Polytechnic Institute)
Data are Market Depth Data for E-Mini S&P 500 futures (Globex) purchased directly from the CME.
In the following plots we'll take a look at the data. When looking at them it is important to note that the plots are in market vs clock time.
Kyle (1985) formally models the trading strategy of a trader with private information, who attempts to trade in a way to maximize profits from this information.
To estimate $\lambda$ we use:
$\lambda = \frac{|\Delta(price)|}{volume\ in\ \$}$rearranging this formula affords:
$|\Delta(price)| = \lambda(volume\ in\ \$)$We can thus estimate $\lambda$ via the following regression equation:
$|\Delta(price)_t| = \alpha + \lambda(volume\ in\ \$)_t + e_t$HFT serve a market making function in modern markets. This function has allowed the creation of new exchanges. HFT that serve as market makers may not have all the regulations of official market makers.
Often employ momentum trading strategies, or trade based on low latency reaction to events ( structural and latency arbitrage; order detection). They still rarely cross the spread.
Is liquidity really there? In modern markets this cannot be adequately answered even ex-post given the speed with which high-frequency traders (HFT) can remove liquidity in response to a market event.
Trade criteria:
We calculate the change in liquidity in the 100 ms after each trade, and regress this on 3 measures of market activity pre-trade. The three pre-trades measures are:
Hasbrouck (2016) (High-Frequency Quoting) used variance ratio tests to find the presence of algorithmic trading. The method was ex-post.
If we can identify periods with particularly volatile liquidity we can create trading mechanisms whereby slower traders liquidity taking orders are canceled/delayed until liquidity is less volatile.
High-latency (retail) would not notice the delay. It would save each retail trader a fraction of a cent on each share, but across all retail trades this would be considerable savings.
Because of the low-latency nature of the data, these are necessarily automated rules (estimate liquidity volatility over the next few milliseconds and potentially delay given the results).
"Now that we have a basic version of a crumbling quote signal to work with,we can consider how to deploy it on our market. Historically, we have embedded it inside our discretionary peg (dpeg) order. This is a dark ordertype that rests on the book at the near side, but can exercise “discretion”to trade at the midpoint of the NBBO when the crumbling quote signal isnot on. In this way, discretionary peg orders behave less aggressively whilethe signal is on, seeking to avoid bad trades at the midpoint just before the NBBO moves in their favor."...
"Just this month, IEX gained approval from the SEC to release a new version of our primary peg order type which will also incorporate the signal.This order type will rest one tick outside the NBBO and exercise discretionto trade at the NBBO while the signal is off."
I attempt to identify the presence of algorithms by including thier presence as a latent variable in a Markov-Switching regression---an unsupervised learning approach
I measure liquidity on each side of the book as the amount of ES that can be bought within one point of the present bid-offer midpoint.
The model is estimated via the Hamilton Filter.
double lik(NumericVector theta, NumericVector lnoil_, NumericVector lnng_, NumericVector change_bam_) {
arma::colvec lnoil = lnoil_;
arma::colvec lnng = lnng_;
arma::colvec change_bam = change_bam_;
double alpha1 = theta[0];
double alpha2 = theta[1];
double alpha3 = theta[2];
double alpha4 = theta[3];
double alpha5 = theta[4];
double alpha6 = theta[5];
double p11 = 1 / (1 + exp(-1*theta[6]));
double p22 = 1 / (1 + exp(-1*theta[7]));
double alpha7 = theta[8];
double alpha8 = theta[9];
arma::mat dist_1 = (1 / (alpha5 * sqrt(2 * PII)))*exp((-pow((lnng - alpha1 - alpha3*lnoil - alpha7 * change_bam), 2))/(2*pow(alpha5,2)));
arma::mat dist_2 = (1 / (alpha6 * sqrt(2 * PII)))*exp((-pow((lnng - alpha2 - alpha4*lnoil - alpha8 * change_bam), 2))/(2*pow(alpha6,2)));
arma::mat dist = arma::join_rows(dist_1, dist_2);
arma::colvec o;
o << 1 << 1;
arma::mat P;
P << p11 << 1 - p22 << arma::endr
<< 1 - p11 << p22 << arma::endr;
int length_lnoil = lnoil.n_elem;
arma::mat xi_a(length_lnoil, 2);
arma::mat xi_b(length_lnoil, 2);
arma::vec model_lik(length_lnoil, 1);
// replace to use armadillo's elementwise multiplication operator % as in mat c = v % b;
arma::rowvec first_xi_a_numerator;
first_xi_a_numerator << p11 * dist.row(0)[0] << p22 * dist.row(0)[2];
double first_xi_a_denominator = p11 * dist.row(0)[0] + p22 * dist.row(0)[1];
xi_a.row(0)[0] = first_xi_a_numerator[0] / first_xi_a_denominator;
xi_a.row(0)[1] = first_xi_a_numerator[1] / first_xi_a_denominator;
for (int i = 1; i < length_lnoil; i++){
xi_b.row(i) = (P * xi_a.row(i - 1).t()).t();
xi_a.row(i) = ((xi_b.row(i) % dist.row(i)) / (xi_b.row(i)[0] * dist.row(i)[0] + xi_b.row(i)[1] * dist.row(i)[1]));
model_lik.at(i) = (xi_b.row(i)[0] * dist.row(i)[0] + xi_b.row(i)[1] * dist.row(i)[1]);
}
double logl = arma::accu(log(model_lik.subvec(1, length_lnoil - 1)));
return -1 * logl;
}
We can use a prediction error above a particular threshold as our algo indicator.
### lets look at the correlation between signals------
pred_error_signal <- 1 * (abs(pred_error) > .1)
state_prob_signal <- 1 * ((1 - state_prob) > .5)
cor.test(pred_error_signal, state_prob_signal)
## Pearson's product-moment correlation
## data: pred_error_signal and state_prob_signal
## t = 110.56, df = 99999, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.3245093 0.3355549
## sample estimates:
## cor
## 0.3300434
Assuming a 20 milllisecond firing window, our signal wil be