Skip to content
All library documents

Constructing Tick Imbalance Bars from Trade Prices

Article Quant Q&A · Author: boniface316

Summary

The document clarifies how tick imbalance bars are formed from transaction data. Each tick receives a direction of plus or minus one based on the change from the prior trade price; unchanged prices inherit the previous direction. The running sum of these signs is compared with a threshold based on the expected bar length and expected directional imbalance. A bar ends when the absolute cumulative imbalance reaches that threshold.

The answers emphasize that the inputs are executed trades, not separate bid and ask quote series. Expected bar length and expected imbalance are updated with exponentially weighted averages, requiring initial estimates and smoothing parameters. The discussion outlines this process and includes an implementation sketch, but it does not provide empirical evidence about predictive value or optimal parameter choices. Different answers vary in how they describe suitable price inputs, so the clearest operational guidance is to build bars from trade prices and calibrate the updates to the available trade history.

Key ideas

  • Tick imbalance bars use the direction of trade price changes, carrying the last direction forward when prices are unchanged.
  • The algorithm accumulates signed ticks until absolute imbalance reaches an expected threshold.
  • The threshold combines expected bar length with expected directional imbalance, both estimated from prior data.
  • The method is intended for executed trade data rather than separate bid and ask quote streams.
  • Initial estimates and EWMA settings are needed, and the document gives no evidence for a universally best choice.

Tags

Full text
# Tick Imbalance Bars - Advances in Financial Machine Learning


# Tick Imbalance Bars - Advances in Financial Machine Learning












I would really appreciate if any of you can clarify the following questions. I have been struggling to understand it on my own.

- $b_t=\begin{cases}b_{t-1}, & \text{if}\ \Delta p_t = 0 \\ \frac{|\Delta p_t|}{\Delta p_t} ,& \text{if} \Delta p_t \neq 0 \end{cases} $ (1)

where $p_t$ = price associated with tick t

Question 1: My tick data have both bid and ask side by side. Based on this equation, am I supposed to do bid and ask separately? i.e $b_{bid}$ and $b_{ask}$?

- $\theta_T = \sum_{t = 1}^{T}b_t$ (2)

T = tick index

$T^* = \underset{T}{Argmin} (|\theta_T| \geq E_0[T]|2P[b_t = 1] - 1)$ (3)

$E_0$ is estimated by the exponentially weighted moving average of T values from previous bars.

$2P[b_t = 1] -1$ is calculated as an exponentially weighted moving average of $b_t$ values from prior bars.

Question 2: T value for equation 2 is derived from equation 3?

Question 3: My interpretation from equation 2 and 3 is that substitute values into T, calculate $\theta_T$ until it is greater than $E_0[T]|2P[b_t = 1] - 1$. Is this interpretation correct?

I really appreciate anyone's input in this matter. Learning these on my own is tough, but with your help, I should be able to achieve it.

## Answer by Alexandr  Proskurin (score 11)

https://quant.stackexchange.com/a/44887

Question 1. Actually, the assumption of trade data format is that you have timestamp, size and price (not bid/ask) of trade. Sometimes, trades(ticks) are included to Level 1 data (also called BBO) which assumes bid and ask information. However, bars are constructed on trades, not quotes.

Question 2. Yes, T value is derived from equation 3. The process is described in details below.

The whole process of imbalance bars calculation is not straightforward. First of all, you have to set 3 parameters:

- Initial guess for expected number of ticks in imbalance bars (𝐸0[𝑇]). When you start to calculate imbalance bars, you don't have any bars at all, so you don't have any information about expected number of ticks inside of an imbalance bar. That is why you need an initial guess. This parameter doesn't significantly impact further imbalance bars, but still it is needed for the first bar calculation

- Number of bars to use for expected number of ticks in bars. When you accumulate imbalance bars you can define 𝐸0[𝑇] as EWMA of number of ticks in previous bars that is why you need to set the window for EWMA calculation.

- Number of ticks to use for expected imbalance calculation. Expected tick imbalance (2𝑃[𝑏𝑡=1]−1) can be found by calculating EWMA from tick imbalances from previous trades/ticks. We need to set the window for EWMA.

The whole algorithm description:

- Set parameters

