AI Predictive Flow (Zeiierman)█ Overview
AI Predictive Flow (Zeiierman) is a pattern-based oscillator that estimates future price direction by comparing the current market state to similar historical conditions.
Instead of relying on traditional indicators like momentum or moving averages alone, the script builds a multi-feature representation of price behavior and uses a k-Nearest Neighbors (kNN) model to identify past patterns that closely resemble the present.
From those matches, it derives an expected forward return, which is then transformed into a smooth oscillator and a predicted trend regime.
The result is a forward-looking signal that reflects a data-driven expectation based on similar past patterns, not just current price movement.
█ How It Works
⚪ Feature Extraction (Market State Model)
The script converts price into a compact feature set that describes the current market state.
It uses four core features:
Short-term return
Momentum
RSI bias
EMA spread
These are created inside the feature function:
feat(shift, mode) =>
c = close
c1 = close
cm = close
ef = ta.ema(close, fLen)
es = ta.ema(close, sLen)
r = ta.rsi(close, rsiLn)
float v = 0.0
if mode == 1
v := c1 != 0 ? math.log(c / c1) : 0.0
else if mode == 2
v := cm != 0 ? (c - cm) / cm : 0.0
else if mode == 3
v := (r - 50.0) / 50.0
else
v := c != 0 ? (ef - es) / c : 0.0
v
Each feature captures a different dimension of price behavior:
return measures immediate movement
momentum measures directional displacement
RSI bias measures internal pressure
EMA spread measures trend structure
These values are then stacked across multiple bars to form the pattern used for comparison.
⚪ Pattern Memory (Historical Pattern Library)
The script stores rolling sequences of each feature into separate matrices so the current market state can be compared against past states.
That process is built here:
pushFeat(mat, mode) =>
vals = array.new(tot, 0.0)
for i = 0 to tot - 1
array.set(vals, tot - 1 - i, feat(i, mode))
cur = array.slice(vals, tot - len, tot)
old = array.slice(vals, 0, len)
matrix out = matrix.new(1, len, 0.0)
for i = 0 to len - 1
matrix.set(out, 0, i, array.get(cur, i))
hist = array.new(len, 0.0)
for i = 0 to len - 1
array.set(hist, i, array.get(old, i))
if mat.rows() >= mem
mat.remove_row(0)
mat.add_row(mat.rows(), hist)
out
This creates:
a current feature row
a rolling history of prior feature patterns
So rather than comparing single-bar values, the model compares multi-bar pattern structure.
⚪ Pattern Matching Engine (kNN Distance Model)
Once the current feature pattern is built, it is compared to all stored historical patterns.
Distance is measured feature-by-feature across the full pattern length:
getDist(matrix a1, matrix a2, matrix a3, matrix a4, matrix b1, matrix b2, matrix b3, matrix b4) =>
out = array.new(b1.rows(), 0.0)
for i = 0 to b1.rows() - 1
s = 0.0
d1 = a1.diff(b1.submatrix(i, i + 1)).row(0)
d2 = a2.diff(b2.submatrix(i, i + 1)).row(0)
d3 = a3.diff(b3.submatrix(i, i + 1)).row(0)
d4 = a4.diff(b4.submatrix(i, i + 1)).row(0)
for j = 0 to len - 1
s += math.pow(d1.get(j), 2) * 0.25 +
math.pow(d2.get(j), 2) * 0.25 +
math.pow(d3.get(j), 2) * 0.25 +
math.pow(d4.get(j), 2) * 0.25
out.set(i, math.sqrt(s))
out
This produces a similarity score for every stored pattern. A smaller distance means the past setup looked more like the present one.
⚪ Prediction Model (kNN Forward Expectation)
After the distances are ranked, the script selects the nearest neighbors and averages their future outcomes.
The kNN model is implemented here:
knn(dist, n) =>
ix = dist.sort_indices()
useN = math.min(n, ix.size())
sumD = 0.0
avg = 0.0
for i = 0 to useN - 1
sumD += dist.get(ix.get(i))
if useN > 0
for i = 0 to useN - 1
d = dist.get(ix.get(i))
w = useN > 1 ? (sumD != 0 ? (1 - d / sumD) : 1.0) : 1.0
avg += Y.get(ix.get(i)) * w
avg
The forward return used for comparison is defined here:
y := math.log(base) - math.log(base )
This represents the forward return following each historical pattern. The result is a weighted expectation of future movement, not just a reading of current trend.
⚪ Predictive Oscillator
The raw kNN prediction is smoothed and transformed into the main oscillator and signal line.
pred_ = ta.ema(pred, smth)
if not na(pred)
predSm := smth > 1 ? pred_ : pred
osc = ta.ema(predSm, oscLn)
sig = ta.ema(osc, sigLn)
hist = osc - sig
This creates:
Oscillator = smoothed expected return
Signal line = secondary smoothing for crossover confirmation
Histogram = distance between oscillator and signal
⚪ Predicted Trend Regime
Beyond the oscillator, the script also builds a broader trend regime using the predicted price path.
First, the raw prediction is converted into a projected price line:
predLine := base + base * (math.exp(pred) - 1)
Then a regime band is created using ATR:
hiRef = predLine + bandM * atr
loRef = predLine - bandM * atr
if ta.highest(hiRef, regLn) == hiRef
trendUp := true
if ta.lowest(loRef, regLn) == loRef
trendUp := false
This background state represents:
bullish predicted regime when the projected path is pressing into new highs
bearish predicted regime when the projected path is pressing into new lows
So the background is not showing the raw price trend. It is showing the model’s predicted regime bias.
█ How to Use
⚪ Read the Oscillator
Above 0 → bullish expectation
Below 0 → bearish expectation
Near 0 → neutral/low conviction
Far from 0 → strong directional push
Use crossovers for entry timing:
Bullish crossover → potential upward continuation
Bearish crossover → potential downward continuation
⚪ Use the Predicted Trend Regime
The background highlights the model’s broader directional bias:
Green → predicted bullish regime
Red → predicted bearish regime
Regime shifts often indicate:
early trend transitions
continuation confirmation
structural changes in expectation
⚪ Combine Signals
Best use comes from alignment:
Oscillator above zero + bullish regime + signal → strong continuation bias
Oscillator below zero + bearish regime + signal → strong downside bias
Divergence between the two → caution / mixed signals
█ Settings
Pattern Length – Controls how many bars define the current pattern. Higher values capture more structure, lower values increase responsiveness.
Memory Size – Number of historical patterns stored for comparison. Larger values improve context but increase computation.
Neighbors (k) – Number of closest matches used in prediction. Lower values are more reactive, higher values are smoother.
Prediction Smoothing – EMA smoothing applied to the raw prediction. Reduces noise at the cost of lag.
Signal Length – Smoothing of the signal line used for crossover signals.
-----------------
Disclaimer
The content provided in my scripts, indicators, ideas, algorithms, and systems is for educational and informational purposes only. It does not constitute financial advice, investment recommendations, or a solicitation to buy or sell any financial instruments. I will not accept liability for any loss or damage, including without limitation any loss of profit, which may arise directly or indirectly from the use of or reliance on such information.
All investments involve risk, and the past performance of a security, industry, sector, market, financial product, trading strategy, backtest, or individual's trading does not guarantee future results or returns. Investors are fully responsible for any investment decisions they make. Such decisions should be based solely on an evaluation of their financial circumstances, investment objectives, risk tolerance, and liquidity needs.
Predictivealgorithms
regressionsLibrary "regressions"
This library computes least square regression models for polynomials of any form for a given data set of x and y values.
fit(X, y, reg_type, degrees)
Takes a list of X and y values and the degrees of the polynomial and returns a least square regression for the given polynomial on the dataset.
Parameters:
X (array) : (float ) X inputs for regression fit.
y (array) : (float ) y outputs for regression fit.
reg_type (string) : (string) The type of regression. If passing value for degrees use reg.type_custom
degrees (array) : (int ) The degrees of the polynomial which will be fit to the data. ex: passing array.from(0, 3) would be a polynomial of form c1x^0 + c2x^3 where c2 and c1 will be coefficients of the best fitting polynomial.
Returns: (regression) returns a regression with the best fitting coefficients for the selecected polynomial
regress(reg, x)
Regress one x input.
Parameters:
reg (regression) : (regression) The fitted regression which the y_pred will be calulated with.
x (float) : (float) The input value cooresponding to the y_pred.
Returns: (float) The best fit y value for the given x input and regression.
predict(reg, X)
Predict a new set of X values with a fitted regression. -1 is one bar ahead of the realtime
Parameters:
reg (regression) : (regression) The fitted regression which the y_pred will be calulated with.
X (array)
Returns: (float ) The best fit y values for the given x input and regression.
generate_points(reg, x, y, left_index, right_index)
Takes a regression object and creates chart points which can be used for plotting visuals like lines and labels.
Parameters:
reg (regression) : (regression) Regression which has been fitted to a data set.
x (array) : (float ) x values which coorispond to passed y values
y (array) : (float ) y values which coorispond to passed x values
left_index (int) : (int) The offset of the bar farthest to the realtime bar should be larger than left_index value.
right_index (int) : (int) The offset of the bar closest to the realtime bar should be less than right_index value.
Returns: (chart.point ) Returns an array of chart points
plot_reg(reg, x, y, left_index, right_index, curved, close, line_color, line_width)
Simple plotting function for regression for more custom plotting use generate_points() to create points then create your own plotting function.
Parameters:
reg (regression) : (regression) Regression which has been fitted to a data set.
x (array)
y (array)
left_index (int) : (int) The offset of the bar farthest to the realtime bar should be larger than left_index value.
right_index (int) : (int) The offset of the bar closest to the realtime bar should be less than right_index value.
curved (bool) : (bool) If the polyline is curved or not.
close (bool) : (bool) If true the polyline will be closed.
line_color (color) : (color) The color of the line.
line_width (int) : (int) The width of the line.
Returns: (polyline) The polyline for the regression.
series_to_list(src, left_index, right_index)
Convert a series to a list. Creates a list of all the cooresponding source values
from left_index to right_index. This should be called at the highest scope for consistency.
Parameters:
src (float) : (float ) The source the list will be comprised of.
left_index (int) : (float ) The left most bar (farthest back historical bar) which the cooresponding source value will be taken for.
right_index (int) : (float ) The right most bar closest to the realtime bar which the cooresponding source value will be taken for.
Returns: (float ) An array of size left_index-right_index
range_list(start, stop, step)
Creates an from the start value to the stop value.
Parameters:
start (int) : (float ) The true y values.
stop (int) : (float ) The predicted y values.
step (int) : (int) Positive integer. The spacing between the values. ex: start=1, stop=6, step=2:
Returns: (float ) An array of size stop-start
regression
Fields:
coeffs (array__float)
degrees (array__float)
type_linear (series__string)
type_quadratic (series__string)
type_cubic (series__string)
type_custom (series__string)
_squared_error (series__float)
X (array__float)
Pine Script® library

