KDB knowledge

Momentum indicators

MACD, stochastic, stochastic RSI, Williams %R, CCI, rate of change, momentum and TRIX on candles, with the same results as TA-Lib.

Momentum is the speed of a price move. A momentum indicator tells how strong a rise or a fall is, and when it gets weaker. Many of them are oscillators: numbers that swing between fixed levels (like 0 and 100). Near the top level a share is called overbought (it rose a lot and may fall back); near the bottom level oversold.

These are series functions, like sma, ema, rsi and atr, with the same rules:

FunctionDefault periodsFirst value on candleIn general
macd, macd_signal, macd_hist12, 26, 934slow + signal - 1
stoch_k, stoch_d14, 3, 318k + k_slowing + d - 2
stochf_k1414k
stochrsi_k, stochrsi_d14, 5, 321rsi_period + k + d - 1
willr1414n
cci2020n
roc, rocp, rocr, mom1011n + 1
trix30893n - 1

Example: Momentum of CITY's one-minute candles: MACD, stochastic, Williams %R and CCI (the last 5) (sample data: sample)

SELECT time, close, macd, stoch_k, willr, cci
FROM (SELECT time, close,
             round(macd(close), 3) AS macd,
             round(stoch_k(high, low, close), 1) AS stoch_k,
             round(willr(high, low, close), 1) AS willr,
             round(cci(high, low, close), 1) AS cci
      FROM ochl_minutes
      WHERE symbol = 'CITY') t
ORDER BY time DESC
LIMIT 5;

Result:

time (TIMESTAMP)close (DOUBLE)macd (DOUBLE)stoch_k (DOUBLE)willr (DOUBLE)cci (DOUBLE)
2026-09-10T09:14:00.000Z504.9-0.09335.2-66.7-6.3
2026-09-10T09:13:00.000Z505.1-0.09129.3-55.616
2026-09-10T09:12:00.000Z504.8-0.10921.5-72.2-57.3
2026-09-10T09:11:00.000Z504.5-0.09928.9-84.2-80.9
2026-09-10T09:10:00.000Z504.6-0.05438.8-78.9-57.7

(5 rows)

macd, macd_signal, macd_hist

Syntax:

macd(x [, fast [, slow [, signal]]])
macd_signal(x [, fast [, slow [, signal]]])
macd_hist(x [, fast [, slow [, signal]]])
macd(x, fast, slow, signal) OVER ([PARTITION BY ...] [ORDER BY ...])

MACD (moving average convergence divergence) shows the trend and its strength with three lines:

When the MACD line crosses above the signal line (the histogram turns from minus to plus), traders read it as a buy signal; crossing below is a sell signal.

ArgumentTypeMeaning
xnumberthe price, usually close
fastwhole number, 1 or morethe short EMA period; default 12
slowwhole number, 1 or morethe long EMA period; default 26
signalwhole number, 1 or morethe EMA period of the signal line; default 9

Example: MACD, signal and histogram of CITY's one-minute candles (the last 5) (sample data: sample)

SELECT time, close, macd, signal, hist
FROM (SELECT time, close,
             round(macd(close), 3) AS macd,
             round(macd_signal(close), 3) AS signal,
             round(macd_hist(close), 3) AS hist
      FROM ochl_minutes
      WHERE symbol = 'CITY') t
ORDER BY time DESC
LIMIT 5;

Result:

time (TIMESTAMP)close (DOUBLE)macd (DOUBLE)signal (DOUBLE)hist (DOUBLE)
2026-09-10T09:14:00.000Z504.9-0.093-0.062-0.031
2026-09-10T09:13:00.000Z505.1-0.091-0.054-0.037
2026-09-10T09:12:00.000Z504.8-0.109-0.045-0.063
2026-09-10T09:11:00.000Z504.5-0.099-0.029-0.069
2026-09-10T09:10:00.000Z504.6-0.054-0.012-0.042

(5 rows)

Example: MACD crossovers: buy and sell signals of COAST on 10 September (sample data: sample)

SELECT time, close, hist,
       CASE WHEN hist > 0 THEN 'BUY' ELSE 'SELL' END AS signal
FROM (SELECT time, close, hist, lag(hist) AS prev_hist
      FROM (SELECT time, close, round(macd_hist(close), 3) AS hist
            FROM ochl_minutes
            WHERE symbol = 'COAST') a) b
