Momentum Indicators

Oscillators and momentum-based indicators for trend and strength analysis.

RSI - Relative Strength Index

Measures momentum by comparing average gains to average losses.

Formula

\[RS = \frac{AvgGain}{AvgLoss}\]
\[RSI = 100 - \frac{100}{1 + RS}\]

Initial averages use simple mean. Subsequent values use Wilder smoothing: $\(AvgGain_t = \frac{AvgGain_{t-1} \times (period-1) + gain_t}{period}\)$

Parameters

Parameter

Type

Default

Range

Description

period

int

14

2-100000

Lookback period

Characteristics

Property

Value

Input

Close price

Output

Single value

Lookback

period

Memory

O(1)

Range

0-100

API Usage

from techkit import RSI

rsi = RSI(period=14)
result = rsi.update(price)
values = rsi.calculate(prices)

# TA-Lib compatible
from techkit import talib_compat as ta
rsi_values = ta.RSI(prices, timeperiod=14)
const tk = require('techkit');
const rsi = tk.rsi(14);
const result = rsi.update(price);
const values = tk.RSI(prices, 14);
techkit::RSI rsi(14);
auto result = rsi.update(price);
tk_indicator rsi = tk_rsi_new(14);
tk_result r = tk_update(rsi, price);
tk_free(rsi);

Trading Usage

Level

Interpretation

> 70

Overbought - potential reversal down

< 30

Oversold - potential reversal up

50

Neutral / trend confirmation

  • Divergence: Price makes new high but RSI doesn’t = bearish divergence

  • Failure swings: RSI breaks previous swing = trend change signal


MACD - Moving Average Convergence Divergence

Trend-following momentum indicator showing relationship between two EMAs.

Formula

\[MACD = EMA(close, fast) - EMA(close, slow)\]
\[Signal = EMA(MACD, signal)\]
\[Histogram = MACD - Signal\]

Parameters

Parameter

Type

Default

Range

Description

fast_period

int

12

2-100000

Fast EMA period

slow_period

int

26

2-100000

Slow EMA period

signal_period

int

9

1-100000

Signal EMA period

Characteristics

Property

Value

Input

Close price

Output

3 values (macd, signal, histogram)

Lookback

slow_period - 1 + signal_period - 1

Memory

O(1)

API Usage

from techkit import MACD

macd = MACD(fast=12, slow=26, signal=9)
result = macd.update(price)
if result.valid:
    print(f"MACD: {result.macd}, Signal: {result.signal}, Hist: {result.histogram}")

# Batch - returns tuple
macd_line, signal_line, histogram = macd.calculate(prices)

# TA-Lib compatible
from techkit import talib_compat as ta
macd, signal, hist = ta.MACD(prices, fastperiod=12, slowperiod=26, signalperiod=9)
const tk = require('techkit');
const macd = tk.macd(12, 26, 9);
const result = macd.update(price);
// result.macd, result.signal, result.histogram

const [macdLine, signalLine, hist] = tk.MACD(prices, 12, 26, 9);
techkit::MACD macd(12, 26, 9);
auto result = macd.update_macd(price);
// result.macd, result.signal, result.histogram
tk_indicator macd = tk_macd_new(12, 26, 9);
tk_macd_result r = tk_macd_update(macd, price);
// r.macd, r.signal, r.histogram
tk_free(macd);

Trading Usage

Signal

Interpretation

MACD crosses above Signal

Bullish

MACD crosses below Signal

Bearish

Histogram increasing

Momentum strengthening

Histogram decreasing

Momentum weakening

MACD crosses zero

Trend change

  • Divergence: Price vs MACD divergence = potential reversal

  • Histogram: Anticipates MACD/Signal crossover


STOCH - Stochastic Oscillator

Compares closing price to price range over a period.

Formula

\[\%K_{raw} = \frac{close - lowest(low, k\_period)}{highest(high, k\_period) - lowest(low, k\_period)} \times 100\]
\[\%K_{slow} = SMA(\%K_{raw}, k\_slow)\]
\[\%D = SMA(\%K_{slow}, d\_period)\]

Parameters

Parameter

Type

Default

Description

k_period

int

14

%K lookback period

k_slow

int

3

%K smoothing period

k_matype

int

0

%K MA type

d_period

int

3

%D smoothing period

d_matype

int

0

%D MA type

Characteristics

Property

Value

Input

OHLCV

Output

2 values (slowk, slowd)

Lookback

k_period - 1 + k_slow - 1 + d_period - 1

Range

0-100

API Usage

from techkit import STOCH

stoch = STOCH(k_period=14, k_slow=3, d_period=3)
result = stoch.update_ohlcv(open, high, low, close, volume)
if result.valid:
    print(f"%K: {result.k}, %D: {result.d}")

slowk, slowd = stoch.calculate(high_arr, low_arr, close_arr)

# TA-Lib compatible
from techkit import talib_compat as ta
slowk, slowd = ta.STOCH(high, low, close, fastk_period=5, slowk_period=3, slowd_period=3)
const { STOCH } = require('techkit');

const stoch = new STOCH({ kPeriod: 14, kSlowPeriod: 3, dPeriod: 3 });
const result = stoch.updateOHLCV({ open, high, low, close, volume });
if (result.valid) {
    console.log(`%K: ${result.k}, %D: ${result.d}`);
}

const { k, d } = stoch.calculate(openArr, highArr, lowArr, closeArr, volumeArr);
#include <techkit/techkit.hpp>