- On each trade calculate cumulative sum of tick imbalances (𝜃𝑇)

- Start accumulating ticks until number of tick imbalances reaches the window used to expected tick imbalance calculation.

- When number of tick imbalance reaches the EWMA window size - calculate expected tick imbalance (2𝑃[𝑏𝑡=1]−1)

- Check if |𝜃𝑇| ≥ 𝐸0[𝑇] * |(2𝑃[𝑏𝑡=1]−1)| (absolute values on left and right)

- If True - it means that we have the first bar. Set 𝜃𝑇 to zero, set expected number of ticks(𝐸0[𝑇]) to EWMA of array of number of ticks in previous bars. As we have only one bar available you call EWMA with you window setting on array of generated bars, don't worry you can call EWMA with window = 3 to an array with less than 3 elements.

- If False continue, until |𝜃𝑇|≥𝐸0[𝑇]|2𝑃[𝑏𝑡=1]−1|

I am contributor to https://github.com/hudson-and-thames/mlfinlab package where you can see the implementation of imbalance bars (dollar, tick, volume) described above

## Answer by andres torres (score 2)

https://quant.stackexchange.com/a/65649

Question 1: Only tick data works for this method of bar generation, which means you actually need to provide the successful transactions. Bid and ask won't work.

Question 2: T value is generated at each bar and its value will depend on the time it takes to meet the condition in equation (3) given the tick data.

Question 3:* E[T] is calculated using the EWMA of b and the EWMA of T from prior bars. The following code should clarify this procedure:

- Keep in mind that at the start you need a guess for the EWMA of b and T, and you need to provide a parameter alpha to compute both of those EWMA.

```
import numpy as np

# Generate tick imbalanced bars id of every tick by computing: get_bars_ids(get_b(ticks))
class Tick_Imbalance():
  def __init__(self, alpha_T, alpha_imbalance, expected_imbalance, expected_ticks):
    self.T = 0
    self.bar_id = 0
    self.imbalance = 0
    self.expected_tick_imbalance = expected_imbalance * expected_ticks

    self.alpha_ticks = alpha_T
    self.alpha_imbalance = alpha_imbalance
    self.EWMA_ticks = expected_ticks
    self.EWMA_imbalance = expected_imbalance

  def __get_EWMA(self, alpha, rt, EWMA_0):
    return alpha * rt + (1 - alpha) * EWMA_0

  def __get_b(self, price_change):
    if price_change == 0: return self.last_b
    self.last_b = abs(price_change)/price_change

    return self.last_b

  def get_b(self, price_ticks: np.ndarray) -> np.ndarray:
    price_change = (price_ticks[1:] - np.roll(price_ticks, 1)[1:]) / np.roll(price_ticks, 1)[1:]
    b = [self.__get_b(x) for x in price_change]

    return np.asarray(b)

  def get_bar_ids(self, b: np.ndarray) -> np.ndarray:
    bars_ids = []    
    for _imbalance in b:
      self.T += 1
      self.imbalance += _imbalance

      self.EWMA_imbalance = self.__get_EWMA(self.alpha_imbalance, _imbalance, self.EWMA_imbalance)

      bars_ids.append(self.bar_id)

      if abs(self.imbalance) >= self.expected_tick_imbalance:
        self.EWMA_ticks = self.__get_EWMA(self.alpha_ticks, self.T, self.EWMA_ticks)
        
        self.expected_tick_imbalance = self.EWMA_ticks * abs(self.EWMA_imbalance)

        self.T = 0
        self.imbalance = 0
        self.bar_id += 1
  
    return np.asarray(bars_ids)
  
```
```

## Answer by Attack68 (score 0)

https://quant.stackexchange.com/a/44479

### Question 1

As I read it from your formula $b_t = \pm 1$, depending on whether the price has risen or fallen since the last evaluated $b_{t-1}$. If the price is unchanged the indicator rolls over from the previous timestep.

I can see two cases, either you calculate your price with actual trade data, i.e. which trades have executed between the timestep and determine a suitable model for determining $p_t$, or you determine $p_t$ based on the depth of the market, i.e. bid and offer. In either case it seems that $b_t$ is some indicator based on price. It is how you choose to model price that matters. Here is a link on that aspect definition of mid price in literature.

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.