WHERE time IN '2026-09-10'
  AND ((hist > 0 AND prev_hist <= 0) OR (hist < 0 AND prev_hist >= 0))
ORDER BY time
LIMIT 6;

Result:

time (TIMESTAMP)close (DOUBLE)hist (DOUBLE)signal (STRING)
2026-09-10T05:35:00.000Z380.8-0.026SELL
2026-09-10T05:53:00.000Z3800.02BUY
2026-09-10T06:21:00.000Z380.7-0.041SELL
2026-09-10T06:36:00.000Z380.40.03BUY
2026-09-10T06:43:00.000Z379.4-0.031SELL
2026-09-10T06:45:00.000Z380.20.013BUY

(6 rows)

Example: Short periods on daily candles: MACD 3, 6, 3 of every symbol on the last day (sample data: sample)

SELECT time, symbol, close, macd, signal, hist
FROM (SELECT time, symbol, close,
             round(macd(close, 3, 6, 3) OVER (PARTITION BY symbol ORDER BY time), 2) AS macd,
             round(macd_signal(close, 3, 6, 3) OVER (PARTITION BY symbol ORDER BY time), 2) AS signal,
             round(macd_hist(close, 3, 6, 3) OVER (PARTITION BY symbol ORDER BY time), 2) AS hist
      FROM ochl_day
      WHERE time >= '2026-08-23') t
WHERE time IN '2026-09-10'
ORDER BY symbol;

Result:

time (TIMESTAMP)symbol (SYMBOL)close (DOUBLE)macd (DOUBLE)signal (DOUBLE)hist (DOUBLE)
2026-09-10T00:00:00.000ZCITY504.91.020.20.83
2026-09-10T00:00:00.000ZCOAST376.10.610.83-0.22
2026-09-10T00:00:00.000ZVOLT191.23.772.930.85

(3 rows)

stoch_k, stoch_d

Syntax:

stoch_k(high, low, close [, k [, k_slowing [, d]]])
stoch_d(high, low, close [, k [, k_slowing [, d]]])
stoch_k(high, low, close, k, k_slowing, d) OVER ([PARTITION BY ...] [ORDER BY ...])

The slow stochastic oscillator, from 0 to 100. It tells where the close is inside the range of the last k candles: 100 is at the highest high, 0 at the lowest low.

Above 80 is overbought, below 20 oversold. When %K crosses above %D in the oversold zone, traders read it as a buy signal.

ArgumentTypeMeaning
highnumberthe candle's high
lownumberthe candle's low
closenumberthe candle's close
kwhole number, 1 or morecandles for the highest high and lowest low; default 14
k_slowingwhole number, 1 or morethe SMA period of %K; default 3
dwhole number, 1 or morethe SMA period of %D; default 3

Example: Slow stochastic 14, 3, 3 of COAST's one-minute candles (the last 5) (sample data: sample)

SELECT time, close, k, d,
       CASE WHEN k >= 80 THEN 'overbought' WHEN k <= 20 THEN 'oversold' ELSE 'normal' END AS zone
FROM (SELECT time, close,
             round(stoch_k(high, low, close), 1) AS k,
             round(stoch_d(high, low, close), 1) AS d
      FROM ochl_minutes
      WHERE symbol = 'COAST') t
ORDER BY time DESC
LIMIT 5;

Result:

time (TIMESTAMP)close (DOUBLE)k (DOUBLE)d (DOUBLE)zone (STRING)
2026-09-10T09:14:00.000Z376.187.387.2overbought
2026-09-10T09:13:00.000Z376.288.682.5overbought
2026-09-10T09:12:00.000Z37685.871.2overbought
2026-09-10T09:11:00.000Z375.573.152.8normal
2026-09-10T09:10:00.000Z375.654.638.4normal

(5 rows)

Example: Stochastic 5, 3, 3 on daily candles, every symbol (sample data: sample)

SELECT time, symbol, close, k, d
FROM (SELECT time, symbol, close,
             round(stoch_k(high, low, close, 5, 3, 3) OVER (PARTITION BY symbol ORDER BY time), 1) AS k,
             round(stoch_d(high, low, close, 5, 3, 3) OVER (PARTITION BY symbol ORDER BY time), 1) AS d
      FROM ochl_day
      WHERE time >= '2026-08-23') t
WHERE time >= '2026-09-08'
ORDER BY symbol, time;

Result:

