ZenQuant.Trend (zen_quant v0.4.0)

Copy Markdown View Source

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

FunctionArityDescriptionParam Kinds
dss_bressert3Calculate DSS Bressert using the published double-smoothed construction.candles: exchange_data, period: value, ema_length: value
stoch_rsi3Normalize Wilder RSI within a caller-selected rolling RSI range.candles: exchange_data, rsi_period: value, stochastic_period: value
rsi2Calculate Wilder's Relative Strength Index from candle closes.candles: exchange_data, period: value
rate_of_change2Calculate close-to-close percentage rate of change.candles: exchange_data, period: value
range_geometry4Measure 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

boundary()

@type boundary() :: %{
  slope: float(),
  intercept: float(),
  start_value: float(),
  end_value: float()
}

A least-squares boundary evaluated at both ends of its range window

geometry()

@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

pivot()

@type pivot() :: %{index: non_neg_integer(), price: float()}

A local high or low, indexed within its requested range window

Functions

dss_bressert(candles, period, ema_length)

@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]
}

range_geometry(candles, windows, pivot_lookback, price)

@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
    }
  }
}

rate_of_change(candles, period)

@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]
}

rsi(candles, period)

@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]
}

stoch_rsi(candles, rsi_period, stochastic_period)

@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]
}