techkit::STOCH stoch(14, 3, 3);
auto result = stoch.update_ohlcv(open, high, low, close, volume);
if (result.valid) {
    std::cout << "%K: " << result.k << ", %D: " << result.d << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator stoch = tk_stoch_new(14, 3, 3);
tk_ohlcv bar = {open, high, low, close, volume};
tk_stoch_result r = tk_stoch_update(stoch, &bar);
if (r.valid) {
    printf("%%K: %f, %%D: %f\n", r.slowk, r.slowd);
}
tk_free(stoch);

Trading Usage

Level

Interpretation

> 80

Overbought

< 20

Oversold

%K crosses %D up

Bullish signal

%K crosses %D down

Bearish signal


ADX - Average Directional Index

Measures trend strength regardless of direction using directional movement.

Formula

\[\begin{split}+DM = \begin{cases} high - prev\_high & \text{if } (high - prev\_high) > (prev\_low - low) \text{ and } (high - prev\_high) > 0 \\ 0 & \text{otherwise} \end{cases}\end{split}\]
\[\begin{split}-DM = \begin{cases} prev\_low - low & \text{if } (prev\_low - low) > (high - prev\_high) \text{ and } (prev\_low - low) > 0 \\ 0 & \text{otherwise} \end{cases}\end{split}\]
\[TR = \max(high - low, |high - prev\_close|, |low - prev\_close|)\]
\[+DI = 100 \times \frac{Wilder\_smooth(+DM)}{Wilder\_smooth(TR)}\]
\[-DI = 100 \times \frac{Wilder\_smooth(-DM)}{Wilder\_smooth(TR)}\]
\[DX = 100 \times \frac{|+DI - -DI|}{+DI + -DI}\]
\[ADX = Wilder\_smooth(DX)\]

Wilder’s smoothing:

  • First smoothed value = sum - sum/period + current

  • Subsequent: smoothed = smoothed - smoothed/period + current

Parameters

Parameter

Type

Default

Range

Description

period

int

14

1-100000

Lookback period for smoothing

Characteristics

Property

Value

Input

OHLCV

Output

3 values (plus_di, minus_di, adx)

Lookback

2 × period - 1

Memory

O(1)

Range

0-100

API Usage

from techkit import ADX

adx = ADX(period=14)
result = adx.update_ohlcv(open, high, low, close, volume)
if result.valid:
    print(f"+DI: {result.plus_di}, -DI: {result.minus_di}, ADX: {result.adx}")

# TA-Lib compatible
from techkit import talib_compat as ta
adx_values = ta.ADX(high, low, close, timeperiod=14)
const tk = require('techkit');
const adx = tk.adx(14);
const result = adx.updateOHLCV({ open, high, low, close, volume });
if (result.valid) {
    console.log(`+DI: ${result.plus_di}, -DI: ${result.minus_di}, ADX: ${result.adx}`);
}

const adxValues = tk.ADX(highArr, lowArr, closeArr, 14);
#include <techkit/techkit.hpp>

techkit::ADX adx(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_adx_result result = adx.update(bar);
if (result.valid) {
    std::cout << "+DI: " << result.plus_di 
              << ", -DI: " << result.minus_di 
              << ", ADX: " << result.adx << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator adx = tk_adx_new(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_adx_result r = tk_adx_update(adx, &bar);
if (r.valid) {
    printf("+DI: %f, -DI: %f, ADX: %f\n", r.plus_di, r.minus_di, r.adx);
}
tk_free(adx);

Trading Usage

Level

Interpretation

ADX > 25

Strong trend - good for trend-following strategies

ADX < 20

Weak/no trend - avoid trend-following strategies

ADX 20-25

Transition zone - trend may be developing

Directional Indicators:

  • +DI > -DI: Uptrend - bullish momentum

  • -DI > +DI: Downtrend - bearish momentum

  • +DI crosses above -DI: Bullish signal

  • -DI crosses above +DI: Bearish signal

Combined Analysis:

  • High ADX (>25) + +DI > -DI = Strong uptrend

  • High ADX (>25) + -DI > +DI = Strong downtrend

  • Low ADX (<20) = Range-bound market, use oscillators instead


Other Momentum Indicators

[Continue with full reference for all 30 momentum indicators…]

Indicator

Function

Description

MOM

MOM(period)

Momentum (close - close[n])

ROC

ROC(period)

Rate of Change %

CCI

CCI(period)

Commodity Channel Index

WILLR

WILLR(period)

Williams %R

APO

APO(fast, slow)

Absolute Price Oscillator

PPO

PPO(fast, slow)

Percentage Price Oscillator

CMO

CMO(period)

Chande Momentum Oscillator

TRIX

TRIX(period)

Triple EMA Rate of Change

ULTOSC

ULTOSC(p1, p2, p3)

Ultimate Oscillator

AROON

AROON(period)

Aroon Up/Down

AROONOSC

AROONOSC(period)

Aroon Oscillator


MOM - Momentum

Simple price change over N periods.

Formula

\[MOM = price_t - price_{t-period}\]

Parameters

Parameter

Type

Default

Range

Description

period

int

10

1-100000

Lookback period

Characteristics

Property

Value

Input

Close price

Output

Single value

Lookback

period

Memory

O(period)

API Usage

from techkit import MOM

mom = MOM(period=10)
result = mom.update(price)
values = mom.calculate(prices)

# TA-Lib compatible
from techkit import talib_compat as ta
mom_values = ta.MOM(prices, timeperiod=10)
const tk = require('techkit');
const mom = tk.mom(10);
const result = mom.update(price);
const values = tk.MOM(prices, 10);
techkit::MOM mom(10);
auto result = mom.update(price);
tk_indicator mom = tk_mom_new(10);
tk_result r = tk_update(mom, price);
tk_free(mom);

Trading Usage

  • Positive: Price rising

  • Negative: Price falling

  • Zero crossing: Trend change

  • Divergence: Price vs momentum divergence signals reversal


ROC - Rate of Change

Percentage change over N periods.

Formula

\[ROC = \frac{price_t - price_{t-period}}{price_{t-period}} \times 100\]

Parameters

Parameter

Type

Default

Range

Description

period

int

10

1-100000

Lookback period

Characteristics

Property

Value

Input

Close price

Output

Single value

Lookback

period

Memory

O(period)

API Usage

from techkit import ROC

roc = ROC(period=10)
result = roc.update(price)
values = roc.calculate(prices)

# TA-Lib compatible
from techkit import talib_compat as ta
roc_values = ta.ROC(prices, timeperiod=10)
const tk = require('techkit');
const roc = tk.roc(10);
const result = roc.update(price);
const values = tk.ROC(prices, 10);
techkit::ROC roc(10);
auto result = roc.update(price);
tk_indicator roc = tk_roc_new(10);
tk_result r = tk_update(roc, price);
tk_free(roc);

Trading Usage

  • Overbought/Oversold: Extreme values suggest reversal

  • Zero line: Crosses indicate momentum shift


ROCP - Rate of Change Percentage

Same as ROC but returns decimal (not multiplied by 100).

Formula

\[ROCP = \frac{price_t - price_{t-period}}{price_{t-period}}\]

Parameters

Parameter

Type

Default

Range

Description

period

int

10

1-100000

Lookback period

Characteristics

Property

Value

Input

Close price

Output

Single value

Lookback

period

Memory

O(period)

API Usage

from techkit import ROCP

rocp = ROCP(period=10)
result = rocp.update(price)
values = rocp.calculate(prices)

# TA-Lib compatible
from techkit import talib_compat as ta
rocp_values = ta.ROCP(prices, timeperiod=10)
const tk = require('techkit');
const rocp = tk.rocp(10);
const result = rocp.update(price);
const values = tk.ROCP(prices, 10);
techkit::ROCP rocp(10);
auto result = rocp.update(price);
tk_indicator rocp = tk_rocp_new(10);
tk_result r = tk_update(rocp, price);
tk_free(rocp);

Trading Usage

  • Positive: Price increased

  • Negative: Price decreased

  • Zero: No change


ROCR - Rate of Change Ratio

Price ratio over N periods.

Formula

\[ROCR = \frac{price_t}{price_{t-period}}\]

Parameters

Parameter

Type

Default

Range

Description

period

int

10

1-100000

Lookback period

Characteristics

Property

Value

Input

Close price

Output

Single value

Lookback

period

Memory

O(period)

API Usage

from techkit import ROCR

rocr = ROCR(period=10)
result = rocr.update(price)
values = rocr.calculate(prices)

# TA-Lib compatible
from techkit import talib_compat as ta
rocr_values = ta.ROCR(prices, timeperiod=10)
const tk = require('techkit');
const rocr = tk.rocr(10);
const result = rocr.update(price);
const values = tk.ROCR(prices, 10);
techkit::ROCR rocr(10);
auto result = rocr.update(price);
tk_indicator rocr = tk_rocr_new(10);
tk_result r = tk_update(rocr, price);
tk_free(rocr);

Trading Usage

  • > 1: Price increased

  • < 1: Price decreased

  • = 1: No change


ROCR100 - Rate of Change Ratio × 100

Formula

\[ROCR100 = \frac{price_t}{price_{t-period}} \times 100\]

Parameters

Parameter

Type

Default

Range

Description

period

int

10

1-100000

Lookback period

Characteristics

Property

Value

Input

Close price

Output

Single value

Lookback

period

Memory

O(period)

API Usage

from techkit import ROCR100

rocr100 = ROCR100(period=10)
result = rocr100.update(price)
values = rocr100.calculate(prices)

# TA-Lib compatible
from techkit import talib_compat as ta
rocr100_values = ta.ROCR100(prices, timeperiod=10)
const tk = require('techkit');
const rocr100 = tk.rocr100(10);
const result = rocr100.update(price);
const values = tk.ROCR100(prices, 10);
techkit::ROCR100 rocr100(10);
auto result = rocr100.update(price);
tk_indicator rocr100 = tk_rocr100_new(10);
tk_result r = tk_update(rocr100, price);
tk_free(rocr100);

Trading Usage

  • > 100: Price increased

  • < 100: Price decreased

  • = 100: No change


MACDEXT - MACD Extended

MACD with configurable MA types for all components.

Parameters

Parameter

Type

Default

Description

fast_period

int

12

Fast MA period

fast_matype

int

0

Fast MA type (0=SMA, 1=EMA…)

slow_period

int

26

Slow MA period

slow_matype

int

0

Slow MA type

signal_period

int

9

Signal MA period

signal_matype

int

0

Signal MA type

MA Type Values

Value

Type

0

SMA

1

EMA

2

WMA

3

DEMA

4

TEMA

5

TRIMA

6

KAMA

7

MAMA

8

T3


MACDFIX - MACD Fixed 12/26

MACD with fixed 12/26 periods, only signal period configurable.

Parameters

Parameter

Type

Default

Description

signal_period

int

9

Signal line period

Fast and slow periods fixed at 12 and 26.


STOCHF - Stochastic Fast

Fast Stochastic without %K smoothing.

Formula

\[Fast\%K = \frac{close - lowest(low, k\_period)}{highest(high, k\_period) - lowest(low, k\_period)} \times 100\]
\[Fast\%D = SMA(Fast\%K, d\_period)\]

Parameters

Parameter

Type

Default

Description

k_period

int

5

%K lookback period

d_period

int

3

%D smoothing period

d_matype

int

0

%D MA type

Characteristics

Property

Value

Input

OHLCV

Output

2 values (fastk, fastd)

Lookback

k_period - 1 + d_period - 1

Range

0-100

API Usage

from techkit import STOCHF

stochf = STOCHF(k_period=5, d_period=3)
result = stochf.update_ohlcv(open, high, low, close, volume)
if result.valid:
    print(f"Fast %K: {result.k}, Fast %D: {result.d}")

fastk, fastd = stochf.calculate(high_arr, low_arr, close_arr)

# TA-Lib compatible
from techkit import talib_compat as ta
fastk, fastd = ta.STOCHF(high, low, close, fastk_period=5, fastd_period=3)
const { STOCHF } = require('techkit');

const stochf = new STOCHF(5, 3);
const result = stochf.updateOHLCV({ open, high, low, close, volume });
if (result.valid) {
    console.log(`Fast %K: ${result.k}, Fast %D: ${result.d}`);
}

const { k, d } = stochf.calculate(openArr, highArr, lowArr, closeArr, volumeArr);
#include <techkit/techkit.hpp>

techkit::STOCHF stochf(5, 3);
auto result = stochf.update_ohlcv(open, high, low, close, volume);
if (result.valid) {
    std::cout << "Fast %K: " << result.k << ", Fast %D: " << result.d << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator stochf = tk_stochf_new(5, 3);
tk_ohlcv bar = {open, high, low, close, volume};
tk_stochf_result r = tk_stochf_update(stochf, &bar);
if (r.valid) {
    printf("Fast %%K: %f, Fast %%D: %f\n", r.fastk, r.fastd);
}
tk_free(stochf);

Trading Usage

Similar to STOCH but more sensitive due to lack of %K smoothing. Faster signals but more prone to false signals.


STOCHRSI - Stochastic RSI

Stochastic formula applied to RSI values instead of price.

Formula

\[RSI\_values = RSI(close, rsi\_period)\]
\[StochRSI = STOCH(RSI\_values, stoch\_period)\]

Parameters

Parameter

Type

Default

Description

rsi_period

int

14

RSI period

stoch_period

int

14

Stochastic period

k_period

int

3

%K smoothing

d_period

int

3

%D smoothing

Characteristics

Property

Value

Input

Close price

Output

2 values (fastk, fastd)

Lookback

rsi_period + stoch_period - 1 + k_period - 1 + d_period - 1

Range

0-100

API Usage

from techkit import STOCHRSI

stochrsi = STOCHRSI(rsi_period=14, stoch_period=14, k_smooth=3, d_period=3)
result = stochrsi.update(close)
if result.valid:
    print(f"StochRSI %K: {result.k}, %D: {result.d}")

k, d = stochrsi.calculate(close_arr)

# TA-Lib compatible
from techkit import talib_compat as ta
fastk, fastd = ta.STOCHRSI(close, timeperiod=14, fastk_period=14, fastd_period=3, fastd_matype=0)
const { STOCHRSI } = require('techkit');

const stochrsi = new STOCHRSI(14, 14, 3, 3);
const result = stochrsi.update(close);
if (result.valid) {
    console.log(`StochRSI %K: ${result.k}, %D: ${result.d}`);
}

const { k, d } = stochrsi.calculate(closeArr);
#include <techkit/techkit.hpp>

techkit::STOCHRSI stochrsi(14, 14, 3, 3);
auto result = stochrsi.update(close);
if (result.valid) {
    std::cout << "StochRSI %K: " << result.k << ", %D: " << result.d << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator stochrsi = tk_stochrsi_new(14, 14, 3, 3);
tk_stochrsi_result r = tk_stochrsi_update(stochrsi, close);
if (r.valid) {
    printf("StochRSI %%K: %f, %%D: %f\n", r.fastk, r.fastd);
}
tk_free(stochrsi);

Trading Usage

More sensitive than standard RSI or Stochastic alone. Combines momentum (RSI) with overbought/oversold levels (Stochastic).

Level

Interpretation

> 80

Overbought

< 20

Oversold

%K crosses %D up

Bullish signal

%K crosses %D down

Bearish signal


ADXR - Average Directional Index Rating

Smoothed version of ADX that averages current ADX with ADX from N periods ago.

Formula

\[ADXR = \frac{ADX_{today} + ADX_{period\_ago}}{2}\]

Where ADX is calculated as in the ADX indicator.

Parameters

Parameter

Type

Default

Range

Description

period

int

14

1-100000

Lookback period for ADX calculation and rating

Characteristics

Property

Value

Input

OHLCV

Output

Single value

Lookback

3 × period - 1

Memory

O(period)

Range

0-100

API Usage

from techkit import ADXR

adxr = ADXR(period=14)
result = adxr.update_ohlcv(open, high, low, close, volume)
if result.valid:
    print(f"ADXR: {result.value}")

# TA-Lib compatible
from techkit import talib_compat as ta
adxr_values = ta.ADXR(high, low, close, timeperiod=14)
const tk = require('techkit');
const adxr = tk.adxr(14);
const result = adxr.updateOHLCV({ open, high, low, close, volume });
if (result.valid) {
    console.log(`ADXR: ${result.value}`);
}

const adxrValues = tk.ADXR(highArr, lowArr, closeArr, 14);
#include <techkit/techkit.hpp>

techkit::ADXR adxr(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result result = adxr.update(bar);
if (result.valid) {
    std::cout << "ADXR: " << result.value << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator adxr = tk_adxr_new(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result r = tk_update_ohlcv(adxr, &bar);
if (r.valid) {
    printf("ADXR: %f\n", r.value);
}
tk_free(adxr);

Trading Usage

ADXR provides a smoother, less volatile measure of trend strength than ADX alone.

Level

Interpretation

> 25

Strong trend confirmed

< 20

Weak trend confirmed

Rising ADXR

Trend strengthening

Falling ADXR

Trend weakening

  • Less sensitive than ADX, filters out noise

  • Better for confirmation of trend strength

  • Use with ADX for trend strength analysis


DX - Directional Movement Index

Raw directional movement index without ADX smoothing. Measures the difference between +DI and -DI.

Formula

\[DX = 100 \times \frac{|+DI - -DI|}{+DI + -DI}\]

Where +DI and -DI are calculated as in ADX.

Parameters

Parameter

Type

Default

Range

Description

period

int

14

1-100000

Lookback period for DI calculation

Characteristics

Property

Value

Input

OHLCV

Output

Single value

Lookback

period

Memory

O(1)

Range

0-100

API Usage

from techkit import DX

dx = DX(period=14)
result = dx.update_ohlcv(open, high, low, close, volume)
if result.valid:
    print(f"DX: {result.value}")

# TA-Lib compatible
from techkit import talib_compat as ta
dx_values = ta.DX(high, low, close, timeperiod=14)
const tk = require('techkit');
const dx = tk.dx(14);
const result = dx.updateOHLCV({ open, high, low, close, volume });
if (result.valid) {
    console.log(`DX: ${result.value}`);
}

const dxValues = tk.DX(highArr, lowArr, closeArr, 14);
#include <techkit/techkit.hpp>

techkit::DX dx(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result result = dx.update(bar);
if (result.valid) {
    std::cout << "DX: " << result.value << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator dx = tk_dx_new(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result r = tk_update_ohlcv(dx, &bar);
if (r.valid) {
    printf("DX: %f\n", r.value);
}
tk_free(dx);

Trading Usage

DX is the raw directional movement index before smoothing into ADX. More volatile than ADX.

  • Higher values: Strong directional movement (either up or down)

  • Lower values: Weak directional movement, ranging market

  • Use ADX instead for most trading applications (ADX is smoothed DX)


PLUS_DI - Plus Directional Indicator

Measures upward directional movement strength relative to true range.

Formula

\[+DI = 100 \times \frac{Wilder\_smooth(+DM)}{Wilder\_smooth(TR)}\]

Where +DM and TR are calculated as in ADX.

Parameters

Parameter

Type

Default

Range

Description

period

int

14

1-100000

Lookback period for smoothing

Characteristics

Property

Value

Input

OHLCV

Output

Single value

Lookback

period

Memory

O(1)

Range

0-100

API Usage

from techkit import PLUS_DI

plus_di = PLUS_DI(period=14)
result = plus_di.update_ohlcv(open, high, low, close, volume)
if result.valid:
    print(f"+DI: {result.value}")

# TA-Lib compatible
from techkit import talib_compat as ta
plus_di_values = ta.PLUS_DI(high, low, close, timeperiod=14)
const tk = require('techkit');
const plusDi = tk.plusDi(14);
const result = plusDi.updateOHLCV({ open, high, low, close, volume });
if (result.valid) {
    console.log(`+DI: ${result.value}`);
}

const plusDiValues = tk.PLUS_DI(highArr, lowArr, closeArr, 14);
#include <techkit/techkit.hpp>

techkit::PLUS_DI plus_di(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result result = plus_di.update(bar);
if (result.valid) {
    std::cout << "+DI: " << result.value << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator plus_di = tk_plus_di_new(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result r = tk_update_ohlcv(plus_di, &bar);
if (r.valid) {
    printf("+DI: %f\n", r.value);
}
tk_free(plus_di);

Trading Usage

+DI measures upward price movement strength.

Condition

Interpretation

+DI > -DI

Uptrend - bullish momentum

+DI crosses above -DI

Bullish signal - trend change to up

+DI rising

Upward momentum increasing

+DI falling

Upward momentum decreasing

  • Use with -DI to determine trend direction

  • Use with ADX to confirm trend strength

  • Higher values indicate stronger upward movement


MINUS_DI - Minus Directional Indicator

Measures downward directional movement strength relative to true range.

Formula

\[-DI = 100 \times \frac{Wilder\_smooth(-DM)}{Wilder\_smooth(TR)}\]

Where -DM and TR are calculated as in ADX.

Parameters

Parameter

Type

Default

Range

Description

period

int

14

1-100000

Lookback period for smoothing

Characteristics

Property

Value

Input

OHLCV

Output

Single value

Lookback

period

Memory

O(1)

Range

0-100

API Usage

from techkit import MINUS_DI

minus_di = MINUS_DI(period=14)
result = minus_di.update_ohlcv(open, high, low, close, volume)
if result.valid:
    print(f"-DI: {result.value}")

# TA-Lib compatible
from techkit import talib_compat as ta
minus_di_values = ta.MINUS_DI(high, low, close, timeperiod=14)
const tk = require('techkit');
const minusDi = tk.minusDi(14);
const result = minusDi.updateOHLCV({ open, high, low, close, volume });
if (result.valid) {
    console.log(`-DI: ${result.value}`);
}

const minusDiValues = tk.MINUS_DI(highArr, lowArr, closeArr, 14);
#include <techkit/techkit.hpp>

techkit::MINUS_DI minus_di(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result result = minus_di.update(bar);
if (result.valid) {
    std::cout << "-DI: " << result.value << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator minus_di = tk_minus_di_new(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result r = tk_update_ohlcv(minus_di, &bar);
if (r.valid) {
    printf("-DI: %f\n", r.value);
}
tk_free(minus_di);

Trading Usage

-DI measures downward price movement strength.

Condition

Interpretation

-DI > +DI

Downtrend - bearish momentum

-DI crosses above +DI

Bearish signal - trend change to down

-DI rising

Downward momentum increasing

-DI falling

Downward momentum decreasing

  • Use with +DI to determine trend direction

  • Use with ADX to confirm trend strength

  • Higher values indicate stronger downward movement


PLUS_DM - Plus Directional Movement

Raw upward directional movement, smoothed using Wilder’s method.

Formula

\[\begin{split}+DM = \begin{cases} high - prev\_high & \text{if } (high - prev\_high) > (prev\_low - low) \text{ and } (high - prev\_high) > 0 \\ 0 & \text{otherwise} \end{cases}\end{split}\]

Smoothed using Wilder’s smoothing:

  • First smoothed value = sum of first period values

  • Subsequent: smoothed = smoothed - smoothed/period + current

Parameters

Parameter

Type

Default

Range

Description

period

int

14

1-100000

Lookback period for smoothing

Characteristics

Property

Value

Input

OHLCV

Output

Single value

Lookback

period - 1

Memory

O(1)

Range

0 to positive infinity

API Usage

from techkit import PLUS_DM

plus_dm = PLUS_DM(period=14)
result = plus_dm.update_ohlcv(open, high, low, close, volume)
if result.valid:
    print(f"+DM: {result.value}")

# TA-Lib compatible
from techkit import talib_compat as ta
plus_dm_values = ta.PLUS_DM(high, low, timeperiod=14)
const tk = require('techkit');
const plusDm = tk.plusDm(14);
const result = plusDm.updateOHLCV({ open, high, low, close, volume });
if (result.valid) {
    console.log(`+DM: ${result.value}`);
}

const plusDmValues = tk.PLUS_DM(highArr, lowArr, 14);
#include <techkit/techkit.hpp>

techkit::PLUS_DM plus_dm(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result result = plus_dm.update(bar);
if (result.valid) {
    std::cout << "+DM: " << result.value << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator plus_dm = tk_plus_dm_new(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result r = tk_update_ohlcv(plus_dm, &bar);
if (r.valid) {
    printf("+DM: %f\n", r.value);
}
tk_free(plus_dm);

Trading Usage

+DM measures the raw upward price movement before normalization.

  • Higher values: Strong upward price movement

  • Lower values: Weak or no upward movement

  • Use +DI instead for most applications (+DI normalizes by true range)

  • Component of ADX system - rarely used standalone


MINUS_DM - Minus Directional Movement

Raw downward directional movement, smoothed using Wilder’s method.

Formula

\[\begin{split}-DM = \begin{cases} prev\_low - low & \text{if } (prev\_low - low) > (high - prev\_high) \text{ and } (prev\_low - low) > 0 \\ 0 & \text{otherwise} \end{cases}\end{split}\]

Smoothed using Wilder’s smoothing:

  • First smoothed value = sum of first period values

  • Subsequent: smoothed = smoothed - smoothed/period + current

Parameters

Parameter

Type

Default

Range

Description

period

int

14

1-100000

Lookback period for smoothing

Characteristics

Property

Value

Input

OHLCV

Output

Single value

Lookback

period - 1

Memory

O(1)

Range

0 to positive infinity

API Usage

from techkit import MINUS_DM

minus_dm = MINUS_DM(period=14)
result = minus_dm.update_ohlcv(open, high, low, close, volume)
if result.valid:
    print(f"-DM: {result.value}")

# TA-Lib compatible
from techkit import talib_compat as ta
minus_dm_values = ta.MINUS_DM(high, low, timeperiod=14)
const tk = require('techkit');
const minusDm = tk.minusDm(14);
const result = minusDm.updateOHLCV({ open, high, low, close, volume });
if (result.valid) {
    console.log(`-DM: ${result.value}`);
}

const minusDmValues = tk.MINUS_DM(highArr, lowArr, 14);
#include <techkit/techkit.hpp>

techkit::MINUS_DM minus_dm(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result result = minus_dm.update(bar);
if (result.valid) {
    std::cout << "-DM: " << result.value << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator minus_dm = tk_minus_dm_new(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result r = tk_update_ohlcv(minus_dm, &bar);
if (r.valid) {
    printf("-DM: %f\n", r.value);
}
tk_free(minus_dm);

Trading Usage

-DM measures the raw downward price movement before normalization.

  • Higher values: Strong downward price movement

  • Lower values: Weak or no downward movement

  • Use -DI instead for most applications (-DI normalizes by true range)

  • Component of ADX system - rarely used standalone


CCI - Commodity Channel Index

Measures deviation of price from its statistical mean using typical price.

Formula

\[TP = \frac{High + Low + Close}{3}\]
\[SMA_{TP} = \frac{1}{period} \sum_{i=0}^{period-1} TP_{t-i}\]
\[MeanDeviation = \frac{1}{period} \sum_{i=0}^{period-1} |TP_{t-i} - SMA_{TP}|\]
\[CCI = \frac{TP - SMA_{TP}}{0.015 \times MeanDeviation}\]

Parameters

Parameter

Type

Default

Range

Description

period

int

20

2-100000

Lookback period

Characteristics

Property

Value

Input

OHLCV (uses typical price)

Output

Single value

Lookback

period - 1

Memory

O(period)

Range

Typically -100 to +100, but unbounded

API Usage

from techkit import CCI

cci = CCI(period=20)
result = cci.update_ohlcv(open, high, low, close, volume)
if result.valid:
    print(f"CCI: {result.value}")

values = cci.calculate(high_arr, low_arr, close_arr)

# TA-Lib compatible
from techkit import talib_compat as ta
cci_values = ta.CCI(high, low, close, timeperiod=20)
const tk = require('techkit');
const cci = tk.cci(20);
const result = cci.updateOHLCV({ open, high, low, close, volume });
if (result.valid) {
    console.log(`CCI: ${result.value}`);
}

const cciValues = tk.CCI(highArr, lowArr, closeArr, 20);
#include <techkit/techkit.hpp>

techkit::CCI cci(20);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result result = cci.update(bar);
if (result.valid) {
    std::cout << "CCI: " << result.value << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator cci = tk_cci_new(20);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result r = tk_update_ohlcv(cci, &bar);
if (r.valid) {
    printf("CCI: %f\n", r.value);
}
tk_free(cci);

Trading Usage

Level

Interpretation

> +100

Overbought - price significantly above mean

< -100

Oversold - price significantly below mean

0

Price at statistical mean

  • Breakouts: CCI > +100 or < -100 indicates strong momentum

  • Reversals: Return from extreme levels may signal reversal

  • Trend confirmation: CCI staying above/below zero confirms trend direction


CMO - Chande Momentum Oscillator

Momentum oscillator similar to RSI but ranges from -100 to +100.

Formula

\[Gain = \max(close - prev\_close, 0)\]
\[Loss = \max(prev\_close - close, 0)\]

Initial period: Use SMA of gains and losses $\(AvgGain = \frac{1}{period} \sum_{i=1}^{period} Gain_i\)\( \)\(AvgLoss = \frac{1}{period} \sum_{i=1}^{period} Loss_i\)$

After warmup: Use Wilder’s smoothing (same as RSI) $\(AvgGain_t = \frac{AvgGain_{t-1} \times (period-1) + Gain_t}{period}\)\( \)\(AvgLoss_t = \frac{AvgLoss_{t-1} \times (period-1) + Loss_t}{period}\)$

\[CMO = 100 \times \frac{AvgGain - AvgLoss}{AvgGain + AvgLoss}\]

Parameters

Parameter

Type

Default

Range

Description

period

int

14

2-100000

Lookback period

Characteristics

Property

Value

Input

Close price

Output

Single value

Lookback

period

Memory

O(1)

Range

-100 to +100

API Usage

from techkit import CMO

cmo = CMO(period=14)
result = cmo.update(close)
if result.valid:
    print(f"CMO: {result.value}")

values = cmo.calculate(close_arr)

# TA-Lib compatible
from techkit import talib_compat as ta
cmo_values = ta.CMO(close, timeperiod=14)
const tk = require('techkit');
const cmo = tk.cmo(14);
const result = cmo.update(close);
if (result.valid) {
    console.log(`CMO: ${result.value}`);
}

const cmoValues = tk.CMO(closeArr, 14);
#include <techkit/techkit.hpp>

techkit::CMO cmo(14);
tk_result result = cmo.update(close);
if (result.valid) {
    std::cout << "CMO: " << result.value << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator cmo = tk_cmo_new(14);
tk_result r = tk_update(cmo, close);
if (r.valid) {
    printf("CMO: %f\n", r.value);
}
tk_free(cmo);

Trading Usage

Level

Interpretation

> +50

Strong upward momentum

< -50

Strong downward momentum

0

Neutral momentum

  • Advantage over RSI: CMO can show negative momentum (below 0)

  • Overbought/Oversold: > +50 or < -50 indicate extreme conditions

  • Zero crossing: Momentum shift signal

  • Divergence: Price vs CMO divergence signals potential reversal


MFI - Money Flow Index

Volume-weighted RSI that incorporates trading volume into momentum calculation.

Formula

\[TP = \frac{High + Low + Close}{3}\]
\[RawMoneyFlow = TP \times Volume\]
\[PositiveMoneyFlow = \sum_{i=0}^{period-1} RawMF_i \text{ where } TP_i > TP_{i-1}\]
\[NegativeMoneyFlow = \sum_{i=0}^{period-1} RawMF_i \text{ where } TP_i < TP_{i-1}\]
\[MoneyFlowRatio = \frac{PositiveMoneyFlow}{NegativeMoneyFlow}\]
\[MFI = 100 - \frac{100}{1 + MoneyFlowRatio}\]

Parameters

Parameter

Type

Default

Range

Description

period

int

14

2-100000

Lookback period

Characteristics

Property

Value

Input

OHLCV

Output

Single value

Lookback

period

Memory

O(period)

Range

0-100

API Usage

from techkit import MFI

mfi = MFI(period=14)
result = mfi.update_ohlcv(open, high, low, close, volume)
if result.valid:
    print(f"MFI: {result.value}")

values = mfi.calculate(high_arr, low_arr, close_arr, volume_arr)

# TA-Lib compatible
from techkit import talib_compat as ta
mfi_values = ta.MFI(high, low, close, volume, timeperiod=14)
const tk = require('techkit');
const mfi = tk.mfi(14);
const result = mfi.updateOHLCV({ open, high, low, close, volume });
if (result.valid) {
    console.log(`MFI: ${result.value}`);
}

const mfiValues = tk.MFI(highArr, lowArr, closeArr, volumeArr, 14);
#include <techkit/techkit.hpp>

techkit::MFI mfi(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result result = mfi.update(bar);
if (result.valid) {
    std::cout << "MFI: " << result.value << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator mfi = tk_mfi_new(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result r = tk_update_ohlcv(mfi, &bar);
if (r.valid) {
    printf("MFI: %f\n", r.value);
}
tk_free(mfi);

Trading Usage

Level

Interpretation

> 80

Overbought - high buying pressure

< 20

Oversold - high selling pressure

50

Neutral

  • Volume confirmation: MFI uses volume, making it more reliable than RSI

  • Divergence: Price makes new high but MFI doesn’t = bearish divergence (distribution)

  • Price makes new low but MFI doesn’t = bullish divergence (accumulation)

  • Use with RSI: MFI confirms RSI signals with volume data


WILLR - Williams %R

Momentum oscillator similar to Stochastic but inverted (ranges -100 to 0).

Formula

\[HighestHigh = \max(high, period)\]
\[LowestLow = \min(low, period)\]
\[WILLR = -100 \times \frac{HighestHigh - Close}{HighestHigh - LowestLow}\]

Parameters

Parameter

Type

Default

Range

Description

period

int

14

2-100000

Lookback period

Characteristics

Property

Value

Input

OHLCV

Output

Single value

Lookback

period - 1

Memory

O(period)

Range

-100 to 0

API Usage

from techkit import WILLR

willr = WILLR(period=14)
result = willr.update_ohlcv(open, high, low, close, volume)
if result.valid:
    print(f"Williams %R: {result.value}")

values = willr.calculate(high_arr, low_arr, close_arr)

# TA-Lib compatible
from techkit import talib_compat as ta
willr_values = ta.WILLR(high, low, close, timeperiod=14)
const tk = require('techkit');
const willr = tk.willr(14);
const result = willr.updateOHLCV({ open, high, low, close, volume });
if (result.valid) {
    console.log(`Williams %R: ${result.value}`);
}

const willrValues = tk.WILLR(highArr, lowArr, closeArr, 14);
#include <techkit/techkit.hpp>

techkit::WILLR willr(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result result = willr.update(bar);
if (result.valid) {
    std::cout << "Williams %R: " << result.value << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator willr = tk_willr_new(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result r = tk_update_ohlcv(willr, &bar);
if (r.valid) {
    printf("Williams %%R: %f\n", r.value);
}
tk_free(willr);

Trading Usage

Level

Interpretation

> -20

Overbought - close near highest high

< -80

Oversold - close near lowest low

-50

Neutral

  • Inverted Stochastic: WILLR = -100 × (1 - Stochastic %K)

  • Overbought/Oversold: More extreme values indicate stronger signals

  • Divergence: Price vs WILLR divergence signals potential reversal

  • Use with Stochastic: Confirms signals from Stochastic oscillator


APO - Absolute Price Oscillator

Measures the absolute difference between two exponential moving averages.

Formula

\[APO = EMA(close, fast\_period) - EMA(close, slow\_period)\]

Parameters

Parameter

Type

Default

Range

Description

fast_period

int

12

2-100000

Fast EMA period

slow_period

int

26

2-100000

Slow EMA period

Characteristics

Property

Value

Input

Close price

Output

Single value

Lookback

slow_period - 1

Memory

O(1)

API Usage

from techkit import APO

apo = APO(fast=12, slow=26)
result = apo.update(close)
if result.valid:
    print(f"APO: {result.value}")

values = apo.calculate(close_arr)

# TA-Lib compatible
from techkit import talib_compat as ta
apo_values = ta.APO(close, fastperiod=12, slowperiod=26)
const tk = require('techkit');
const apo = tk.apo(12, 26);
const result = apo.update(close);
if (result.valid) {
    console.log(`APO: ${result.value}`);
}

const apoValues = tk.APO(closeArr, 12, 26);
#include <techkit/techkit.hpp>

techkit::APO apo(12, 26);
tk_result result = apo.update(close);
if (result.valid) {
    std::cout << "APO: " << result.value << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator apo = tk_apo_new(12, 26);
tk_result r = tk_update(apo, close);
if (r.valid) {
    printf("APO: %f\n", r.value);
}
tk_free(apo);

Trading Usage

Signal

Interpretation

APO > 0

Fast EMA above slow EMA - bullish

APO < 0

Fast EMA below slow EMA - bearish

APO crosses above 0

Bullish crossover

APO crosses below 0

Bearish crossover

Increasing APO

Momentum strengthening

Decreasing APO

Momentum weakening

  • Similar to MACD: APO is the MACD line without signal smoothing

  • Absolute values: Useful for comparing across different price levels

  • Zero crossing: Trend change signal


PPO - Percentage Price Oscillator

Measures the percentage difference between two exponential moving averages.

Formula

\[PPO = 100 \times \frac{EMA(close, fast\_period) - EMA(close, slow\_period)}{EMA(close, slow\_period)}\]

Parameters

Parameter

Type

Default

Range

Description

fast_period

int

12

2-100000

Fast EMA period

slow_period

int

26

2-100000

Slow EMA period

Characteristics

Property

Value

Input

Close price

Output

Single value

Lookback

slow_period - 1

Memory

O(1)

API Usage

from techkit import PPO

ppo = PPO(fast=12, slow=26)
result = ppo.update(close)
if result.valid:
    print(f"PPO: {result.value}")

values = ppo.calculate(close_arr)

# TA-Lib compatible
from techkit import talib_compat as ta
ppo_values = ta.PPO(close, fastperiod=12, slowperiod=26)
const tk = require('techkit');
const ppo = tk.ppo(12, 26);
const result = ppo.update(close);
if (result.valid) {
    console.log(`PPO: ${result.value}`);
}

const ppoValues = tk.PPO(closeArr, 12, 26);
#include <techkit/techkit.hpp>

techkit::PPO ppo(12, 26);
tk_result result = ppo.update(close);
if (result.valid) {
    std::cout << "PPO: " << result.value << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator ppo = tk_ppo_new(12, 26);
tk_result r = tk_update(ppo, close);
if (r.valid) {
    printf("PPO: %f\n", r.value);
}
tk_free(ppo);

Trading Usage

Signal

Interpretation

PPO > 0

Fast EMA above slow EMA - bullish

PPO < 0

Fast EMA below slow EMA - bearish

PPO crosses above 0

Bullish crossover

PPO crosses below 0

Bearish crossover

  • Advantage over APO: Percentage format allows comparison across different securities

  • Normalized: Same percentage value means same relative momentum regardless of price level

  • Use for portfolio analysis: Compare momentum across different stocks


TRIX - Triple Smooth EMA Rate of Change

Momentum oscillator showing the percent rate of change of a triple exponentially smoothed moving average.

Formula

\[EMA1 = EMA(close, period)\]
\[EMA2 = EMA(EMA1, period)\]
\[EMA3 = EMA(EMA2, period)\]
\[TRIX = 100 \times \frac{EMA3_t - EMA3_{t-1}}{EMA3_{t-1}}\]

Parameters

Parameter

Type

Default

Range

Description

period

int

30

2-100000

EMA period for all three smoothing stages

Characteristics

Property

Value

Input

Close price

Output

Single value

Lookback

3 × (period - 1) + 1

Memory

O(1)

API Usage

from techkit import TRIX

trix = TRIX(period=30)
result = trix.update(close)
if result.valid:
    print(f"TRIX: {result.value}")

values = trix.calculate(close_arr)

# TA-Lib compatible
from techkit import talib_compat as ta
trix_values = ta.TRIX(close, timeperiod=30)
const tk = require('techkit');
const trix = tk.trix(30);
const result = trix.update(close);
if (result.valid) {
    console.log(`TRIX: ${result.value}`);
}

const trixValues = tk.TRIX(closeArr, 30);
#include <techkit/techkit.hpp>

techkit::TRIX trix(30);
tk_result result = trix.update(close);
if (result.valid) {
    std::cout << "TRIX: " << result.value << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator trix = tk_trix_new(30);
tk_result r = tk_update(trix, close);
if (r.valid) {
    printf("TRIX: %f\n", r.value);
}
tk_free(trix);

Trading Usage

Signal

Interpretation

TRIX > 0

Upward momentum

TRIX < 0

Downward momentum

TRIX crosses above 0

Bullish signal

TRIX crosses below 0

Bearish signal

  • Smooth indicator: Triple smoothing filters out noise effectively

  • Momentum measurement: Shows rate of change, not absolute level

  • Divergence: Price vs TRIX divergence signals potential reversal

  • Long lookback: Default period 30 makes it less sensitive to short-term fluctuations


ULTOSC - Ultimate Oscillator

Combines three different timeframes of buying pressure to identify overbought/oversold conditions.

Formula

\[BP = Close - \min(Low, PrevClose)\]
\[TR = \max(High, PrevClose) - \min(Low, PrevClose)\]
\[Avg1 = \frac{\sum_{i=0}^{period1-1} BP_{t-i}}{\sum_{i=0}^{period1-1} TR_{t-i}}\]
\[Avg2 = \frac{\sum_{i=0}^{period2-1} BP_{t-i}}{\sum_{i=0}^{period2-1} TR_{t-i}}\]
\[Avg3 = \frac{\sum_{i=0}^{period3-1} BP_{t-i}}{\sum_{i=0}^{period3-1} TR_{t-i}}\]
\[ULTOSC = 100 \times \frac{4 \times Avg1 + 2 \times Avg2 + Avg3}{7}\]

Parameters

Parameter

Type

Default

Range

Description

period1

int

7

1-100000

Short-term period

period2

int

14

1-100000

Medium-term period

period3

int

28

1-100000

Long-term period

Note: Must satisfy period1 < period2 < period3

Characteristics

Property

Value

Input

OHLCV

Output

Single value

Lookback

period3

Memory

O(period3)

Range

0-100

API Usage

from techkit import ULTOSC

ultosc = ULTOSC(period1=7, period2=14, period3=28)
result = ultosc.update_ohlcv(open, high, low, close, volume)
if result.valid:
    print(f"Ultimate Oscillator: {result.value}")

values = ultosc.calculate(high_arr, low_arr, close_arr)

# TA-Lib compatible
from techkit import talib_compat as ta
ultosc_values = ta.ULTOSC(high, low, close, timeperiod1=7, timeperiod2=14, timeperiod3=28)
const tk = require('techkit');
const ultosc = tk.ultosc(7, 14, 28);
const result = ultosc.updateOHLCV({ open, high, low, close, volume });
if (result.valid) {
    console.log(`Ultimate Oscillator: ${result.value}`);
}

const ultoscValues = tk.ULTOSC(highArr, lowArr, closeArr, 7, 14, 28);
#include <techkit/techkit.hpp>

techkit::ULTOSC ultosc(7, 14, 28);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result result = ultosc.update(bar);
if (result.valid) {
    std::cout << "Ultimate Oscillator: " << result.value << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator ultosc = tk_ultosc_new(7, 14, 28);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result r = tk_update_ohlcv(ultosc, &bar);
if (r.valid) {
    printf("Ultimate Oscillator: %f\n", r.value);
}
tk_free(ultosc);

Trading Usage

Level

Interpretation

> 70

Overbought - potential reversal down

< 30

Oversold - potential reversal up

50

Neutral

  • Multi-timeframe: Combines short, medium, and long-term momentum

  • Weighted average: Short-term (4×) has more weight than long-term (1×)

  • Less false signals: Multi-timeframe approach reduces whipsaws

  • Divergence: Price vs ULTOSC divergence signals potential reversal


AROON - Aroon Indicator

Measures how long since the highest high and lowest low occurred within a period.

Formula

\[AroonUp = 100 \times \frac{period - bars\_since\_highest\_high}{period}\]
\[AroonDown = 100 \times \frac{period - bars\_since\_lowest\_low}{period}\]

Parameters

Parameter

Type

Default

Range

Description

period

int

14

2-100000

Lookback period

Characteristics

Property

Value

Input

OHLCV

Output

2 values (aroon_up, aroon_down)

Lookback

period

Memory

O(period)

Range

0-100 for both outputs

API Usage

from techkit import AROON

aroon = AROON(period=14)
result = aroon.update_ohlcv(open, high, low, close, volume)
if result.valid:
    print(f"Aroon Up: {result.up}, Aroon Down: {result.down}")

up, down = aroon.calculate(high_arr, low_arr)

# TA-Lib compatible
from techkit import talib_compat as ta
up, down = ta.AROON(high, low, timeperiod=14)
const tk = require('techkit');
const aroon = tk.aroon(14);
const result = aroon.updateOHLCV({ open, high, low, close, volume });
if (result.valid) {
    console.log(`Aroon Up: ${result.up}, Aroon Down: ${result.down}`);
}

const { up, down } = tk.AROON(highArr, lowArr, 14);
#include <techkit/techkit.hpp>

techkit::AROON aroon(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_aroon_result result = aroon.update(bar);
if (result.valid) {
    std::cout << "Aroon Up: " << result.up 
              << ", Aroon Down: " << result.down << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator aroon = tk_aroon_new(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_aroon_result r = tk_aroon_update(aroon, &bar);
if (r.valid) {
    printf("Aroon Up: %f, Aroon Down: %f\n", r.up, r.down);
}
tk_free(aroon);

Trading Usage

Condition

Interpretation

Aroon Up > 70

Strong uptrend - recent new highs

Aroon Down > 70

Strong downtrend - recent new lows

Aroon Up crosses above Aroon Down

Bullish signal

Aroon Down crosses above Aroon Up

Bearish signal

Both < 50

Consolidation/ranging market

  • Trend strength: High Aroon values indicate strong trends

  • Trend change: Crossovers signal potential trend reversals

  • Time-based: Measures time since extremes, not price levels

  • Use with AROONOSC: Oscillator version simplifies analysis


AROONOSC - Aroon Oscillator

Single-value oscillator derived from Aroon Up and Aroon Down.

Formula

\[AROONOSC = AroonUp - AroonDown\]

Where Aroon Up and Aroon Down are calculated as in AROON indicator.

Parameters

Parameter

Type

Default

Range

Description

period

int

14

2-100000

Lookback period

Characteristics

Property

Value

Input

OHLCV

Output

Single value

Lookback

period

Memory

O(period)

Range

-100 to +100

API Usage

from techkit import AROONOSC

aroonosc = AROONOSC(period=14)
result = aroonosc.update_ohlcv(open, high, low, close, volume)
if result.valid:
    print(f"Aroon Oscillator: {result.value}")

values = aroonosc.calculate(high_arr, low_arr)

# TA-Lib compatible
from techkit import talib_compat as ta
aroonosc_values = ta.AROONOSC(high, low, timeperiod=14)
const tk = require('techkit');
const aroonosc = tk.aroonosc(14);
const result = aroonosc.updateOHLCV({ open, high, low, close, volume });
if (result.valid) {
    console.log(`Aroon Oscillator: ${result.value}`);
}

const aroonoscValues = tk.AROONOSC(highArr, lowArr, 14);
#include <techkit/techkit.hpp>

techkit::AROONOSC aroonosc(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result result = aroonosc.update(bar);
if (result.valid) {
    std::cout << "Aroon Oscillator: " << result.value << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator aroonosc = tk_aroonosc_new(14);
tk_ohlcv bar = {open, high, low, close, volume};
tk_result r = tk_update_ohlcv(aroonosc, &bar);
if (r.valid) {
    printf("Aroon Oscillator: %f\n", r.value);
}
tk_free(aroonosc);

Trading Usage

Level

Interpretation

> 0

Aroon Up > Aroon Down - bullish

< 0

Aroon Down > Aroon Up - bearish

> +50

Strong uptrend

< -50

Strong downtrend

Crosses zero

Trend change signal

  • Simplified Aroon: Single value instead of two

  • Zero crossing: Signals trend changes

  • Extreme values: > +50 or < -50 indicate strong trends

  • Use with AROON: Provides same information in simpler format


BOP - Balance of Power

Measures the relationship between opening and closing prices relative to the trading range.

Formula

\[BOP = \frac{Close - Open}{High - Low}\]

If High == Low (no range), BOP = 0.

Parameters

Parameter

Type

Default

Range

Description

None

-

-

-

Stateless indicator (no parameters)

Characteristics

Property

Value

Input

OHLCV

Output

Single value

Lookback

0 (always valid)

Memory

O(1)

Range

Typically -1 to +1

API Usage

from techkit import BOP

bop = BOP()
result = bop.update_ohlcv(open, high, low, close, volume)
if result.valid:
    print(f"Balance of Power: {result.value}")

values = bop.calculate(open_arr, high_arr, low_arr, close_arr)

# TA-Lib compatible
from techkit import talib_compat as ta
bop_values = ta.BOP(open, high, low, close)
const tk = require('techkit');
const bop = tk.bop();
const result = bop.updateOHLCV({ open, high, low, close, volume });
if (result.valid) {
    console.log(`Balance of Power: ${result.value}`);
}

const bopValues = tk.BOP(openArr, highArr, lowArr, closeArr);
#include <techkit/techkit.hpp>

techkit::BOP bop;
tk_ohlcv bar = {open, high, low, close, volume};
tk_result result = bop.update(bar);
if (result.valid) {
    std::cout << "Balance of Power: " << result.value << std::endl;
}
#include <techkit/techkit_c.h>

tk_indicator bop = tk_bop_new();
tk_ohlcv bar = {open, high, low, close, volume};
tk_result r = tk_update_ohlcv(bop, &bar);
if (r.valid) {
    printf("Balance of Power: %f\n", r.value);
}
tk_free(bop);

Trading Usage

Level

Interpretation

> 0

Close > Open - bullish (buyers in control)

< 0

Close < Open - bearish (sellers in control)

= +1

Close = High, Open = Low - maximum bullish

= -1

Close = Low, Open = High - maximum bearish

= 0

Close = Open or High = Low - neutral

  • Intraday momentum: Shows who controlled the bar (buyers vs sellers)

  • No warmup: Always valid from first bar (stateless)

  • Range normalization: Values normalized by bar range

  • Use with other indicators: Confirms momentum from other oscillators