time (TIMESTAMP)symbol (SYMBOL)close (DOUBLE)k (DOUBLE)d (DOUBLE)
2026-09-08T00:00:00.000ZCITY497.53730.7
2026-09-09T00:00:00.000ZCITY504.64337.1
2026-09-10T00:00:00.000ZCITY504.950.443.5
2026-09-08T00:00:00.000ZCOAST377.281.577.3
2026-09-09T00:00:00.000ZCOAST380.170.778.2
2026-09-10T00:00:00.000ZCOAST376.145.665.9
2026-09-08T00:00:00.000ZVOLT182.47573.3
2026-09-09T00:00:00.000ZVOLT187.378.475.8
2026-09-10T00:00:00.000ZVOLT191.29181.4

(9 rows)

Example: %K crosses above %D: buy signals of CITY's one-minute candles on 10 September (sample data: sample)

SELECT time, close, k, d
FROM (SELECT time, close, k, d, lag(k) AS prev_k, lag(d) AS prev_d
      FROM (SELECT time, close,
                   round(stoch_k(high, low, close), 1) AS k,
                   round(stoch_d(high, low, close), 1) AS d
            FROM ochl_minutes
            WHERE symbol = 'CITY') a) b
WHERE time IN '2026-09-10' AND k > d AND prev_k <= prev_d AND k < 30
ORDER BY time
LIMIT 5;

Result:

time (TIMESTAMP)close (DOUBLE)k (DOUBLE)d (DOUBLE)
2026-09-10T05:18:00.000Z504.418.916.3
2026-09-10T05:30:00.000Z504.526.225.5
2026-09-10T06:06:00.000Z505.515.613.8
2026-09-10T06:37:00.000Z504.511.510
2026-09-10T06:48:00.000Z503.28.46.4

(5 rows)

stochf_k

Syntax:

stochf_k(high, low, close [, k])
stochf_k(high, low, close, k) OVER ([PARTITION BY ...] [ORDER BY ...])

The fast stochastic %K: the raw stochastic value without smoothing, (close - lowest low) / (highest high - lowest low) × 100 over the last k candles. It reacts at once, so it jumps more than stoch_k.

ArgumentTypeMeaning
highnumberthe candle's high
lownumberthe candle's low
closenumberthe candle's close
kwhole number, 1 or morehow many candles; default 14

Example: Fast %K and fast %D (SMA 3 of fast %K) of VOLT (sample data: sample)

SELECT time, close, fast_k, round(sma(fast_k, 3), 1) AS fast_d
FROM (SELECT time, close, round(stochf_k(high, low, close, 5), 1) AS fast_k
      FROM ochl_day
      WHERE symbol = 'VOLT' AND time >= '2026-08-23') t
ORDER BY time;

Result:

time (TIMESTAMP)close (DOUBLE)fast_k (DOUBLE)fast_d (DOUBLE)
2026-08-23T00:00:00.000Z181NULLNULL
2026-08-24T00:00:00.000Z178.5NULLNULL
2026-08-25T00:00:00.000Z176.8NULLNULL
2026-08-26T00:00:00.000Z174.2NULLNULL
2026-08-27T00:00:00.000Z173.311.2NULL
2026-08-30T00:00:00.000Z17318.5NULL
2026-08-31T00:00:00.000Z172.617.215.6
2026-09-01T00:00:00.000Z16915.317
2026-09-02T00:00:00.000Z171.548.827.1
2026-09-03T00:00:00.000Z1768750.4
2026-09-06T00:00:00.000Z180.177.171
2026-09-07T00:00:00.000Z176.957.874
2026-09-08T00:00:00.000Z182.489.974.9
2026-09-09T00:00:00.000Z187.387.578.4
2026-09-10T00:00:00.000Z191.295.490.9

(15 rows)

stochrsi_k, stochrsi_d

Syntax:

stochrsi_k(x [, rsi_period [, k [, d]]])
stochrsi_d(x [, rsi_period [, k [, d]]])
stochrsi_k(x, rsi_period, k, d) OVER ([PARTITION BY ...] [ORDER BY ...])

The stochastic RSI, from 0 to 100. It puts the stochastic formula on the RSI values instead of the prices: where is today's RSI inside the range of the last k RSI values? It moves faster than the RSI and reaches overbought (above 80) and oversold (below 20) more often.

ArgumentTypeMeaning
xnumberthe price, usually close
rsi_periodwhole number, 1 or morethe RSI period; default 14
kwhole number, 1 or morehow many RSI values for the range; default 5
dwhole number, 1 or morethe SMA period of %D; default 3

