OPEN-SOURCE SCRIPT

Order Flow Hawkes Process [ScorsoneEnterprises]

442
This indicator is an implementation of the Hawkes Process. This tool is designed to show the excitability of the different sides of volume, it is an estimation of bid and ask size per bar. The code for the volume delta is from tradingview.com/support/solutions/43000725057-volume-delta/

Here’s a link to a more sophisticated research article about Hawkes Process than this post arxiv.org/pdf/2105.00521

This tool is designed to show how excitable the different sides are. Excitability refers to how likely that side is to get more activity. Alan Hawkes made Hawkes Process for seismology. A big earthquake happens, lots of little ones follow until it returns to normal. Same for financial markets, big orders come in, causing a lot of little orders to come. Alpha, Beta, and Lambda parameters are estimated by minimizing a negative log likelihood function.

How it works

There are a few components to this script, so we’ll go into the equation and then the other functions used in this script.

Pine Script®
hawkes_process(params, events, lkb) => alpha = clamp(array.get(params, 0), 0.01, 1.0) beta = clamp(array.get(params, 1), 0.1, 10.0) lambda_0 = clamp(array.get(params, 2), 0.01, 0.3) intensity = array.new_float(lkb, 0.0) events_array = array.new_float(lkb, 0.0) for i = 0 to lkb - 1 array.set(events_array, i, array.get(events, i)) for i = 0 to lkb - 1 sum_decay = 0.0 current_event = array.get(events_array, i) for j = 0 to i - 1 time_diff = i - j past_event = array.get(events_array, j) decay = math.exp(-beta * time_diff) past_event_val = na(past_event) ? 0 : past_event sum_decay := sum_decay + (past_event_val * decay) array.set(intensity, i, lambda_0 + alpha * sum_decay) intensity


The parameters alpha, beta, and lambda all represent a different real thing.

Alpha (α):
Definition: Alpha represents the excitation factor or the magnitude of the influence that past events have on the future intensity of the process. In simpler terms, it measures how much each event "excites" or triggers additional events. It is constrained between 0.01 and 1.0 (e.g., clamp(array.get(params, 0), 0.01, 1.0)). A higher alpha means past events have a stronger influence on increasing the intensity (likelihood) of future events. Initial value is set to 0.1 in init_params. In the hawkes_process function, alpha scales the contribution of past events to the current intensity via the term alpha * sum_decay.
Beta (β):
Definition: Beta controls the rate of exponential decay of the influence of past events over time. It determines how quickly the effect of a past event fades away. It is constrained between 0.1 and 10.0 (e.g., clamp(array.get(params, 1), 0.1, 10.0)). A higher beta means the influence of past events decays faster, while a lower beta means the influence lingers longer. Initial value is set to 0.1 in init_params. In the hawkes_process function, beta appears in the decay term math.exp(-beta * time_diff), which reduces the impact of past events as the time difference (time_diff) increases.
Lambda_0 (λ₀):
Definition: Lambda_0 is the baseline intensity of the process, representing the rate at which events occur in the absence of any excitation from past events. It’s the "background" rate of the process. It is constrained between 0.01 and 0.3 .A higher lambda_0 means a higher natural frequency of events, even without the influence of past events. Initial value is set to 0.1 in init_params. In the hawkes_process function, lambda_0 sets the minimum intensity level, to which the excitation term (alpha * sum_decay) is added: lambda_0 + alpha * sum_decay

Alpha (α): Strength of event excitation (how much past events boost future events).
Beta (β): Rate of decay of past event influence (how fast the effect fades).
Lambda_0 (λ₀): Baseline event rate (background intensity without excitation).

Other parts of the script.

Clamp

The clamping function is a simple way to make sure parameters don’t grow or shrink too much.

ObjectiveFunction

This function defines the objective function (negative log-likelihood) to minimize during parameter optimization.It returns a float representing the negative log-likelihood (to be minimized).
How It Works:
Calls hawkes_process to compute the intensity array based on current parameters.Iterates over the lookback period:lambda_t: Intensity at time i.event: Event magnitude at time i.Handles na values by replacing them with 0.Computes log-likelihood: event_clean * math.log(math.max(lambda_t_clean, 0.001)) - lambda_t_clean.Ensures lambda_t_clean is at least 0.001 to avoid log(0).Accumulates into log_likelihood.Returns -log_likelihood (negative because the goal is to minimize, not maximize).
It is used in the optimization process to evaluate how well the parameters fit the observed event data.

Finite Difference Gradient:

This function calculates the gradient of the objective function we spoke about. The gradient is like a directional derivative. Which is like the direction of the rate of change. Which is like the direction of the slope of a hill, we can go up or down a hill. It nudges around the parameter, and calculates the derivative of the parameter. The array of these nudged around parameters is what is returned after they are optimized.

Minimize:

This is the function that actually has the loop and calls the Finite Difference Gradient each time. Here is where the minimizing happens, how we go down the hill. If we are below a tolerance, we are at the bottom of the hill.

Applied

After an initial guess the parameters are optimized with a mix of bid and ask levels to prevent some over-fitting for each side while keeping some efficiency. We initialize two different arrays to store the bid and ask sizes. After we optimize the parameters we clamp them for the calculations. We then get the array of intensities from the Hawkes Process of bid and ask and plot them both. When the bids are greater than the ask it represents a bullish scenario where there are likely to be more buy than sell orders, pushing up price.

Tool examples:

The idea is that when the bid side is more excitable it is more likely to see a bullish reaction, when the ask is we see a bearish reaction.

syot kilat

We see that there are a lot of crossovers, and I picked two specific spots. The idea of this isn’t to spot crossovers but avoid chop. The values are either close together or far apart. When they are far, it is a classification for us to look for our own opportunities in, when they are close, it signals the market can’t pick a direction just yet.

syot kilat

The value works just as well on a higher timeframe as on a lower one. Hawkes Process is an estimate, so there is a leading value aspect of it.

syot kilat

The value works on equities as well, here is TSLA on a lower time frame with a lookback of 5.

Inputs

Users can enter the lookback value and timeframe.

No tool is perfect, the Hawkes Process value is also not perfect and should not be followed blindly. It is good to use any tool along with discretion and price action.

Penafian

Maklumat dan penerbitan adalah tidak dimaksudkan untuk menjadi, dan tidak membentuk, nasihat untuk kewangan, pelaburan, perdagangan dan jenis-jenis lain atau cadangan yang dibekalkan atau disahkan oleh TradingView. Baca dengan lebih lanjut di Terma Penggunaan.