Range geometry and momentum mechanics over chronologically ordered candles.
Every lookback and smoothing length is supplied by the caller. The functions report quantities only: they do not name chart patterns, apply thresholds, or emit trading signals.
dss_bressert/3 follows the
published ProRealTime construction:
stochastic close position, EMA, normalization of that smoothed series against
its own rolling bounds, then a second EMA. This differs from prose descriptions
that instead smooth separate stochastic numerators and denominators.
Positional OHLCV rows can be converted to the shared candle-map shape with
ZenQuant.Volatility.normalize_candles/1 before calling this module.
API Functions
| Function | Arity | Description | Param Kinds |
|---|---|---|---|
dss_bressert | 3 | Calculate DSS Bressert using the published double-smoothed construction. | candles: exchange_data, period: value, ema_length: value |
stoch_rsi | 3 | Normalize Wilder RSI within a caller-selected rolling RSI range. | candles: exchange_data, rsi_period: value, stochastic_period: value |
rsi | 2 | Calculate Wilder's Relative Strength Index from candle closes. | candles: exchange_data, period: value |
rate_of_change | 2 | Calculate close-to-close percentage rate of change. | candles: exchange_data, period: value |
range_geometry | 4 | Measure pivot-fitted range boundaries for every requested window. | candles: exchange_data, windows: value, pivot_lookback: value, price: value |
Summary
Types
A least-squares boundary evaluated at both ends of its range window
Measured range geometry for one requested window
A local high or low, indexed within its requested range window
Functions
Calculate DSS Bressert using the published double-smoothed construction.
Measure pivot-fitted range boundaries for every requested window.
Calculate close-to-close percentage rate of change.
Calculate Wilder's Relative Strength Index from candle closes.
Normalize Wilder RSI within a caller-selected rolling RSI range.
Types
@type boundary() :: %{ slope: float(), intercept: float(), start_value: float(), end_value: float() }
A least-squares boundary evaluated at both ends of its range window
@type geometry() :: %{ upper_pivots: [pivot()], lower_pivots: [pivot()], upper_boundary: boundary() | nil, lower_boundary: boundary() | nil, upper_slope: float() | nil, lower_slope: float() | nil, converging?: boolean() | nil, width_start: float() | nil, width_end: float() | nil, distance_to_upper: float() | nil, distance_to_lower: float() | nil }
Measured range geometry for one requested window
@type pivot() :: %{index: non_neg_integer(), price: float()}
A local high or low, indexed within its requested range window
Functions
@spec dss_bressert([ZenQuant.Volatility.candle()], pos_integer(), pos_integer()) :: [ float() ]
Calculate DSS Bressert using the published double-smoothed construction.
Parameters
candles- Chronological candle maps with a :close field (exchange_data)period- Caller-selected stochastic and normalization period (value)ema_length- Caller-selected length for both EMA smoothing passes (value)
Returns
Chronological DSS values on a 0-100 scale (list)
Example
[36.2, 48.9, 67.4]# descripex:contract
%{
params: %{
period: %{
description: "Caller-selected stochastic and normalization period",
kind: :value
},
candles: %{
description: "Chronological candle maps with a :close field",
source: "fetch_ohlcv(symbol) |> ZenQuant.Volatility.normalize_candles()",
kind: :exchange_data
},
ema_length: %{
description: "Caller-selected length for both EMA smoothing passes",
kind: :value
}
},
returns: %{
type: :list,
description: "Chronological DSS values on a 0-100 scale"
},
returns_example: [36.2, 48.9, 67.4]
}
@spec range_geometry( [ZenQuant.Volatility.candle()], [pos_integer()], pos_integer(), number() ) :: %{required(pos_integer()) => geometry()} | {:error, {:insufficient_candles, pos_integer()}}
Measure pivot-fitted range boundaries for every requested window.
Parameters
candles- Chronological candle maps with :high and :low fields (exchange_data)windows- Set of trailing window lengths to measure (value)pivot_lookback- Bars required on each side of a strict local high or low (value)price- Price whose absolute distance to each ending boundary is measured (value)
Returns
Map of window to pivots, fitted boundaries, slopes, convergence, widths, and price distances; error if a window exceeds the series (map)
Example
%{
60 => %{
upper_slope: -0.08,
lower_slope: 0.03,
converging?: true,
width_start: 12.4,
width_end: 5.91
}
}Errors
:insufficient_candles
# descripex:contract
%{
params: %{
windows: %{
description: "Set of trailing window lengths to measure",
kind: :value
},
price: %{
description: "Price whose absolute distance to each ending boundary is measured",
kind: :value
},
candles: %{
description: "Chronological candle maps with :high and :low fields",
source: "fetch_ohlcv(symbol) |> ZenQuant.Volatility.normalize_candles()",
kind: :exchange_data
},
pivot_lookback: %{
description: "Bars required on each side of a strict local high or low",
kind: :value
}
},
errors: [:insufficient_candles],
returns: %{
type: :map,
description: "Map of window to pivots, fitted boundaries, slopes, convergence, widths, and price distances; error if a window exceeds the series"
},
returns_example: %{
60 => %{
upper_slope: -0.08,
lower_slope: 0.03,
converging?: true,
width_start: 12.4,
width_end: 5.91
}
}
}
@spec rate_of_change([ZenQuant.Volatility.candle()], pos_integer()) :: [float()]
Calculate close-to-close percentage rate of change.
Parameters
candles- Chronological candle maps with a :close field (exchange_data)period- Caller-selected comparison period (value)
Returns
Chronological percentage rate-of-change values (list)
Example
[2.5, -1.2, 0.8]# descripex:contract
%{
params: %{
period: %{description: "Caller-selected comparison period", kind: :value},
candles: %{
description: "Chronological candle maps with a :close field",
source: "fetch_ohlcv(symbol) |> ZenQuant.Volatility.normalize_candles()",
kind: :exchange_data
}
},
returns: %{
type: :list,
description: "Chronological percentage rate-of-change values"
},
returns_example: [2.5, -1.2, 0.8]
}
@spec rsi([ZenQuant.Volatility.candle()], pos_integer()) :: [float()]
Calculate Wilder's Relative Strength Index from candle closes.
Parameters
candles- Chronological candle maps with a :close field (exchange_data)period- Caller-selected Wilder smoothing period (value)
Returns
Chronological RSI values on a 0-100 scale (list)
Example
[48.3, 51.7, 55.1]# descripex:contract
%{
params: %{
period: %{
description: "Caller-selected Wilder smoothing period",
kind: :value
},
candles: %{
description: "Chronological candle maps with a :close field",
source: "fetch_ohlcv(symbol) |> ZenQuant.Volatility.normalize_candles()",
kind: :exchange_data
}
},
returns: %{
type: :list,
description: "Chronological RSI values on a 0-100 scale"
},
returns_example: [48.3, 51.7, 55.1]
}
@spec stoch_rsi([ZenQuant.Volatility.candle()], pos_integer(), pos_integer()) :: [ float() ]
Normalize Wilder RSI within a caller-selected rolling RSI range.
Parameters
candles- Chronological candle maps with a :close field (exchange_data)rsi_period- Caller-selected Wilder RSI period (value)stochastic_period- Caller-selected RSI normalization period (value)
Returns
Chronological StochRSI values on a 0-100 scale (list)
Example
[18.4, 42.7, 100.0]# descripex:contract
%{
params: %{
candles: %{
description: "Chronological candle maps with a :close field",
source: "fetch_ohlcv(symbol) |> ZenQuant.Volatility.normalize_candles()",
kind: :exchange_data
},
rsi_period: %{
description: "Caller-selected Wilder RSI period",
kind: :value
},
stochastic_period: %{
description: "Caller-selected RSI normalization period",
kind: :value
}
},
returns: %{
type: :list,
description: "Chronological StochRSI values on a 0-100 scale"
},
returns_example: [18.4, 42.7, 100.0]
}