Example: Stochastic RSI 14, 5, 3 of CITY's one-minute candles (the last 5) (sample data: sample)

SELECT time, close, rsi14, k, d
FROM (SELECT time, close,
             round(rsi(close, 14), 1) AS rsi14,
             round(stochrsi_k(close), 1) AS k,
             round(stochrsi_d(close), 1) AS d
      FROM ochl_minutes
      WHERE symbol = 'CITY') t
ORDER BY time DESC
LIMIT 5;

Result:

time (TIMESTAMP)close (DOUBLE)rsi14 (DOUBLE)k (DOUBLE)d (DOUBLE)
2026-09-10T09:14:00.000Z504.947.669.482.4
2026-09-10T09:13:00.000Z505.150.110059.3
2026-09-10T09:12:00.000Z504.846.277.825.9
2026-09-10T09:11:00.000Z504.54203.6
2026-09-10T09:10:00.000Z504.64303.6

(5 rows)

willr, williams_r

Syntax:

willr(high, low, close [, n])
williams_r(high, low, close [, n])
willr(high, low, close, n) OVER ([PARTITION BY ...] [ORDER BY ...])

Williams %R, from -100 to 0. Like the stochastic, it shows where the close is inside the range of the last n candles, but counted down from the top: 0 is at the highest high, -100 at the lowest low. Above -20 is overbought, below -80 oversold. williams_r is the same function.

%R = (highest high - close) / (highest high - lowest low) × -100

ArgumentTypeMeaning
highnumberthe candle's high
lownumberthe candle's low
closenumberthe candle's close
nwhole number, 1 or morehow many candles; default 14

Example: Williams %R 5 of every symbol on the last three days (sample data: sample)

SELECT time, symbol, close, wr,
       CASE WHEN wr >= -20 THEN 'overbought' WHEN wr <= -80 THEN 'oversold' ELSE 'normal' END AS zone
FROM (SELECT time, symbol, close,
             round(williams_r(high, low, close, 5) OVER (PARTITION BY symbol ORDER BY time), 1) AS wr
      FROM ochl_day
      WHERE time >= '2026-08-23') t
WHERE time >= '2026-09-08'
ORDER BY symbol, time;

Result:

time (TIMESTAMP)symbol (SYMBOL)close (DOUBLE)wr (DOUBLE)zone (STRING)
2026-09-08T00:00:00.000ZCITY497.5-60.9normal
2026-09-09T00:00:00.000ZCITY504.6-44.8normal
2026-09-10T00:00:00.000ZCITY504.9-43.1normal
2026-09-08T00:00:00.000ZCOAST377.2-22.9normal
2026-09-09T00:00:00.000ZCOAST380.1-53.9normal
2026-09-10T00:00:00.000ZCOAST376.1-86.3oversold
2026-09-08T00:00:00.000ZVOLT182.4-10.1overbought
2026-09-09T00:00:00.000ZVOLT187.3-12.5overbought
2026-09-10T00:00:00.000ZVOLT191.2-4.6overbought

(9 rows)

Example: %R is the fast stochastic minus 100 (sample data: sample)

SELECT time, close,
       round(willr(high, low, close, 5), 2) AS willr5,
       round(stochf_k(high, low, close, 5) - 100, 2) AS fast_k_minus_100
FROM ochl_day
WHERE symbol = 'COAST' AND time >= '2026-09-03'
ORDER BY time;

Result:

time (TIMESTAMP)close (DOUBLE)willr5 (DOUBLE)fast_k_minus_100 (DOUBLE)
2026-09-03T00:00:00.000Z373.2NULLNULL
2026-09-06T00:00:00.000Z375.4NULLNULL
2026-09-07T00:00:00.000Z379.2NULLNULL
2026-09-08T00:00:00.000Z377.2NULLNULL
2026-09-09T00:00:00.000Z380.1-53.89-53.89
2026-09-10T00:00:00.000Z376.1-86.31-86.31

(6 rows)

cci

Syntax:

cci(high, low, close [, n])
cci(high, low, close, n) OVER ([PARTITION BY ...] [ORDER BY ...])

The commodity channel index. It measures how far the typical price (high + low + close) / 3 is from its average of the last n candles, compared with the usual distance. Most values are between -100 and +100. Above +100 the price is unusually high (a strong rise, or overbought); below -100 unusually low.

CCI = (typical price - SMA of the typical price) / (0.015 × mean deviation). The mean deviation is the average distance of the n typical prices from their SMA.

ArgumentTypeMeaning
highnumberthe candle's high
lownumberthe candle's low
closenumberthe candle's close
nwhole number, 1 or morehow many candles; default 20

Example: CCI 20 of COAST's one-minute candles (the last 5) (sample data: sample)

SELECT time, close, cci20,
       CASE WHEN cci20 > 100 THEN 'above +100' WHEN cci20 < -100 THEN 'below -100' ELSE 'inside' END AS channel
FROM (SELECT time, close, round(cci(high, low, close), 1) AS cci20
      FROM ochl_minutes
      WHERE symbol = 'COAST') t
ORDER BY time DESC
LIMIT 5;

Result:

time (TIMESTAMP)close (DOUBLE)cci20 (DOUBLE)channel (STRING)
2026-09-10T09:14:00.000Z376.1148.5above +100
2026-09-10T09:13:00.000Z376.2135.6above +100
2026-09-10T09:12:00.000Z376129.4above +100
2026-09-10T09:11:00.000Z375.545.1inside
2026-09-10T09:10:00.000Z375.643.4inside

(5 rows)

Example: CCI 5 on daily candles, every symbol on the last day (sample data: sample)

SELECT symbol, close, cci5
FROM (SELECT time, symbol, close,
             round(cci(high, low, close, 5) OVER (PARTITION BY symbol ORDER BY time), 1) AS cci5
      FROM ochl_day) t
WHERE time IN '2026-09-10'
ORDER BY cci5 DESC;

Result:

symbol (SYMBOL)close (DOUBLE)cci5 (DOUBLE)
VOLT191.2108.6
CITY504.956.2
COAST376.1-38

(3 rows)

roc, rocp, rocr

Syntax:

roc(x [, n])
rocp(x [, n])
rocr(x [, n])
roc(x, n) OVER ([PARTITION BY ...] [ORDER BY ...])

The rate of change: how much the price changed against the price n candles ago. The three functions give the same change in three forms:

FunctionFormula10% rise gives
roc(x / x n candles ago - 1) × 10010 (percent)
rocp(x - x n candles ago) / x n candles ago0.1 (a fraction)
rocrx / x n candles ago1.1 (a ratio)

Above 0 (above 1 for rocr), the price is higher than n candles ago. When ROC gets smaller while the price still rises, the move is losing speed.

ArgumentTypeMeaning
xnumberthe price, usually close
nwhole number, 1 or morehow many candles back; default 10

Example: 5-day rate of change of CITY in three forms (sample data: sample)

SELECT time, close,
       round(roc(close, 5), 2) AS roc5_pct,
       round(rocp(close, 5), 4) AS rocp5,
       round(rocr(close, 5), 4) AS rocr5
FROM ochl_day
WHERE symbol = 'CITY' AND time >= '2026-08-23'
ORDER BY time;

Result:

time (TIMESTAMP)close (DOUBLE)roc5_pct (DOUBLE)rocp5 (DOUBLE)rocr5 (DOUBLE)
2026-08-23T00:00:00.000Z507.9NULLNULLNULL
2026-08-24T00:00:00.000Z510.3NULLNULLNULL
2026-08-25T00:00:00.000Z513.3NULLNULLNULL
2026-08-26T00:00:00.000Z513.2NULLNULLNULL
2026-08-27T00:00:00.000Z505.9NULLNULLNULL
2026-08-30T00:00:00.000Z503.1-0.95-0.00950.9905
2026-08-31T00:00:00.000Z505.7-0.9-0.0090.991
2026-09-01T00:00:00.000Z502.4-2.12-0.02120.9788
2026-09-02T00:00:00.000Z496.4-3.27-0.03270.9673
2026-09-03T00:00:00.000Z497.9-1.58-0.01580.9842
2026-09-06T00:00:00.000Z499-0.81-0.00810.9919
2026-09-07T00:00:00.000Z498.7-1.38-0.01380.9862
2026-09-08T00:00:00.000Z497.5-0.98-0.00980.9902
2026-09-09T00:00:00.000Z504.61.650.01651.0165
2026-09-10T00:00:00.000Z504.91.410.01411.0141

(15 rows)

Example: Which symbol rose most in the last 5 trading days? (sample data: sample)

SELECT symbol, close, roc5
FROM (SELECT time, symbol, close,
             round(roc(close, 5) OVER (PARTITION BY symbol ORDER BY time), 2) AS roc5
      FROM ochl_day) t
WHERE time IN '2026-09-10'
ORDER BY roc5 DESC;

Result:

symbol (SYMBOL)close (DOUBLE)roc5 (DOUBLE)
VOLT191.28.64
CITY504.91.41
COAST376.10.78

(3 rows)

mom, momentum

Syntax:

mom(x [, n])
momentum(x [, n])
mom(x, n) OVER ([PARTITION BY ...] [ORDER BY ...])

The momentum: the price now minus the price n candles ago, in the unit of the price. Above 0, the price is higher than n candles ago. momentum is the same function.

ArgumentTypeMeaning
xnumberthe price, usually close
nwhole number, 1 or morehow many candles back; default 10

Example: 10-minute momentum of COAST (the last 5) (sample data: sample)

SELECT time, close, mom10
FROM (SELECT time, close, round(momentum(close), 2) AS mom10
      FROM ochl_minutes
      WHERE symbol = 'COAST') t
ORDER BY time DESC
LIMIT 5;

Result:

time (TIMESTAMP)close (DOUBLE)mom10 (DOUBLE)
2026-09-10T09:14:00.000Z376.11.5
2026-09-10T09:13:00.000Z376.21.8
2026-09-10T09:12:00.000Z3761.2
2026-09-10T09:11:00.000Z375.50.1
2026-09-10T09:10:00.000Z375.60.2

(5 rows)

Example: The first n rows have no old price (sample data: sample)

SELECT time, close, round(mom(close, 3), 1) AS mom3, round(close - lag(close, 3), 1) AS same
FROM ochl_day
WHERE symbol = 'VOLT' AND time >= '2026-09-03'
ORDER BY time;

Result:

time (TIMESTAMP)close (DOUBLE)mom3 (DOUBLE)same (DOUBLE)
2026-09-03T00:00:00.000Z176NULLNULL
2026-09-06T00:00:00.000Z180.1NULLNULL
2026-09-07T00:00:00.000Z176.9NULLNULL
2026-09-08T00:00:00.000Z182.46.46.4
2026-09-09T00:00:00.000Z187.37.27.2
2026-09-10T00:00:00.000Z191.214.314.3

(6 rows)

trix

Syntax:

trix(x [, n])
trix(x, n) OVER ([PARTITION BY ...] [ORDER BY ...])

TRIX: the change from one candle to the next, in percent, of a triple-smoothed EMA (the EMA of the EMA of the EMA of the price). The triple smoothing removes the small moves, so TRIX shows only the bigger trend. Above 0 the trend is up, below 0 down. Traders often add a signal line (a 9-candle EMA of TRIX) and watch the crossings.

ArgumentTypeMeaning
xnumberthe price, usually close
nwhole number, 1 or morethe period of the three EMAs; default 30

Example: TRIX 30 of CITY's one-minute candles (the last 5) (sample data: sample)

SELECT time, close, trix30
FROM (SELECT time, close, round(trix(close), 4) AS trix30
      FROM ochl_minutes
      WHERE symbol = 'CITY') t
ORDER BY time DESC
LIMIT 5;

Result:

time (TIMESTAMP)close (DOUBLE)trix30 (DOUBLE)
2026-09-10T09:14:00.000Z504.90.0047
2026-09-10T09:13:00.000Z505.10.005
2026-09-10T09:12:00.000Z504.80.0053
2026-09-10T09:11:00.000Z504.50.0056
2026-09-10T09:10:00.000Z504.60.0059

(5 rows)

Example: TRIX and its signal line: leave the warm-up rows out before the EMA (sample data: sample)

SELECT time, trix15, round(ema(trix15, 9), 4) AS signal
FROM (SELECT time, trix15
      FROM (SELECT time, round(trix(close, 15), 4) AS trix15
            FROM ochl_minutes
            WHERE symbol = 'COAST') a
      WHERE trix15 IS NOT NULL) b
ORDER BY time DESC
LIMIT 5;

Result:

time (TIMESTAMP)trix15 (DOUBLE)signal (DOUBLE)
2026-09-10T09:14:00.000Z-0.0001-0.0035
2026-09-10T09:13:00.000Z-0.0015-0.0044
2026-09-10T09:12:00.000Z-0.0028-0.0051
2026-09-10T09:11:00.000Z-0.0039-0.0057
2026-09-10T09:10:00.000Z-0.0045-0.0061

(5 rows)