fix(python): critical bug fixes across Python wrapper

This commit is contained in:
Miha Kralj
2026-03-01 21:35:19 -08:00
parent 9c03a5bbbe
commit ce4416d388
40 changed files with 9592 additions and 1397 deletions
+69 -21
View File
@@ -1,30 +1,78 @@
# quantalib (Python NativeAOT wrapper)
# quantalib Python NativeAOT Wrapper
Skeleton package and NativeAOT project scaffolding for the `quantalib` Python wrapper over QuanTAlib.
High-performance Python wrapper for [QuanTAlib](https://github.com/mihakralj/quantalib), a .NET NativeAOT technical analysis library.
## Current status
## Features
This is a **skeleton-only** implementation containing:
- **~391 indicators** across 15 categories: channels, core, cycles, dynamics, errors, filters, momentum, numerics, oscillators, reversals, statistics, trends (FIR & IIR), volatility, volume
- **Zero-copy FFI** — ctypes bridge to pre-compiled NativeAOT shared library
- **NumPy native** — all inputs/outputs are `float64` arrays
- **Optional pandas support** — pass `pd.Series` in, get `pd.Series` out with preserved index
- **pandas-ta compatible** — `quantalib._compat` provides alias mapping for drop-in migration
- NativeAOT project files (`python.csproj`, `Directory.Build.props`)
- Python packaging metadata (`pyproject.toml`)
- Python package layout (`quantalib/`)
- Loader and bridge stubs (`_loader.py`, `_bridge.py`)
- Native artifact placeholders (`quantalib/native/...`)
- Minimal smoke test scaffold (`tests/test_smoke.py`)
- Native export scaffolding (`src/StatusCodes.cs`, `src/ArrayBridge.cs`, `src/Exports.cs`)
## Installation
## Not included yet
```bash
pip install quantalib
```
- Full indicator export implementation
- Full ctypes signatures for all exports
- Indicator wrappers in `indicators.py`
- Complete test matrix and compatibility suite
> **Note:** The NativeAOT shared library (`quantalib_native.dll` / `.so` / `.dylib`) must be present in `quantalib/native/<platform>/`. Pre-built binaries are included in wheel distributions.
## Local dev
## Quick Start
From `python/`:
```python
import numpy as np
import quantalib as qtl
- Create venv and install deps
- Run tests: `pytest`
- Build wheel: `python -m build`
close = np.random.randn(200).cumsum() + 100
# Simple Moving Average
sma = qtl.sma(close, length=20)
# Bollinger Bands (multi-output → tuple or DataFrame)
upper, mid, lower = qtl.bbands(close, length=20, std=2.0)
# With pandas
import pandas as pd
s = pd.Series(close, name="close")
rsi = qtl.rsi(s, length=14) # returns pd.Series with preserved index
```
## Categories
| Category | Module | Examples |
|----------|--------|----------|
| Channels | `channels` | bbands, kchannel, dchannel, aberr |
| Core | `core` | ha, midpoint, avgprice, typprice |
| Cycles | `cycles` | ht_dcperiod, ht_sine, cg, dsp |
| Dynamics | `dynamics` | adx, aroon, ichimoku, supertrend |
| Errors | `errors` | mse, rmse, mae, mape, huber |
| Filters | `filters` | kalman, sgf, hp, butter2, wavelet |
| Momentum | `momentum` | rsi, macd, roc, mom, tsi |
| Numerics | `numerics` | fft, normalize, sigmoid, slope |
| Oscillators | `oscillators` | stoch, cci, fisher, qqe, willr |
| Reversals | `reversals` | psar, pivot, fractals, swings |
| Statistics | `statistics` | zscore, correlation, entropy, linreg |
| Trends FIR | `trends_fir` | sma, wma, hma, alma, trima |
| Trends IIR | `trends_iir` | ema, dema, tema, kama, jma |
| Volatility | `volatility` | atr, bbw, stddev, hv, tr |
| Volume | `volume` | obv, vwma, mfi, cmf, adl |
## Local Development
```bash
cd python/
python -m venv .venv && .venv/Scripts/activate # or source .venv/bin/activate
pip install -e ".[dev]"
pytest
```
### Building the native library
```bash
dotnet publish python.csproj -c Release
```
## License
[MIT](../LICENSE)
+26
View File
@@ -7,8 +7,34 @@ name = "quantalib"
dynamic = ["version"]
description = "High-performance technical analysis wrappers over QuanTAlib NativeAOT"
readme = "README.md"
license = "MIT"
requires-python = ">=3.10"
dependencies = ["numpy>=1.24"]
authors = [
{ name = "QuanTAlib Contributors" },
]
keywords = ["quantitative", "finance", "technical-analysis", "indicators", "nativeaot"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Financial and Insurance Industry",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Office/Business :: Financial :: Investment",
"Topic :: Scientific/Engineering :: Mathematics",
"Typing :: Typed",
]
[project.urls]
Homepage = "https://github.com/mihakralj/quantalib"
Repository = "https://github.com/mihakralj/quantalib"
Documentation = "https://mihakralj.github.io/quantalib/"
Issues = "https://github.com/mihakralj/quantalib/issues"
[project.optional-dependencies]
pandas = ["pandas>=1.5"]
+5
View File
@@ -11,6 +11,11 @@
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DebugSymbols>false</DebugSymbols>
<DebugType>none</DebugType>
</PropertyGroup>
<ItemGroup>
<Compile Include="src\**\*.cs" />
</ItemGroup>
+65 -6
View File
@@ -6,6 +6,9 @@ Usage::
result = qtl.sma(close_array, length=14)
result = qtl.bbands(close_array, length=20, std=2.0)
print(qtl.version) # e.g. "0.8.0"
print(qtl.__version__) # same
"""
from __future__ import annotations
@@ -14,6 +17,26 @@ from pathlib import Path
from ._loader import load_native_library
from . import indicators
from .indicators import * # noqa: F401, F403 — re-export all indicator functions
# Re-export per-category submodules for direct access
from . import ( # noqa: F401
channels,
core,
cycles,
dynamics,
errors,
filters,
momentum,
numerics,
oscillators,
reversals,
statistics,
trends_fir,
trends_iir,
volatility,
volume,
)
from ._compat import ALIASES, get_compat
from ._bridge import (
QtlError,
@@ -26,6 +49,21 @@ from ._bridge import (
__all__ = [
"load_native_library",
"indicators",
"channels",
"core",
"cycles",
"dynamics",
"errors",
"filters",
"momentum",
"numerics",
"oscillators",
"reversals",
"statistics",
"trends_fir",
"trends_iir",
"volatility",
"volume",
"ALIASES",
"get_compat",
"QtlError",
@@ -33,14 +71,35 @@ __all__ = [
"QtlInvalidLengthError",
"QtlInvalidParamError",
"QtlInternalError",
"version",
"__version__",
]
def _resolve_version() -> str:
version_file = Path(__file__).resolve().parents[2] / "lib" / "VERSION"
if version_file.exists():
version = version_file.read_text(encoding="utf-8").strip()
if version:
return version
"""Resolve version from lib/VERSION (dev) or package metadata (installed)."""
# 1. Try repo-local VERSION file (works in dev / editable install)
pkg_dir = Path(__file__).resolve().parent # python/quantalib/
candidates = [
pkg_dir.parents[1] / "lib" / "VERSION", # repo root / lib / VERSION
pkg_dir.parent / "lib" / "VERSION", # python / lib / VERSION (fallback)
pkg_dir / "VERSION", # baked into wheel
]
for vf in candidates:
if vf.is_file():
ver = vf.read_text(encoding="utf-8").strip()
if ver:
return ver
# 2. Fall back to importlib.metadata (pip-installed wheel)
try:
from importlib.metadata import version as _pkg_version
return _pkg_version("quantalib")
except Exception:
pass
return "0.0.0"
__version__ = _resolve_version()
__version__: str = _resolve_version()
version: str = __version__
Binary file not shown.
Binary file not shown.
Binary file not shown.
+441 -179
View File
@@ -1,5 +1,7 @@
"""Low-level ctypes bindings for every quantalib NativeAOT export.
Auto-generated by generate_category_modules.py — DO NOT EDIT.
Each native function is bound via ``_bind`` at module load. If the shared
library was compiled without a particular export the binding is silently
skipped (the corresponding ``HAS_*`` flag stays False).
@@ -66,41 +68,10 @@ _lib = load_native_library()
# Shorthand type aliases
_dp = POINTER(c_double) # double*
_ip = POINTER(c_int) # int*
_lp = POINTER(ctypes.c_long) # long*
_ci = c_int
_cd = c_double
# ---------------------------------------------------------------------------
# ABI signature pattern templates
#
# Pattern A : (src*, n, dst*, period) → single-input + int
# Pattern A2: (src*, n, dst*, alpha) → single-input + double
# Pattern A3: (src*, n, dst*) → single-input no params
# Pattern B : (h*, l*, c*, v*, n, dst*, period) → HLCV + int
# Pattern C : (o*, h*, l*, c*, n, dst*) → OHLC no extra
# Pattern C2: (o*, h*, l*, c*, n, dst*, double) → OHLC + double
# Pattern D : (h*, l*, n, dst*) → HL
# Pattern E : (h*, l*, c*, n, dst*) → HLC
# Pattern F : (actual*, predicted*, n, dst*, period) → dual-input + int
# Pattern G : (src*, vol*, n, dst*) → source+volume
# Pattern G2: (src*, vol*, n, dst*, period) → source+volume+int
# Pattern H : (x*, y*, n, dst*, period) → X+Y + int
# Pattern I : multi-output (various)
# ---------------------------------------------------------------------------
# Common argtypes per pattern
_PA = [_dp, _ci, _dp, _ci] # Pattern A
_PA2 = [_dp, _ci, _dp, _cd] # Pattern A (alpha)
_PA3 = [_dp, _ci, _dp] # Pattern A (no param)
_PB = [_dp, _dp, _dp, _dp, _ci, _dp, _ci] # Pattern B (HLCV)
_PC = [_dp, _dp, _dp, _dp, _ci, _dp] # Pattern C (OHLC)
_PC2 = [_dp, _dp, _dp, _dp, _ci, _dp, _cd] # Pattern C (OHLC+double)
_PD = [_dp, _dp, _ci, _dp] # Pattern D (HL)
_PE = [_dp, _dp, _dp, _ci, _dp] # Pattern E (HLC)
_PF = [_dp, _dp, _ci, _dp, _ci] # Pattern F
_PG = [_dp, _dp, _ci, _dp] # Pattern G
_PG2 = [_dp, _dp, _ci, _dp, _ci] # Pattern G2
_PH = [_dp, _dp, _ci, _dp, _ci] # Pattern H
def _bind(name: str, argtypes: list[object]) -> bool:
"""Bind a single native function. Returns True if found."""
@@ -118,187 +89,478 @@ def _bind(name: str, argtypes: list[object]) -> bool:
HAS_SKELETON = _bind("qtl_skeleton_noop", [_dp, _ci, _dp])
# ═══════════════════════════════════════════════════════════════════════════
# §8.1 Core
# Core (Exports.Generated.cs)
# ═══════════════════════════════════════════════════════════════════════════
HAS_AVGPRICE = _bind("qtl_avgprice", _PC)
HAS_MEDPRICE = _bind("qtl_medprice", _PD)
HAS_TYPPRICE = _bind("qtl_typprice", [_dp, _dp, _dp, _ci, _dp]) # OHL (no close!)
HAS_MIDBODY = _bind("qtl_midbody", [_dp, _dp, _ci, _dp]) # OC
HAS_HA = _bind("qtl_ha", [_dp, _dp, _dp, _dp, _dp, _dp, _dp, _dp, _ci])
HAS_MIDPOINT = _bind("qtl_midpoint", [_dp, _dp, _ci, _ci])
HAS_MIDPRICE = _bind("qtl_midprice", [_dp, _dp, _dp, _ci, _ci])
HAS_WCLPRICE = _bind("qtl_wclprice", [_dp, _dp, _dp, _dp, _ci])
# ── Core (Exports.cs — manual) ──
HAS_AVGPRICE = _bind("qtl_avgprice", [_dp, _dp, _dp, _dp, _ci, _dp])
HAS_MEDPRICE = _bind("qtl_medprice", [_dp, _dp, _ci, _dp])
HAS_TYPPRICE = _bind("qtl_typprice", [_dp, _dp, _dp, _ci, _dp])
HAS_MIDBODY = _bind("qtl_midbody", [_dp, _dp, _ci, _dp])
# ═══════════════════════════════════════════════════════════════════════════
# §8.2 Momentum
# Momentum
# ═══════════════════════════════════════════════════════════════════════════
HAS_RSI = _bind("qtl_rsi", _PA)
HAS_ROC = _bind("qtl_roc", _PA)
HAS_MOM = _bind("qtl_mom", _PA)
HAS_CMO = _bind("qtl_cmo", _PA)
HAS_TSI = _bind("qtl_tsi", [_dp, _ci, _dp, _ci, _ci]) # longP, shortP
HAS_APO = _bind("qtl_apo", [_dp, _ci, _dp, _ci, _ci]) # fast, slow
HAS_BIAS = _bind("qtl_bias", _PA)
HAS_CFO = _bind("qtl_cfo", _PA)
HAS_CFB = _bind("qtl_cfb", [_dp, _ci, _dp, _ip, _ci]) # special
HAS_ASI = _bind("qtl_asi", _PC2) # OHLC + double limit
HAS_BOP = _bind("qtl_bop", [_dp, _dp, _dp, _dp, _dp, _ci])
HAS_CCI = _bind("qtl_cci", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _dp])
HAS_MACD = _bind("qtl_macd", [_dp, _dp, _ci, _ci, _ci])
HAS_PMO = _bind("qtl_pmo", [_dp, _dp, _ci, _ci, _ci, _ci])
HAS_PPO = _bind("qtl_ppo", [_dp, _dp, _ci, _ci, _ci])
HAS_PRS = _bind("qtl_prs", [_dp, _dp, _dp, _ci, _ci])
HAS_ROCP = _bind("qtl_rocp", [_dp, _dp, _ci, _ci])
HAS_ROCR = _bind("qtl_rocr", [_dp, _dp, _ci, _ci])
HAS_SAM = _bind("qtl_sam", [_dp, _dp, _ci, _cd, _ci])
HAS_VEL = _bind("qtl_vel", [_dp, _dp, _ci, _ci])
# ═══════════════════════════════════════════════════════════════════════════
# §8.3 Oscillators
# Oscillators
# ═══════════════════════════════════════════════════════════════════════════
HAS_FISHER = _bind("qtl_fisher", _PA)
HAS_FISHER04 = _bind("qtl_fisher04", _PA)
HAS_DPO = _bind("qtl_dpo", _PA)
HAS_TRIX = _bind("qtl_trix", _PA)
HAS_INERTIA = _bind("qtl_inertia", _PA)
HAS_RSX = _bind("qtl_rsx", _PA)
HAS_ER = _bind("qtl_er", _PA)
HAS_CTI = _bind("qtl_cti", _PA)
HAS_REFLEX = _bind("qtl_reflex", _PA)
HAS_TRENDFLEX = _bind("qtl_trendflex", _PA)
HAS_KRI = _bind("qtl_kri", _PA)
HAS_PSL = _bind("qtl_psl", _PA)
HAS_DECO = _bind("qtl_deco", [_dp, _ci, _dp, _ci, _ci]) # shortP, longP
HAS_DOSC = _bind("qtl_dosc", [_dp, _ci, _dp, _ci, _ci, _ci, _ci]) # rsiP, ema1P, ema2P, sigP
HAS_DYMOI = _bind("qtl_dymoi", [_dp, _ci, _dp, _ci, _ci, _ci, _ci, _ci]) # p1..p5
HAS_CRSI = _bind("qtl_crsi", [_dp, _ci, _dp, _ci, _ci, _ci]) # rsiP, streakP, rankP
HAS_BBB = _bind("qtl_bbb", [_dp, _ci, _dp, _ci, _cd]) # period, mult
HAS_BBI = _bind("qtl_bbi", [_dp, _ci, _dp, _ci, _ci, _ci, _ci]) # p1..p4
HAS_DEM = _bind("qtl_dem", [_dp, _dp, _ci, _dp, _ci]) # high,low,n,dst,period
HAS_BRAR = _bind("qtl_brar", [_dp, _dp, _dp, _dp, _ci, _dp, _dp, _ci]) # OHLC + 2 outputs + period
HAS_AC = _bind("qtl_ac", [_dp, _dp, _dp, _ci, _ci, _ci, _ci])
HAS_AO = _bind("qtl_ao", [_dp, _dp, _dp, _ci, _ci, _ci])
HAS_BBS = _bind("qtl_bbs", [_dp, _dp, _dp, _dp, _ci, _ci, _cd])
HAS_COPPOCK = _bind("qtl_coppock", [_dp, _dp, _ci, _ci, _ci, _ci])
HAS_ERI = _bind("qtl_eri", [_dp, _ci, _ci, _dp])
HAS_FI = _bind("qtl_fi", [_dp, _ci, _ci, _dp])
HAS_GATOR = _bind("qtl_gator", [_dp, _dp, _ci, _ci, _ci, _ci, _ci, _ci, _ci])
HAS_IMI = _bind("qtl_imi", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _dp])
HAS_KDJ = _bind("qtl_kdj", [_dp, _dp, _dp, _dp, _dp, _dp, _ci, _ci, _ci])
HAS_KST = _bind("qtl_kst", [_dp, _dp, _dp, _ci, _ci, _ci, _ci, _ci, _ci, _ci, _ci, _ci, _ci])
HAS_MARKETFI = _bind("qtl_marketfi", [_dp, _dp, _dp, _dp, _ci])
HAS_MSTOCH = _bind("qtl_mstoch", [_dp, _dp, _ci, _ci, _ci, _ci])
HAS_PGO = _bind("qtl_pgo", [_dp, _dp, _dp, _dp, _ci, _ci])
HAS_QQE = _bind("qtl_qqe", [_dp, _dp, _ci, _ci, _ci, _cd])
HAS_REVERSEEMA = _bind("qtl_reverseema", [_dp, _dp, _ci, _ci])
HAS_RVGI = _bind("qtl_rvgi", [_dp, _dp, _dp, _dp, _dp, _dp, _ci, _ci])
HAS_SMI = _bind("qtl_smi", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _ci, _ci, _ci])
HAS_SQUEEZE = _bind("qtl_squeeze", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _cd, _cd])
HAS_STC = _bind("qtl_stc", [_dp, _dp, _ci, _ci, _ci, _ci, _ci, _ci])
HAS_STOCH = _bind("qtl_stoch", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _ci])
HAS_STOCHF = _bind("qtl_stochf", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _ci])
HAS_STOCHRSI = _bind("qtl_stochrsi", [_dp, _dp, _ci, _ci, _ci, _ci, _ci])
HAS_TTMWAVE = _bind("qtl_ttmwave", [_dp, _ci, _dp])
HAS_ULTOSC = _bind("qtl_ultosc", [_dp, _dp, _dp, _dp, _ci, _ci, _ci, _ci])
HAS_WILLR = _bind("qtl_willr", [_dp, _dp, _dp, _dp, _ci, _ci])
# ═══════════════════════════════════════════════════════════════════════════
# §8.4 Trends — FIR
# Trends — FIR
# ═══════════════════════════════════════════════════════════════════════════
HAS_SMA = _bind("qtl_sma", _PA)
HAS_WMA = _bind("qtl_wma", _PA)
HAS_HMA = _bind("qtl_hma", _PA)
HAS_TRIMA = _bind("qtl_trima", _PA)
HAS_SWMA = _bind("qtl_swma", _PA)
HAS_DWMA = _bind("qtl_dwma", _PA)
HAS_BLMA = _bind("qtl_blma", _PA)
HAS_ALMA = _bind("qtl_alma", [_dp, _ci, _dp, _ci, _cd, _cd]) # period, offset, sigma
HAS_LSMA = _bind("qtl_lsma", _PA)
HAS_SGMA = _bind("qtl_sgma", _PA)
HAS_SINEMA = _bind("qtl_sinema", _PA)
HAS_HANMA = _bind("qtl_hanma", _PA)
HAS_PARZEN = _bind("qtl_parzen", _PA)
HAS_TSF = _bind("qtl_tsf", _PA)
HAS_CONV = _bind("qtl_conv", [_dp, _ci, _dp, _dp, _ci]) # src,n,dst,kernel*,kernelLen
HAS_BWMA = _bind("qtl_bwma", [_dp, _ci, _dp, _ci, _ci]) # period, polyOrder
HAS_CRMA = _bind("qtl_crma", [_dp, _ci, _dp, _ci, _cd]) # period, volumeFactor
HAS_SP15 = _bind("qtl_sp15", _PA)
HAS_TUKEY_W = _bind("qtl_tukey_w", _PA)
HAS_RAIN = _bind("qtl_rain", _PA)
HAS_AFIRMA = _bind("qtl_afirma", [_dp, _ci, _dp, _ci, _ci, _ci]) # src,n,dst,period,windowType,useSimd
HAS_FWMA = _bind("qtl_fwma", [_dp, _dp, _ci, _ci])
HAS_GWMA = _bind("qtl_gwma", [_dp, _dp, _ci, _ci, _cd])
HAS_HAMMA = _bind("qtl_hamma", [_dp, _dp, _ci, _ci])
HAS_HEND = _bind("qtl_hend", [_dp, _dp, _ci, _ci, _cd])
HAS_ILRS = _bind("qtl_ilrs", [_dp, _dp, _ci, _ci])
HAS_KAISER = _bind("qtl_kaiser", [_dp, _dp, _ci, _ci, _cd, _cd])
HAS_LANCZOS = _bind("qtl_lanczos", [_dp, _dp, _ci, _ci, _cd])
HAS_NLMA = _bind("qtl_nlma", [_dp, _dp, _ci, _ci])
HAS_NYQMA = _bind("qtl_nyqma", [_dp, _dp, _ci, _ci, _ci])
HAS_PMA = _bind("qtl_pma", [_dp, _dp, _dp, _ci, _ci])
HAS_PWMA = _bind("qtl_pwma", [_dp, _dp, _ci, _ci])
HAS_QRMA = _bind("qtl_qrma", [_dp, _dp, _ci, _ci, _cd])
HAS_RWMA = _bind("qtl_rwma", [_dp, _dp, _dp, _dp, _ci, _ci])
# ═══════════════════════════════════════════════════════════════════════════
# §8.5 Trends — IIR
# Trends — IIR
# ═══════════════════════════════════════════════════════════════════════════
HAS_EMA = _bind("qtl_ema", _PA)
HAS_EMA_ALPHA = _bind("qtl_ema_alpha", _PA2)
HAS_DEMA = _bind("qtl_dema", _PA)
HAS_DEMA_ALPHA = _bind("qtl_dema_alpha", _PA2)
HAS_TEMA = _bind("qtl_tema", _PA)
HAS_LEMA = _bind("qtl_lema", _PA)
HAS_HEMA = _bind("qtl_hema", _PA)
HAS_AHRENS = _bind("qtl_ahrens", _PA)
HAS_DECYCLER = _bind("qtl_decycler", _PA)
HAS_DSMA = _bind("qtl_dsma", [_dp, _ci, _dp, _ci, _cd]) # period, factor
HAS_GDEMA = _bind("qtl_gdema", [_dp, _ci, _dp, _ci, _cd]) # period, factor
HAS_CORAL = _bind("qtl_coral", [_dp, _ci, _dp, _ci, _cd]) # period, friction
HAS_AGC = _bind("qtl_agc", _PA2) # alpha
HAS_CCYC = _bind("qtl_ccyc", _PA2) # alpha
HAS_ADXVMA = _bind("qtl_adxvma", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _dp])
HAS_FRAMA = _bind("qtl_frama", [_dp, _dp, _ci, _ci])
HAS_HOLT = _bind("qtl_holt", [_dp, _dp, _ci, _ci, _cd])
HAS_HTIT = _bind("qtl_htit", [_dp, _dp, _ci])
HAS_HWMA = _bind("qtl_hwma", [_dp, _dp, _ci, _ci])
HAS_JMA = _bind("qtl_jma", [_dp, _dp, _ci, _ci, _ci, _cd])
HAS_KAMA = _bind("qtl_kama", [_dp, _dp, _ci, _ci, _ci, _ci])
HAS_LTMA = _bind("qtl_ltma", [_dp, _dp, _ci, _ci])
HAS_MAMA = _bind("qtl_mama", [_dp, _dp, _cd, _ci, _cd, _dp])
HAS_MAVP = _bind("qtl_mavp", [_dp, _dp, _dp, _ci, _ci, _ci])
HAS_MCNMA = _bind("qtl_mcnma", [_dp, _dp, _ci, _ci])
HAS_MGDI = _bind("qtl_mgdi", [_dp, _dp, _ci, _ci, _cd])
HAS_MMA = _bind("qtl_mma", [_dp, _dp, _ci, _ci])
HAS_NMA = _bind("qtl_nma", [_dp, _dp, _ci, _ci])
HAS_QEMA = _bind("qtl_qema", [_dp, _dp, _ci, _ci])
HAS_REMA = _bind("qtl_rema", [_dp, _dp, _ci, _ci, _cd])
HAS_RGMA = _bind("qtl_rgma", [_dp, _dp, _ci, _ci, _ci])
HAS_RMA = _bind("qtl_rma", [_dp, _dp, _ci, _ci])
HAS_T3 = _bind("qtl_t3", [_dp, _dp, _ci, _ci, _cd])
HAS_TRAMA = _bind("qtl_trama", [_dp, _dp, _ci, _ci])
HAS_VAMA = _bind("qtl_vama", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _ci, _ci, _ci, _ci, _dp])
HAS_VIDYA = _bind("qtl_vidya", [_dp, _dp, _ci, _ci])
HAS_YZVAMA = _bind("qtl_yzvama", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _ci, _ci, _ci, _ci, _dp])
HAS_ZLDEMA = _bind("qtl_zldema", [_dp, _dp, _ci, _ci])
HAS_ZLEMA = _bind("qtl_zlema", [_dp, _dp, _ci, _ci])
HAS_ZLTEMA = _bind("qtl_zltema", [_dp, _dp, _ci, _ci])
# ═══════════════════════════════════════════════════════════════════════════
# §8.6 Channels
# Channels
# ═══════════════════════════════════════════════════════════════════════════
HAS_BBANDS = _bind("qtl_bbands", [_dp, _ci, _dp, _dp, _dp, _ci, _cd]) # src,n, upper,mid,lower, period,mult
HAS_ABBER = _bind("qtl_abber", [_dp, _dp, _dp, _dp, _ci, _ci, _cd]) # src,mid,upper,lower,n,period,mult
HAS_ATRBANDS = _bind("qtl_atrbands", [_dp, _dp, _dp, _ci, _dp, _dp, _dp, _ci, _cd]) # h,l,c,n, upper,mid,lower, period,mult
HAS_APCHANNEL = _bind("qtl_apchannel", [_dp, _dp, _ci, _dp, _dp, _ci]) # h,l,n, upper,lower, period
HAS_ACCBANDS = _bind("qtl_accbands", [_dp, _dp, _dp, _dp, _dp, _dp, _ci, _ci, _cd])
HAS_APZ = _bind("qtl_apz", [_dp, _dp, _dp, _dp, _dp, _ci, _cd, _ci, _dp, _dp, _dp])
HAS_DCHANNEL = _bind("qtl_dchannel", [_dp, _dp, _dp, _dp, _dp, _ci, _ci])
HAS_DECAYCHANNEL = _bind("qtl_decaychannel", [_dp, _dp, _dp, _dp, _dp, _ci, _ci])
HAS_FCB = _bind("qtl_fcb", [_dp, _dp, _dp, _dp, _dp, _ci, _ci])
HAS_JBANDS = _bind("qtl_jbands", [_dp, _dp, _dp, _dp, _ci, _ci, _ci])
HAS_KCHANNEL = _bind("qtl_kchannel", [_dp, _dp, _dp, _dp, _dp, _dp, _ci, _ci, _cd])
HAS_MAENV = _bind("qtl_maenv", [_dp, _dp, _dp, _dp, _ci, _ci, _cd, _ci])
HAS_MMCHANNEL = _bind("qtl_mmchannel", [_dp, _dp, _dp, _dp, _ci, _ci])
HAS_PCHANNEL = _bind("qtl_pchannel", [_dp, _dp, _dp, _dp, _dp, _ci, _ci])
HAS_REGCHANNEL = _bind("qtl_regchannel", [_dp, _dp, _dp, _dp, _ci, _ci, _cd])
HAS_SDCHANNEL = _bind("qtl_sdchannel", [_dp, _dp, _dp, _dp, _ci, _ci, _cd])
HAS_STARCHANNEL = _bind("qtl_starchannel", [_dp, _dp, _dp, _dp, _dp, _dp, _ci, _ci, _cd, _ci])
HAS_STBANDS = _bind("qtl_stbands", [_dp, _dp, _dp, _dp, _dp, _dp, _ci, _ci, _cd])
HAS_TTMLRC = _bind("qtl_ttmlrc", [_dp, _dp, _dp, _dp, _dp, _dp, _ci, _ci])
HAS_UBANDS = _bind("qtl_ubands", [_dp, _dp, _dp, _dp, _ci, _ci, _cd])
HAS_UCHANNEL = _bind("qtl_uchannel", [_dp, _dp, _dp, _dp, _dp, _dp, _ci, _ci, _ci, _cd])
HAS_VWAPBANDS = _bind("qtl_vwapbands", [_dp, _dp, _dp, _dp, _dp, _dp, _dp, _dp, _ci, _cd])
HAS_VWAPSD = _bind("qtl_vwapsd", [_dp, _dp, _dp, _dp, _dp, _dp, _ci, _cd])
# ═══════════════════════════════════════════════════════════════════════════
# §8.7 Volatility
# Volatility
# ═══════════════════════════════════════════════════════════════════════════
HAS_TR = _bind("qtl_tr", _PE) # HLC
HAS_BBW = _bind("qtl_bbw", _PA)
HAS_BBWN = _bind("qtl_bbwn", [_dp, _ci, _dp, _ci, _cd, _ci]) # period, mult, lookback
HAS_BBWP = _bind("qtl_bbwp", [_dp, _ci, _dp, _ci, _cd, _ci]) # period, mult, lookback
HAS_STDDEV = _bind("qtl_stddev", _PA)
HAS_VARIANCE = _bind("qtl_variance", _PA)
HAS_ETHERM = _bind("qtl_etherm", [_dp, _dp, _ci, _dp, _ci]) # high,low,n,dst,period
HAS_CCV = _bind("qtl_ccv", [_dp, _ci, _dp, _ci, _ci]) # shortP, longP
HAS_CV = _bind("qtl_cv", [_dp, _ci, _dp, _ci, _cd, _cd]) # period, minVol, maxVol
HAS_CVI = _bind("qtl_cvi", [_dp, _ci, _dp, _ci, _ci]) # emaPeriod, rocPeriod
HAS_EWMA = _bind("qtl_ewma", [_dp, _ci, _dp, _ci, _ci, _ci]) # period, isPop, annFactor
HAS_ADR = _bind("qtl_adr", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _ci, _dp])
HAS_ATR = _bind("qtl_atr", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _dp])
HAS_ATRN = _bind("qtl_atrn", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _dp])
HAS_GKV = _bind("qtl_gkv", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _ci, _ci])
HAS_HLV = _bind("qtl_hlv", [_dp, _dp, _dp, _ci, _ci, _ci, _ci])
HAS_HV = _bind("qtl_hv", [_dp, _dp, _ci, _ci, _ci, _ci])
HAS_JVOLTY = _bind("qtl_jvolty", [_dp, _dp, _ci, _ci])
HAS_JVOLTYN = _bind("qtl_jvoltyn", [_dp, _dp, _ci, _ci])
HAS_MASSI = _bind("qtl_massi", [_dp, _dp, _ci, _ci, _ci])
HAS_NATR = _bind("qtl_natr", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _dp])
HAS_RSV = _bind("qtl_rsv", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _ci, _ci])
HAS_RV = _bind("qtl_rv", [_dp, _dp, _ci, _ci, _ci, _ci, _ci])
HAS_RVI = _bind("qtl_rvi", [_dp, _dp, _ci, _ci, _ci])
HAS_UI = _bind("qtl_ui", [_dp, _dp, _ci, _ci])
HAS_VOV = _bind("qtl_vov", [_dp, _dp, _ci, _ci, _ci])
HAS_VR = _bind("qtl_vr", [_dp, _dp, _dp, _dp, _ci, _ci])
HAS_YZV = _bind("qtl_yzv", [_dp, _dp, _dp, _dp, _dp, _ci, _ci])
# ═══════════════════════════════════════════════════════════════════════════
# §8.8 Volume
# Volume
# ═══════════════════════════════════════════════════════════════════════════
HAS_OBV = _bind("qtl_obv", _PG) # close,vol,n,dst
HAS_PVT = _bind("qtl_pvt", _PG)
HAS_PVR = _bind("qtl_pvr", _PG)
HAS_VF = _bind("qtl_vf", _PG)
HAS_NVI = _bind("qtl_nvi", _PG)
HAS_PVI = _bind("qtl_pvi", _PG)
HAS_TVI = _bind("qtl_tvi", _PG2) # close,vol,n,dst,period
HAS_PVD = _bind("qtl_pvd", _PG2)
HAS_VWMA = _bind("qtl_vwma", _PG2)
HAS_EVWMA = _bind("qtl_evwma", _PG2)
HAS_EFI = _bind("qtl_efi", _PG2)
HAS_AOBV = _bind("qtl_aobv", [_dp, _dp, _ci, _dp, _dp]) # close,vol,n,obv,signal
HAS_MFI = _bind("qtl_mfi", _PB) # HLCV + period
HAS_CMF = _bind("qtl_cmf", _PB)
HAS_EOM = _bind("qtl_eom", [_dp, _dp, _dp, _ci, _dp, _ci]) # h,l,v,n,dst,period
HAS_PVO = _bind("qtl_pvo", [_dp, _ci, _dp, _dp, _dp, _ci, _ci, _ci]) # vol,n, pvo,signal,hist, fast,slow,signal_p
HAS_ADL = _bind("qtl_adl", [_dp, _dp, _dp, _dp, _dp, _ci])
HAS_ADOSC = _bind("qtl_adosc", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _ci])
HAS_III = _bind("qtl_iii", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _ci])
HAS_KVO = _bind("qtl_kvo", [_dp, _dp, _dp, _dp, _dp, _dp, _ci, _ci, _ci, _ci])
HAS_TWAP = _bind("qtl_twap", [_dp, _dp, _ci, _ci])
HAS_VA = _bind("qtl_va", [_dp, _dp, _dp, _dp, _dp, _ci])
HAS_VO = _bind("qtl_vo", [_dp, _dp, _ci, _ci, _ci])
HAS_VROC = _bind("qtl_vroc", [_dp, _dp, _ci, _ci, _ci])
HAS_VWAD = _bind("qtl_vwad", [_dp, _dp, _dp, _dp, _dp, _ci, _ci])
HAS_VWAP = _bind("qtl_vwap", [_dp, _dp, _dp, _dp, _dp, _ci, _ci])
HAS_WAD = _bind("qtl_wad", [_dp, _dp, _dp, _dp, _dp, _ci])
# ═══════════════════════════════════════════════════════════════════════════
# §8.9 Statistics
# Statistics
# ═══════════════════════════════════════════════════════════════════════════
HAS_ZSCORE = _bind("qtl_zscore", _PA)
HAS_CMA = _bind("qtl_cma", _PA3) # no period
HAS_ENTROPY = _bind("qtl_entropy", _PA)
HAS_CORRELATION = _bind("qtl_correlation", _PH)
HAS_COVARIANCE = _bind("qtl_covariance", [_dp, _dp, _ci, _dp, _ci, _ci]) # x,y,n,dst,period,isSample
HAS_COINTEGRATION = _bind("qtl_cointegration", _PH)
HAS_ACF = _bind("qtl_acf", [_dp, _dp, _ci, _ci, _ci])
HAS_GEOMEAN = _bind("qtl_geomean", [_dp, _dp, _ci, _ci])
HAS_GRANGER = _bind("qtl_granger", [_dp, _dp, _dp, _ci, _ci])
HAS_HARMEAN = _bind("qtl_harmean", [_dp, _dp, _ci, _ci])
HAS_HURST = _bind("qtl_hurst", [_dp, _dp, _ci, _ci])
HAS_IQR = _bind("qtl_iqr", [_dp, _dp, _ci, _ci])
HAS_JB = _bind("qtl_jb", [_dp, _dp, _ci, _ci])
HAS_KENDALL = _bind("qtl_kendall", [_dp, _dp, _dp, _ci, _ci])
HAS_KURTOSIS = _bind("qtl_kurtosis", [_dp, _dp, _ci, _ci, _ci])
HAS_LINREG = _bind("qtl_linreg", [_dp, _dp, _ci, _ci, _ci, _cd])
HAS_MEANDEV = _bind("qtl_meandev", [_dp, _dp, _ci, _ci])
HAS_MEDIAN = _bind("qtl_median", [_dp, _dp, _ci, _ci])
HAS_MODE = _bind("qtl_mode", [_dp, _dp, _ci, _ci])
HAS_PACF = _bind("qtl_pacf", [_dp, _dp, _ci, _ci, _ci])
HAS_PERCENTILE = _bind("qtl_percentile", [_dp, _dp, _ci, _ci, _cd])
HAS_POLYFIT = _bind("qtl_polyfit", [_dp, _dp, _ci, _ci, _ci, _cd])
HAS_QUANTILE = _bind("qtl_quantile", [_dp, _dp, _ci, _ci, _cd])
HAS_SKEW = _bind("qtl_skew", [_dp, _dp, _ci, _ci, _ci])
HAS_SPEARMAN = _bind("qtl_spearman", [_dp, _dp, _dp, _ci, _ci])
HAS_STDERR = _bind("qtl_stderr", [_dp, _dp, _ci, _ci])
HAS_SUM = _bind("qtl_sum", [_dp, _dp, _ci, _ci])
HAS_THEIL = _bind("qtl_theil", [_dp, _dp, _ci, _ci])
HAS_TRIM = _bind("qtl_trim", [_dp, _dp, _ci, _ci, _cd])
HAS_WAVG = _bind("qtl_wavg", [_dp, _dp, _ci, _ci])
HAS_WINS = _bind("qtl_wins", [_dp, _dp, _ci, _ci, _cd])
HAS_ZTEST = _bind("qtl_ztest", [_dp, _dp, _ci, _ci, _cd])
# ═══════════════════════════════════════════════════════════════════════════
# §8.10 Errors
# Errors
# ═══════════════════════════════════════════════════════════════════════════
HAS_MSE = _bind("qtl_mse", _PF)
HAS_RMSE = _bind("qtl_rmse", _PF)
HAS_MAE = _bind("qtl_mae", _PF)
HAS_MAPE = _bind("qtl_mape", _PF)
HAS_HUBER = _bind("qtl_huber", [_dp, _dp, _dp, _ci, _ci, _cd])
HAS_LOGCOSH = _bind("qtl_logcosh", [_dp, _dp, _dp, _ci, _ci])
HAS_MAAPE = _bind("qtl_maape", [_dp, _dp, _dp, _ci, _ci])
HAS_MAPD = _bind("qtl_mapd", [_dp, _dp, _dp, _ci, _ci])
HAS_MASE = _bind("qtl_mase", [_dp, _dp, _dp, _ci, _ci])
HAS_MDAE = _bind("qtl_mdae", [_dp, _dp, _dp, _ci, _ci])
HAS_MDAPE = _bind("qtl_mdape", [_dp, _dp, _dp, _ci, _ci])
HAS_ME = _bind("qtl_me", [_dp, _dp, _dp, _ci, _ci])
HAS_MPE = _bind("qtl_mpe", [_dp, _dp, _dp, _ci, _ci])
HAS_MRAE = _bind("qtl_mrae", [_dp, _dp, _dp, _ci, _ci])
HAS_MSLE = _bind("qtl_msle", [_dp, _dp, _dp, _ci, _ci])
HAS_PSEUDOHUBER = _bind("qtl_pseudohuber", [_dp, _dp, _dp, _ci, _ci, _cd])
HAS_QUANTILELOSS = _bind("qtl_quantileloss", [_dp, _dp, _dp, _ci, _ci, _cd])
HAS_RAE = _bind("qtl_rae", [_dp, _dp, _dp, _ci, _ci])
HAS_RMSLE = _bind("qtl_rmsle", [_dp, _dp, _dp, _ci, _ci])
HAS_RSE = _bind("qtl_rse", [_dp, _dp, _dp, _ci, _ci])
HAS_RSQUARED = _bind("qtl_rsquared", [_dp, _dp, _dp, _ci, _ci])
HAS_SMAPE = _bind("qtl_smape", [_dp, _dp, _dp, _ci, _ci])
HAS_THEILU = _bind("qtl_theilu", [_dp, _dp, _dp, _ci, _ci])
HAS_TUKEYBIWEIGHT = _bind("qtl_tukeybiweight", [_dp, _dp, _dp, _ci, _ci, _cd])
HAS_WMAPE = _bind("qtl_wmape", [_dp, _dp, _dp, _ci, _ci])
HAS_WRMSE = _bind("qtl_wrmse", [_dp, _dp, _dp, _ci, _ci])
# ═══════════════════════════════════════════════════════════════════════════
# §8.11 Filters
# Filters
# ═══════════════════════════════════════════════════════════════════════════
HAS_BESSEL = _bind("qtl_bessel", _PA)
HAS_BUTTER2 = _bind("qtl_butter2", _PA)
HAS_BUTTER3 = _bind("qtl_butter3", _PA)
HAS_CHEBY1 = _bind("qtl_cheby1", _PA)
HAS_CHEBY2 = _bind("qtl_cheby2", _PA)
HAS_ELLIPTIC = _bind("qtl_elliptic", _PA)
HAS_EDCF = _bind("qtl_edcf", _PA)
HAS_BPF = _bind("qtl_bpf", _PA)
HAS_ALAGUERRE = _bind("qtl_alaguerre", [_dp, _ci, _dp, _ci, _ci]) # period, order
HAS_BILATERAL = _bind("qtl_bilateral", [_dp, _ci, _dp, _ci, _cd, _cd]) # period, sigmaS, sigmaR
HAS_BAXTERKING = _bind("qtl_baxterking", [_dp, _ci, _dp, _ci, _ci, _ci]) # period, minP, maxP
HAS_CFITZ = _bind("qtl_cfitz", [_dp, _ci, _dp, _ci, _ci]) # period, bandwidthP
HAS_GAUSS = _bind("qtl_gauss", [_dp, _dp, _ci, _cd])
HAS_HANN = _bind("qtl_hann", [_dp, _dp, _ci, _ci])
HAS_HP = _bind("qtl_hp", [_dp, _dp, _ci, _cd])
HAS_HPF = _bind("qtl_hpf", [_dp, _dp, _ci, _ci])
HAS_KALMAN = _bind("qtl_kalman", [_dp, _dp, _ci, _cd, _cd])
HAS_LAGUERRE = _bind("qtl_laguerre", [_dp, _dp, _ci, _cd])
HAS_LMS = _bind("qtl_lms", [_dp, _dp, _ci, _ci, _cd])
HAS_LOESS = _bind("qtl_loess", [_dp, _dp, _ci, _ci])
HAS_MODF = _bind("qtl_modf", [_dp, _dp, _ci, _ci, _cd, _ci, _cd])
HAS_NOTCH = _bind("qtl_notch", [_dp, _dp, _ci, _ci, _cd])
HAS_NW = _bind("qtl_nw", [_dp, _dp, _ci, _ci, _cd])
HAS_ONEEURO = _bind("qtl_oneeuro", [_dp, _dp, _ci, _cd, _cd, _cd])
HAS_RLS = _bind("qtl_rls", [_dp, _dp, _ci, _ci, _cd])
HAS_RMED = _bind("qtl_rmed", [_dp, _dp, _ci, _ci])
HAS_ROOFING = _bind("qtl_roofing", [_dp, _dp, _ci, _ci, _ci])
HAS_SGF = _bind("qtl_sgf", [_dp, _dp, _ci, _ci, _ci])
HAS_SPBF = _bind("qtl_spbf", [_dp, _dp, _ci, _ci, _ci, _ci])
HAS_SSF2 = _bind("qtl_ssf2", [_dp, _dp, _ci, _ci])
HAS_SSF3 = _bind("qtl_ssf3", [_dp, _dp, _ci, _ci, _cd])
HAS_USF = _bind("qtl_usf", [_dp, _dp, _ci, _ci])
HAS_VOSS = _bind("qtl_voss", [_dp, _dp, _ci, _ci, _ci, _cd])
HAS_WAVELET = _bind("qtl_wavelet", [_dp, _dp, _ci, _ci, _cd])
HAS_WIENER = _bind("qtl_wiener", [_dp, _dp, _ci, _ci, _ci])
# ═══════════════════════════════════════════════════════════════════════════
# §8.12 Cycles
# Cycles
# ═══════════════════════════════════════════════════════════════════════════
HAS_CG = _bind("qtl_cg", _PA)
HAS_DSP = _bind("qtl_dsp", _PA)
HAS_CCOR = _bind("qtl_ccor", _PA)
HAS_EBSW = _bind("qtl_ebsw", [_dp, _ci, _dp, _ci, _ci]) # period, hpPeriod
HAS_EACP = _bind("qtl_eacp", [_dp, _ci, _dp, _ci, _ci, _ci, _ci]) # period, minP, maxP, useMedian
HAS_HOMOD = _bind("qtl_homod", [_dp, _dp, _ci, _cd, _cd])
HAS_HTDCPERIOD = _bind("qtl_htdcperiod", [_dp, _dp, _ci])
HAS_HTDCPHASE = _bind("qtl_htdcphase", [_dp, _dp, _ci])
HAS_HTPHASOR = _bind("qtl_htphasor", [_dp, _dp, _dp, _ci])
HAS_HTSINE = _bind("qtl_htsine", [_dp, _dp, _dp, _ci])
HAS_LUNAR = _bind("qtl_lunar", [_dp, _ci, _dp])
HAS_SOLAR = _bind("qtl_solar", [_dp, _ci, _dp])
HAS_SSFDSP = _bind("qtl_ssfdsp", [_dp, _dp, _ci, _ci])
# ═══════════════════════════════════════════════════════════════════════════
# §8.14 Numerics
# Dynamics
# ═══════════════════════════════════════════════════════════════════════════
HAS_CHANGE = _bind("qtl_change", _PA)
HAS_EXPTRANS = _bind("qtl_exptrans", _PA3) # no period
HAS_BETADIST = _bind("qtl_betadist", [_dp, _ci, _dp, _ci, _cd, _cd]) # period, alpha, beta
HAS_EXPDIST = _bind("qtl_expdist", [_dp, _ci, _dp, _ci, _cd]) # period, lambda
HAS_BINOMDIST = _bind("qtl_binomdist", [_dp, _ci, _dp, _ci, _ci, _ci]) # period, trials, successes
HAS_CWT = _bind("qtl_cwt", [_dp, _ci, _dp, _cd, _cd]) # scale, omega
HAS_DWT = _bind("qtl_dwt", [_dp, _ci, _dp, _ci, _ci]) # period, levels
HAS_ADX = _bind("qtl_adx", [_dp, _dp, _dp, _ci, _ci, _dp])
HAS_ADXR = _bind("qtl_adxr", [_dp, _dp, _dp, _ci, _ci, _dp])
HAS_ALLIGATOR = _bind("qtl_alligator", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _ci, _ci, _ci, _ci, _ci, _dp])
HAS_AMAT = _bind("qtl_amat", [_dp, _dp, _dp, _ci, _ci, _ci])
HAS_AROON = _bind("qtl_aroon", [_dp, _dp, _ci, _ci, _dp])
HAS_AROONOSC = _bind("qtl_aroonosc", [_dp, _dp, _ci, _ci, _dp])
HAS_CHOP = _bind("qtl_chop", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _dp])
HAS_DMX = _bind("qtl_dmx", [_dp, _dp, _dp, _ci, _ci, _dp])
HAS_DX = _bind("qtl_dx", [_dp, _dp, _dp, _ci, _ci, _dp])
HAS_GHLA = _bind("qtl_ghla", [_dp, _dp, _dp, _dp, _ci, _ci])
HAS_HTTRENDMODE = _bind("qtl_httrendmode", [_dp, _dp, _ci])
HAS_ICHIMOKU = _bind("qtl_ichimoku", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _ci, _ci, _ci, _dp, _dp, _dp, _dp, _dp])
HAS_IMPULSE = _bind("qtl_impulse", [_dp, _ci, _ci, _ci, _ci, _ci, _dp])
HAS_PFE = _bind("qtl_pfe", [_dp, _dp, _ci, _ci, _ci])
HAS_QSTICK = _bind("qtl_qstick", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _ci, _dp])
HAS_RAVI = _bind("qtl_ravi", [_dp, _dp, _ci, _ci, _ci])
HAS_SUPER = _bind("qtl_super", [_dp, _dp, _dp, _dp, _dp, _ci, _cd, _ci, _dp])
HAS_TTMSQUEEZE = _bind("qtl_ttmsqueeze", [_dp, _dp, _dp, _dp, _dp, _ci, _cd, _ci, _cd, _ci, _ci, _dp])
HAS_TTMTREND = _bind("qtl_ttmtrend", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _dp])
HAS_VHF = _bind("qtl_vhf", [_dp, _dp, _ci, _ci])
HAS_VORTEX = _bind("qtl_vortex", [_dp, _dp, _dp, _ci, _dp, _ci, _dp])
# ═══════════════════════════════════════════════════════════════════════════
# Numerics
# ═══════════════════════════════════════════════════════════════════════════
HAS_ACCEL = _bind("qtl_accel", [_dp, _dp, _ci])
HAS_FDIST = _bind("qtl_fdist", [_dp, _dp, _ci, _ci, _ci, _ci])
HAS_FFT = _bind("qtl_fft", [_dp, _dp, _ci, _ci, _ci, _ci])
HAS_GAMMADIST = _bind("qtl_gammadist", [_dp, _dp, _ci, _cd, _cd, _ci])
HAS_HIGHEST = _bind("qtl_highest", [_dp, _dp, _ci, _ci])
HAS_IFFT = _bind("qtl_ifft", [_dp, _dp, _ci, _ci, _ci])
HAS_JERK = _bind("qtl_jerk", [_dp, _dp, _ci])
HAS_LINEARTRANS = _bind("qtl_lineartrans", [_dp, _dp, _ci, _cd, _cd])
HAS_LOGNORMDIST = _bind("qtl_lognormdist", [_dp, _dp, _ci, _cd, _cd, _ci])
HAS_LOGTRANS = _bind("qtl_logtrans", [_dp, _dp, _ci])
HAS_LOWEST = _bind("qtl_lowest", [_dp, _dp, _ci, _ci])
HAS_NORMALIZE = _bind("qtl_normalize", [_dp, _dp, _ci, _ci])
HAS_NORMDIST = _bind("qtl_normdist", [_dp, _dp, _ci, _cd, _cd, _ci])
HAS_POISSONDIST = _bind("qtl_poissondist", [_dp, _dp, _ci, _cd, _ci, _ci])
HAS_RELU = _bind("qtl_relu", [_dp, _dp, _ci])
HAS_SIGMOID = _bind("qtl_sigmoid", [_dp, _dp, _ci, _cd, _cd])
HAS_SLOPE = _bind("qtl_slope", [_dp, _dp, _ci])
HAS_SQRTTRANS = _bind("qtl_sqrttrans", [_dp, _dp, _ci])
HAS_TDIST = _bind("qtl_tdist", [_dp, _dp, _ci, _ci, _ci])
HAS_WEIBULLDIST = _bind("qtl_weibulldist", [_dp, _dp, _ci, _cd, _cd, _ci])
# ═══════════════════════════════════════════════════════════════════════════
# Reversals
# ═══════════════════════════════════════════════════════════════════════════
HAS_CHANDELIER = _bind("qtl_chandelier", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _cd])
HAS_CKSTOP = _bind("qtl_ckstop", [_dp, _dp, _dp, _dp, _dp, _ci, _ci, _cd, _ci])
HAS_FRACTALS = _bind("qtl_fractals", [_dp, _dp, _dp, _dp, _ci])
HAS_PIVOT = _bind("qtl_pivot", [_dp, _dp, _dp, _dp, _ci])
HAS_PIVOTCAM = _bind("qtl_pivotcam", [_dp, _dp, _dp, _dp, _ci])
HAS_PIVOTDEM = _bind("qtl_pivotdem", [_dp, _dp, _dp, _dp, _dp, _ci])
HAS_PIVOTEXT = _bind("qtl_pivotext", [_dp, _dp, _dp, _dp, _ci])
HAS_PIVOTFIB = _bind("qtl_pivotfib", [_dp, _dp, _dp, _dp, _ci])
HAS_PIVOTWOOD = _bind("qtl_pivotwood", [_dp, _dp, _dp, _dp, _ci])
HAS_PSAR = _bind("qtl_psar", [_dp, _dp, _dp, _dp, _dp, _ci, _cd, _cd, _cd])
HAS_SWINGS = _bind("qtl_swings", [_dp, _dp, _dp, _dp, _ci, _ci])
HAS_TTMSCALPER = _bind("qtl_ttmscalper", [_dp, _dp, _dp, _dp, _dp, _ci, _ci])
# ── Momentum (Exports.cs — manual) ──
HAS_RSI = _bind("qtl_rsi", [_dp, _ci, _dp, _ci])
HAS_ROC = _bind("qtl_roc", [_dp, _ci, _dp, _ci])
HAS_MOM = _bind("qtl_mom", [_dp, _ci, _dp, _ci])
HAS_CMO = _bind("qtl_cmo", [_dp, _ci, _dp, _ci])
HAS_TSI = _bind("qtl_tsi", [_dp, _ci, _dp, _ci, _ci])
HAS_APO = _bind("qtl_apo", [_dp, _ci, _dp, _ci, _ci])
HAS_BIAS = _bind("qtl_bias", [_dp, _ci, _dp, _ci])
HAS_CFO = _bind("qtl_cfo", [_dp, _ci, _dp, _ci])
HAS_CFB = _bind("qtl_cfb", [_dp, _ci, _dp, _ip, _ci])
HAS_ASI = _bind("qtl_asi", [_dp, _dp, _dp, _dp, _ci, _dp, _cd])
# ── Oscillators (Exports.cs — manual) ──
HAS_FISHER = _bind("qtl_fisher", [_dp, _ci, _dp, _ci])
HAS_FISHER04 = _bind("qtl_fisher04", [_dp, _ci, _dp, _ci])
HAS_DPO = _bind("qtl_dpo", [_dp, _ci, _dp, _ci])
HAS_TRIX = _bind("qtl_trix", [_dp, _ci, _dp, _ci])
HAS_INERTIA = _bind("qtl_inertia", [_dp, _ci, _dp, _ci])
HAS_RSX = _bind("qtl_rsx", [_dp, _ci, _dp, _ci])
HAS_ER = _bind("qtl_er", [_dp, _ci, _dp, _ci])
HAS_CTI = _bind("qtl_cti", [_dp, _ci, _dp, _ci])
HAS_REFLEX = _bind("qtl_reflex", [_dp, _ci, _dp, _ci])
HAS_TRENDFLEX = _bind("qtl_trendflex", [_dp, _ci, _dp, _ci])
HAS_KRI = _bind("qtl_kri", [_dp, _ci, _dp, _ci])
HAS_PSL = _bind("qtl_psl", [_dp, _ci, _dp, _ci])
HAS_DECO = _bind("qtl_deco", [_dp, _ci, _dp, _ci, _ci])
HAS_DOSC = _bind("qtl_dosc", [_dp, _ci, _dp, _ci, _ci, _ci, _ci])
HAS_DYMOI = _bind("qtl_dymoi", [_dp, _ci, _dp, _ci, _ci, _ci, _ci, _ci])
HAS_CRSI = _bind("qtl_crsi", [_dp, _ci, _dp, _ci, _ci, _ci])
HAS_BBB = _bind("qtl_bbb", [_dp, _ci, _dp, _ci, _cd])
HAS_BBI = _bind("qtl_bbi", [_dp, _ci, _dp, _ci, _ci, _ci, _ci])
HAS_DEM = _bind("qtl_dem", [_dp, _dp, _ci, _dp, _ci])
HAS_BRAR = _bind("qtl_brar", [_dp, _dp, _dp, _dp, _ci, _dp, _dp, _ci])
# ── Trends — FIR (Exports.cs — manual) ──
HAS_SMA = _bind("qtl_sma", [_dp, _ci, _dp, _ci])
HAS_WMA = _bind("qtl_wma", [_dp, _ci, _dp, _ci])
HAS_HMA = _bind("qtl_hma", [_dp, _ci, _dp, _ci])
HAS_TRIMA = _bind("qtl_trima", [_dp, _ci, _dp, _ci])
HAS_SWMA = _bind("qtl_swma", [_dp, _ci, _dp, _ci])
HAS_DWMA = _bind("qtl_dwma", [_dp, _ci, _dp, _ci])
HAS_BLMA = _bind("qtl_blma", [_dp, _ci, _dp, _ci])
HAS_ALMA = _bind("qtl_alma", [_dp, _ci, _dp, _ci, _cd, _cd])
HAS_LSMA = _bind("qtl_lsma", [_dp, _ci, _dp, _ci, _ci, _cd])
HAS_SGMA = _bind("qtl_sgma", [_dp, _ci, _dp, _ci])
HAS_SINEMA = _bind("qtl_sinema", [_dp, _ci, _dp, _ci])
HAS_HANMA = _bind("qtl_hanma", [_dp, _ci, _dp, _ci])
HAS_PARZEN = _bind("qtl_parzen", [_dp, _ci, _dp, _ci])
HAS_TSF = _bind("qtl_tsf", [_dp, _ci, _dp, _ci])
HAS_CONV = _bind("qtl_conv", [_dp, _ci, _dp, _dp, _ci])
HAS_BWMA = _bind("qtl_bwma", [_dp, _ci, _dp, _ci, _ci])
HAS_CRMA = _bind("qtl_crma", [_dp, _ci, _dp, _ci, _cd])
HAS_SP15 = _bind("qtl_sp15", [_dp, _ci, _dp, _ci])
HAS_TUKEY_W = _bind("qtl_tukey_w", [_dp, _ci, _dp, _ci])
HAS_RAIN = _bind("qtl_rain", [_dp, _ci, _dp, _ci])
HAS_AFIRMA = _bind("qtl_afirma", [_dp, _ci, _dp, _ci, _ci, _ci])
# ── Trends — IIR (Exports.cs — manual) ──
HAS_EMA = _bind("qtl_ema", [_dp, _ci, _dp, _ci])
HAS_EMA_ALPHA = _bind("qtl_ema_alpha", [_dp, _ci, _dp, _cd])
HAS_DEMA = _bind("qtl_dema", [_dp, _ci, _dp, _ci])
HAS_DEMA_ALPHA = _bind("qtl_dema_alpha", [_dp, _ci, _dp, _cd])
HAS_TEMA = _bind("qtl_tema", [_dp, _ci, _dp, _ci])
HAS_LEMA = _bind("qtl_lema", [_dp, _ci, _dp, _ci])
HAS_HEMA = _bind("qtl_hema", [_dp, _ci, _dp, _ci])
HAS_AHRENS = _bind("qtl_ahrens", [_dp, _ci, _dp, _ci])
HAS_DECYCLER = _bind("qtl_decycler", [_dp, _ci, _dp, _ci])
HAS_DSMA = _bind("qtl_dsma", [_dp, _ci, _dp, _ci, _cd])
HAS_GDEMA = _bind("qtl_gdema", [_dp, _ci, _dp, _ci, _cd])
HAS_CORAL = _bind("qtl_coral", [_dp, _ci, _dp, _ci, _cd])
HAS_AGC = _bind("qtl_agc", [_dp, _ci, _dp, _cd])
HAS_CCYC = _bind("qtl_ccyc", [_dp, _ci, _dp, _cd])
# ── Channels (Exports.cs — manual) ──
HAS_BBANDS = _bind("qtl_bbands", [_dp, _ci, _dp, _dp, _dp, _ci, _cd])
HAS_ATRBANDS = _bind("qtl_atrbands", [_dp, _dp, _dp, _ci, _dp, _dp, _dp, _ci, _cd])
HAS_APCHANNEL = _bind("qtl_apchannel", [_dp, _dp, _ci, _dp, _dp, _cd])
# ── Volatility (Exports.cs — manual) ──
HAS_TR = _bind("qtl_tr", [_dp, _dp, _dp, _ci, _dp])
HAS_BBW = _bind("qtl_bbw", [_dp, _ci, _dp, _ci, _cd])
HAS_BBWN = _bind("qtl_bbwn", [_dp, _ci, _dp, _ci, _cd, _ci])
HAS_BBWP = _bind("qtl_bbwp", [_dp, _ci, _dp, _ci, _cd, _ci])
HAS_STDDEV = _bind("qtl_stddev", [_dp, _ci, _dp, _ci])
HAS_VARIANCE = _bind("qtl_variance", [_dp, _ci, _dp, _ci])
HAS_ETHERM = _bind("qtl_etherm", [_dp, _dp, _ci, _dp, _ci])
HAS_CCV = _bind("qtl_ccv", [_dp, _ci, _dp, _ci, _ci])
HAS_CV = _bind("qtl_cv", [_dp, _ci, _dp, _ci, _cd, _cd])
HAS_CVI = _bind("qtl_cvi", [_dp, _ci, _dp, _ci, _ci])
HAS_EWMA = _bind("qtl_ewma", [_dp, _ci, _dp, _ci, _ci, _ci])
# ── Volume (Exports.cs — manual) ──
HAS_OBV = _bind("qtl_obv", [_dp, _dp, _ci, _dp])
HAS_PVT = _bind("qtl_pvt", [_dp, _dp, _ci, _dp])
HAS_PVR = _bind("qtl_pvr", [_dp, _dp, _ci, _dp])
HAS_VF = _bind("qtl_vf", [_dp, _dp, _ci, _dp])
HAS_NVI = _bind("qtl_nvi", [_dp, _dp, _ci, _dp])
HAS_PVI = _bind("qtl_pvi", [_dp, _dp, _ci, _dp])
HAS_TVI = _bind("qtl_tvi", [_dp, _dp, _ci, _dp, _ci])
HAS_PVD = _bind("qtl_pvd", [_dp, _dp, _ci, _dp, _ci])
HAS_VWMA = _bind("qtl_vwma", [_dp, _dp, _ci, _dp, _ci])
HAS_EVWMA = _bind("qtl_evwma", [_dp, _dp, _ci, _dp, _ci])
HAS_EFI = _bind("qtl_efi", [_dp, _dp, _ci, _dp, _ci])
HAS_AOBV = _bind("qtl_aobv", [_dp, _dp, _ci, _dp, _dp])
HAS_MFI = _bind("qtl_mfi", [_dp, _dp, _dp, _dp, _ci, _dp, _ci])
HAS_CMF = _bind("qtl_cmf", [_dp, _dp, _dp, _dp, _ci, _dp, _ci])
HAS_EOM = _bind("qtl_eom", [_dp, _dp, _dp, _ci, _dp, _ci, _cd])
HAS_PVO = _bind("qtl_pvo", [_dp, _ci, _dp, _dp, _dp, _ci, _ci, _ci])
# ── Statistics (Exports.cs — manual) ──
HAS_ZSCORE = _bind("qtl_zscore", [_dp, _ci, _dp, _ci])
HAS_CMA = _bind("qtl_cma", [_dp, _ci, _dp])
HAS_ENTROPY = _bind("qtl_entropy", [_dp, _ci, _dp, _ci])
HAS_CORRELATION = _bind("qtl_correlation", [_dp, _dp, _ci, _dp, _ci])
HAS_COVARIANCE = _bind("qtl_covariance", [_dp, _dp, _ci, _dp, _ci, _ci])
HAS_COINTEGRATION = _bind("qtl_cointegration", [_dp, _dp, _ci, _dp, _ci])
# ── Errors (Exports.cs — manual) ──
HAS_MSE = _bind("qtl_mse", [_dp, _dp, _ci, _dp, _ci])
HAS_RMSE = _bind("qtl_rmse", [_dp, _dp, _ci, _dp, _ci])
HAS_MAE = _bind("qtl_mae", [_dp, _dp, _ci, _dp, _ci])
HAS_MAPE = _bind("qtl_mape", [_dp, _dp, _ci, _dp, _ci])
# ── Filters (Exports.cs — manual) ──
HAS_BESSEL = _bind("qtl_bessel", [_dp, _ci, _dp, _ci])
HAS_BUTTER2 = _bind("qtl_butter2", [_dp, _ci, _dp, _ci, _cd])
HAS_BUTTER3 = _bind("qtl_butter3", [_dp, _ci, _dp, _ci, _cd])
HAS_CHEBY1 = _bind("qtl_cheby1", [_dp, _ci, _dp, _ci, _cd])
HAS_CHEBY2 = _bind("qtl_cheby2", [_dp, _ci, _dp, _ci, _cd])
HAS_ELLIPTIC = _bind("qtl_elliptic", [_dp, _ci, _dp, _ci])
HAS_EDCF = _bind("qtl_edcf", [_dp, _ci, _dp, _ci])
HAS_BPF = _bind("qtl_bpf", [_dp, _ci, _dp, _ci, _ci])
HAS_ALAGUERRE = _bind("qtl_alaguerre", [_dp, _ci, _dp, _ci, _ci])
HAS_BILATERAL = _bind("qtl_bilateral", [_dp, _ci, _dp, _ci, _cd, _cd])
HAS_BAXTERKING = _bind("qtl_baxterking", [_dp, _ci, _dp, _ci, _ci, _ci])
HAS_CFITZ = _bind("qtl_cfitz", [_dp, _ci, _dp, _ci, _ci])
# ── Cycles (Exports.cs — manual) ──
HAS_CG = _bind("qtl_cg", [_dp, _ci, _dp, _ci])
HAS_DSP = _bind("qtl_dsp", [_dp, _ci, _dp, _ci])
HAS_CCOR = _bind("qtl_ccor", [_dp, _ci, _dp, _ci, _cd])
HAS_EBSW = _bind("qtl_ebsw", [_dp, _ci, _dp, _ci, _ci])
HAS_EACP = _bind("qtl_eacp", [_dp, _ci, _dp, _ci, _ci, _ci, _ci])
# ── Numerics (Exports.cs — manual) ──
HAS_CHANGE = _bind("qtl_change", [_dp, _ci, _dp, _ci])
HAS_EXPTRANS = _bind("qtl_exptrans", [_dp, _ci, _dp])
HAS_BETADIST = _bind("qtl_betadist", [_dp, _ci, _dp, _ci, _cd, _cd])
HAS_EXPDIST = _bind("qtl_expdist", [_dp, _ci, _dp, _ci, _cd])
HAS_BINOMDIST = _bind("qtl_binomdist", [_dp, _ci, _dp, _ci, _ci, _ci])
HAS_CWT = _bind("qtl_cwt", [_dp, _ci, _dp, _cd, _cd])
HAS_DWT = _bind("qtl_dwt", [_dp, _ci, _dp, _ci, _ci])
+236
View File
@@ -0,0 +1,236 @@
"""Shared wrapper helpers for quantalib indicator modules.
Auto-generated by generate_category_modules.py — DO NOT EDIT.
"""
from __future__ import annotations
import numpy as np
from numpy.typing import NDArray
from ._bridge import _lib, _check, _dp, _ci, _cd
# Optional pandas support
try:
import pandas as pd # type: ignore[import-untyped]
except ImportError: # pragma: no cover
pd = None # type: ignore[assignment]
# ---------------------------------------------------------------------------
# Internal helpers
# ---------------------------------------------------------------------------
_F64 = np.float64
def _arr(x: object) -> tuple[NDArray[np.float64], object]:
"""Return (contiguous float64 array, original_index_or_None)."""
if x is None:
raise ValueError("Input array must not be None")
idx = None
if pd is not None and isinstance(x, pd.Series):
idx = x.index
x = x.to_numpy(dtype=_F64, copy=False)
elif pd is not None and isinstance(x, pd.DataFrame):
idx = x.index
x = x.iloc[:, 0].to_numpy(dtype=_F64, copy=False)
arr = np.asarray(x, dtype=_F64)
if not arr.flags["C_CONTIGUOUS"]:
arr = np.ascontiguousarray(arr)
if arr.ndim == 0 or len(arr) == 0:
raise ValueError("Input array must not be empty")
return arr, idx
def _ptr(a: NDArray[np.float64]): # noqa: ANN202
"""Get ctypes double* from array."""
return a.ctypes.data_as(_dp)
def _out(n: int) -> NDArray[np.float64]:
"""Allocate output array."""
return np.empty(n, dtype=_F64)
def _offset(arr: NDArray[np.float64], off: int) -> NDArray[np.float64]:
"""Apply offset (roll + NaN fill)."""
if off != 0:
arr = np.roll(arr, off)
if off > 0:
arr[:off] = np.nan
else:
arr[off:] = np.nan
return arr
def _wrap(
arr: NDArray[np.float64],
idx: object,
name: str,
category: str,
offset: int = 0,
):
"""Wrap result: apply offset, optionally convert to pd.Series."""
arr = _offset(arr, offset)
if idx is not None and pd is not None:
s = pd.Series(arr, index=idx, name=name)
s.attrs["category"] = category
return s
return arr
def _wrap_multi(
arrays: dict[str, NDArray[np.float64]],
idx: object,
category: str,
offset: int = 0,
):
"""Wrap multi-output result into tuple or DataFrame."""
for k in arrays:
arrays[k] = _offset(arrays[k], offset)
if idx is not None and pd is not None:
df = pd.DataFrame(arrays, index=idx)
df.attrs["category"] = category
return df
return tuple(arrays.values())
# ═══════════════════════════════════════════════════════════════════════════
# Generic pattern helpers
# ═══════════════════════════════════════════════════════════════════════════
def _pa(
fn_name: str, close: object, length: int, offset: int,
default_length: int, label: str, category: str,
) -> object:
"""Generic Pattern A wrapper: single-input + period."""
length = int(length) if length is not None else default_length
offset = int(offset) if offset is not None else 0
src, idx = _arr(close)
n = len(src)
dst = _out(n)
_check(getattr(_lib, fn_name)(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"{label}_{length}", category, offset)
def _pa3(
fn_name: str, close: object, offset: int,
label: str, category: str,
) -> object:
"""Generic Pattern A3 wrapper: single-input, no params."""
offset = int(offset) if offset is not None else 0
src, idx = _arr(close)
n = len(src)
dst = _out(n)
_check(getattr(_lib, fn_name)(_ptr(src), n, _ptr(dst)))
return _wrap(dst, idx, label, category, offset)
def _pf(
fn_name: str, actual: object, predicted: object,
length: int, offset: int, default_length: int,
label: str, category: str,
) -> object:
"""Generic Pattern F wrapper: actual+predicted+period."""
length = int(length) if length is not None else default_length
offset = int(offset) if offset is not None else 0
a, idx = _arr(actual)
p, _ = _arr(predicted)
n = len(a)
dst = _out(n)
_check(getattr(_lib, fn_name)(_ptr(a), _ptr(p), n, _ptr(dst), length))
return _wrap(dst, idx, f"{label}_{length}", category, offset)
def _pg(
fn_name: str, close: object, volume: object,
offset: int, label: str, category: str,
) -> object:
"""Pattern G: source+volume, no period."""
offset = int(offset) if offset is not None else 0
c, idx = _arr(close)
v, _ = _arr(volume)
n = len(c)
dst = _out(n)
_check(getattr(_lib, fn_name)(_ptr(c), _ptr(v), n, _ptr(dst)))
return _wrap(dst, idx, label, category, offset)
def _pg2(
fn_name: str, close: object, volume: object, length: int,
offset: int, default_length: int, label: str, category: str,
) -> object:
"""Pattern G2: source+volume+period."""
length = int(length) if length is not None else default_length
offset = int(offset) if offset is not None else 0
c, idx = _arr(close)
v, _ = _arr(volume)
n = len(c)
dst = _out(n)
_check(getattr(_lib, fn_name)(_ptr(c), _ptr(v), n, _ptr(dst), length))
return _wrap(dst, idx, f"{label}_{length}", category, offset)
def _ph(
fn_name: str, x: object, y: object, length: int,
offset: int, default_length: int, label: str, category: str,
) -> object:
"""Pattern H: X+Y+period."""
length = int(length) if length is not None else default_length
offset = int(offset) if offset is not None else 0
xarr, idx = _arr(x)
yarr, _ = _arr(y)
n = len(xarr)
dst = _out(n)
_check(getattr(_lib, fn_name)(_ptr(xarr), _ptr(yarr), n, _ptr(dst), length))
return _wrap(dst, idx, f"{label}_{length}", category, offset)
def _ohlcv_bars_period(
fn_name: str, open: object, high: object, low: object,
close: object, volume: object, period: int,
offset: int, default_period: int, label: str, category: str,
) -> object:
"""OHLCV bars + period → single output (BuildBars pattern)."""
period = int(period) if period is not None else default_period
offset = int(offset) if offset is not None else 0
o, idx = _arr(open)
h, _ = _arr(high)
l, _ = _arr(low)
c, _ = _arr(close)
v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(getattr(_lib, fn_name)(
_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), period, n, _ptr(dst)))
return _wrap(dst, idx, f"{label}_{period}", category, offset)
def _hlc_period(
fn_name: str, high: object, low: object, close: object,
period: int, offset: int, default_period: int,
label: str, category: str,
) -> object:
"""HLC + period → single output."""
period = int(period) if period is not None else default_period
offset = int(offset) if offset is not None else 0
h, idx = _arr(high)
l, _ = _arr(low)
c, _ = _arr(close)
n = len(h)
dst = _out(n)
_check(getattr(_lib, fn_name)(
_ptr(h), _ptr(l), _ptr(c), period, n, _ptr(dst)))
return _wrap(dst, idx, f"{label}_{period}", category, offset)
def _src_period(
fn_name: str, source: object, period: int,
offset: int, default_period: int, label: str, category: str,
) -> object:
"""source + period → single output (BuildSeries pattern, src,period,n,dst)."""
period = int(period) if period is not None else default_period
offset = int(offset) if offset is not None else 0
src, idx = _arr(source)
n = len(src)
dst = _out(n)
_check(getattr(_lib, fn_name)(_ptr(src), period, n, _ptr(dst)))
return _wrap(dst, idx, f"{label}_{period}", category, offset)
+352
View File
@@ -0,0 +1,352 @@
"""quantalib channels indicators.
Auto-generated — DO NOT EDIT.
"""
from __future__ import annotations
from ._helpers import _arr, _ptr, _out, _wrap, _wrap_multi, _check, _lib
__all__ = [
"aberr",
"accbands",
"apchannel",
"apz",
"atrbands",
"bbands",
"dchannel",
"decaychannel",
"fcb",
"jbands",
"kchannel",
"maenv",
"mmchannel",
"pchannel",
"regchannel",
"sdchannel",
"starchannel",
"stbands",
"ttm_lrc",
"ubands",
"uchannel",
"vwapbands",
"vwapsd",
]
def aberr(close: object, period: int = 14, multiplier: float = 2.0, offset: int = 0, **kwargs) -> object:
"""Aberration Bands."""
period = int(period)
multiplier = float(multiplier)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
middle = _out(n)
upper = _out(n)
lower = _out(n)
_check(_lib.qtl_abber(_ptr(src), _ptr(middle), _ptr(upper), _ptr(lower), n, period, multiplier))
return _wrap_multi({"middle": middle, "upper": upper, "lower": lower}, idx, "channels", offset)
def accbands(high: object, low: object, close: object, period: int = 14, factor: float = 2.0, offset: int = 0, **kwargs) -> object:
"""Acceleration Bands."""
period = int(period)
factor = float(factor)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
middle = _out(n)
upper = _out(n)
lower = _out(n)
_check(_lib.qtl_accbands(_ptr(h), _ptr(l), _ptr(c), _ptr(middle), _ptr(upper), _ptr(lower), n, period, factor))
return _wrap_multi({"middle": middle, "upper": upper, "lower": lower}, idx, "channels", offset)
def apz(open: object, high: object, low: object, close: object, volume: object, period: int = 14, multiplier: float = 2.0, offset: int = 0, **kwargs) -> object:
"""Adaptive Price Zone."""
period = int(period)
multiplier = float(multiplier)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dstMiddle = _out(n)
dstUpper = _out(n)
dstLower = _out(n)
_check(_lib.qtl_apz(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), period, multiplier, n, _ptr(dstMiddle), _ptr(dstUpper), _ptr(dstLower)))
return _wrap_multi({"dstMiddle": dstMiddle, "dstUpper": dstUpper, "dstLower": dstLower}, idx, "channels", offset)
def dchannel(high: object, low: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Donchian Channel."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low)
n = len(h)
middle = _out(n)
upper = _out(n)
lower = _out(n)
_check(_lib.qtl_dchannel(_ptr(h), _ptr(l), _ptr(middle), _ptr(upper), _ptr(lower), n, period))
return _wrap_multi({"middle": middle, "upper": upper, "lower": lower}, idx, "channels", offset)
def decaychannel(high: object, low: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Decay Channel."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low)
n = len(h)
middle = _out(n)
upper = _out(n)
lower = _out(n)
_check(_lib.qtl_decaychannel(_ptr(h), _ptr(l), _ptr(middle), _ptr(upper), _ptr(lower), n, period))
return _wrap_multi({"middle": middle, "upper": upper, "lower": lower}, idx, "channels", offset)
def fcb(high: object, low: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Fractal Chaos Bands."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low)
n = len(h)
middle = _out(n)
upper = _out(n)
lower = _out(n)
_check(_lib.qtl_fcb(_ptr(h), _ptr(l), _ptr(middle), _ptr(upper), _ptr(lower), n, period))
return _wrap_multi({"middle": middle, "upper": upper, "lower": lower}, idx, "channels", offset)
def jbands(close: object, period: int = 14, phase: int = 0, offset: int = 0, **kwargs) -> object:
"""J-Line Bands."""
period = int(period)
phase = int(phase)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
middle = _out(n)
upper = _out(n)
lower = _out(n)
_check(_lib.qtl_jbands(_ptr(src), _ptr(middle), _ptr(upper), _ptr(lower), n, period, phase))
return _wrap_multi({"middle": middle, "upper": upper, "lower": lower}, idx, "channels", offset)
def kchannel(high: object, low: object, close: object, period: int = 14, multiplier: float = 2.0, offset: int = 0, **kwargs) -> object:
"""Keltner Channel."""
period = int(period)
multiplier = float(multiplier)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
middle = _out(n)
upper = _out(n)
lower = _out(n)
_check(_lib.qtl_kchannel(_ptr(h), _ptr(l), _ptr(c), _ptr(middle), _ptr(upper), _ptr(lower), n, period, multiplier))
return _wrap_multi({"middle": middle, "upper": upper, "lower": lower}, idx, "channels", offset)
def maenv(close: object, period: int = 14, percentage: float = 2.5, maType: int = 0, offset: int = 0, **kwargs) -> object:
"""Moving Average Envelope."""
period = int(period)
percentage = float(percentage)
maType = int(maType)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
middle = _out(n)
upper = _out(n)
lower = _out(n)
_check(_lib.qtl_maenv(_ptr(src), _ptr(middle), _ptr(upper), _ptr(lower), n, period, percentage, maType))
return _wrap_multi({"middle": middle, "upper": upper, "lower": lower}, idx, "channels", offset)
def mmchannel(high: object, low: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Min-Max Channel."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low)
n = len(h)
upper = _out(n)
lower = _out(n)
_check(_lib.qtl_mmchannel(_ptr(h), _ptr(l), _ptr(upper), _ptr(lower), n, period))
return _wrap_multi({"upper": upper, "lower": lower}, idx, "channels", offset)
def pchannel(high: object, low: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Price Channel."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low)
n = len(h)
middle = _out(n)
upper = _out(n)
lower = _out(n)
_check(_lib.qtl_pchannel(_ptr(h), _ptr(l), _ptr(middle), _ptr(upper), _ptr(lower), n, period))
return _wrap_multi({"middle": middle, "upper": upper, "lower": lower}, idx, "channels", offset)
def regchannel(close: object, period: int = 14, multiplier: float = 2.0, offset: int = 0, **kwargs) -> object:
"""Regression Channel."""
period = int(period)
multiplier = float(multiplier)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
middle = _out(n)
upper = _out(n)
lower = _out(n)
_check(_lib.qtl_regchannel(_ptr(src), _ptr(middle), _ptr(upper), _ptr(lower), n, period, multiplier))
return _wrap_multi({"middle": middle, "upper": upper, "lower": lower}, idx, "channels", offset)
def sdchannel(close: object, period: int = 14, multiplier: float = 2.0, offset: int = 0, **kwargs) -> object:
"""Standard Deviation Channel."""
period = int(period)
multiplier = float(multiplier)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
middle = _out(n)
upper = _out(n)
lower = _out(n)
_check(_lib.qtl_sdchannel(_ptr(src), _ptr(middle), _ptr(upper), _ptr(lower), n, period, multiplier))
return _wrap_multi({"middle": middle, "upper": upper, "lower": lower}, idx, "channels", offset)
def starchannel(high: object, low: object, close: object, period: int = 14, multiplier: float = 2.0, atrPeriod: int = 22, offset: int = 0, **kwargs) -> object:
"""Stoller Average Range Channel (STARC)."""
period = int(period)
multiplier = float(multiplier)
atrPeriod = int(atrPeriod)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
middle = _out(n)
upper = _out(n)
lower = _out(n)
_check(_lib.qtl_starchannel(_ptr(h), _ptr(l), _ptr(c), _ptr(middle), _ptr(upper), _ptr(lower), n, period, multiplier, atrPeriod))
return _wrap_multi({"middle": middle, "upper": upper, "lower": lower}, idx, "channels", offset)
def stbands(high: object, low: object, close: object, period: int = 14, multiplier: float = 2.0, offset: int = 0, **kwargs) -> object:
"""SuperTrend Bands."""
period = int(period)
multiplier = float(multiplier)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
upper = _out(n)
lower = _out(n)
trend = _out(n)
_check(_lib.qtl_stbands(_ptr(h), _ptr(l), _ptr(c), _ptr(upper), _ptr(lower), _ptr(trend), n, period, multiplier))
return _wrap_multi({"upper": upper, "lower": lower, "trend": trend}, idx, "channels", offset)
def ttm_lrc(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""TTM Linear Regression Channel."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
midline = _out(n)
upper1 = _out(n)
lower1 = _out(n)
upper2 = _out(n)
lower2 = _out(n)
_check(_lib.qtl_ttmlrc(_ptr(src), _ptr(midline), _ptr(upper1), _ptr(lower1), _ptr(upper2), _ptr(lower2), n, period))
return _wrap_multi({"midline": midline, "upper1": upper1, "lower1": lower1, "upper2": upper2, "lower2": lower2}, idx, "channels", offset)
def ubands(close: object, period: int = 14, multiplier: float = 2.0, offset: int = 0, **kwargs) -> object:
"""Upper/Lower Bands."""
period = int(period)
multiplier = float(multiplier)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
upper = _out(n)
middle = _out(n)
lower = _out(n)
_check(_lib.qtl_ubands(_ptr(src), _ptr(upper), _ptr(middle), _ptr(lower), n, period, multiplier))
return _wrap_multi({"upper": upper, "middle": middle, "lower": lower}, idx, "channels", offset)
def uchannel(high: object, low: object, close: object, strPeriod: int = 14, centerPeriod: int = 20, multiplier: float = 2.0, offset: int = 0, **kwargs) -> object:
"""Ulcer Channel."""
strPeriod = int(strPeriod)
centerPeriod = int(centerPeriod)
multiplier = float(multiplier)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
upper = _out(n)
middle = _out(n)
lower = _out(n)
_check(_lib.qtl_uchannel(_ptr(h), _ptr(l), _ptr(c), _ptr(upper), _ptr(middle), _ptr(lower), n, strPeriod, centerPeriod, multiplier))
return _wrap_multi({"upper": upper, "middle": middle, "lower": lower}, idx, "channels", offset)
def vwapbands(price: object, volume: object, multiplier: float = 2.0, offset: int = 0, **kwargs) -> object:
"""VWAP Bands."""
multiplier = float(multiplier)
offset = int(offset)
pr, idx = _arr(price); v, _ = _arr(volume)
n = len(pr)
upper1 = _out(n)
lower1 = _out(n)
upper2 = _out(n)
lower2 = _out(n)
vwap = _out(n)
stdDev = _out(n)
_check(_lib.qtl_vwapbands(_ptr(pr), _ptr(v), _ptr(upper1), _ptr(lower1), _ptr(upper2), _ptr(lower2), _ptr(vwap), _ptr(stdDev), n, multiplier))
return _wrap_multi({"upper1": upper1, "lower1": lower1, "upper2": upper2, "lower2": lower2, "vwap": vwap, "stdDev": stdDev}, idx, "channels", offset)
def vwapsd(price: object, volume: object, numDevs: float = 2.0, offset: int = 0, **kwargs) -> object:
"""VWAP Standard Deviation."""
numDevs = float(numDevs)
offset = int(offset)
pr, idx = _arr(price); v, _ = _arr(volume)
n = len(pr)
upper = _out(n)
lower = _out(n)
vwap = _out(n)
stdDev = _out(n)
_check(_lib.qtl_vwapsd(_ptr(pr), _ptr(v), _ptr(upper), _ptr(lower), _ptr(vwap), _ptr(stdDev), n, numDevs))
return _wrap_multi({"upper": upper, "lower": lower, "vwap": vwap, "stdDev": stdDev}, idx, "channels", offset)
def bbands(close: object, length: int = 20, std: float = 2.0,
offset: int = 0, **kwargs) -> object:
"""Bollinger Bands -> (upper, mid, lower) or DataFrame."""
length = int(length); std = float(std); offset = int(offset)
src, idx = _arr(close); n = len(src)
upper = _out(n); mid = _out(n); lower = _out(n)
_check(_lib.qtl_bbands(_ptr(src), n, _ptr(upper), _ptr(mid), _ptr(lower), length, std))
return _wrap_multi(
{f"BBU_{length}_{std}": upper, f"BBM_{length}_{std}": mid, f"BBL_{length}_{std}": lower},
idx, "channels", offset)
def atrbands(high: object, low: object, close: object,
length: int = 14, mult: float = 2.0,
offset: int = 0, **kwargs) -> object:
"""ATR Bands -> (upper, mid, lower) or DataFrame."""
length = int(length); mult = float(mult); offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
upper = _out(n); mid = _out(n); lower = _out(n)
_check(_lib.qtl_atrbands(_ptr(h), _ptr(l), _ptr(c), n, _ptr(upper), _ptr(mid), _ptr(lower), length, mult))
return _wrap_multi(
{f"ATRBU_{length}_{mult}": upper, f"ATRBM_{length}_{mult}": mid, f"ATRBL_{length}_{mult}": lower},
idx, "channels", offset)
def apchannel(high: object, low: object, length: int = 20,
offset: int = 0, **kwargs) -> object:
"""Average Price Channel -> (upper, lower) or DataFrame."""
length = int(length); offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low)
n = len(h)
upper = _out(n); lower = _out(n)
_check(_lib.qtl_apchannel(_ptr(h), _ptr(l), n, _ptr(upper), _ptr(lower), float(length)))
return _wrap_multi({f"APCU_{length}": upper, f"APCL_{length}": lower}, idx, "channels", offset)
+98
View File
@@ -0,0 +1,98 @@
"""quantalib core indicators.
Auto-generated — DO NOT EDIT.
"""
from __future__ import annotations
from ._helpers import _arr, _ptr, _out, _wrap, _wrap_multi, _check, _lib
__all__ = [
"ha",
"midpoint",
"midprice",
"wclprice",
"avgprice",
"medprice",
"typprice",
"midbody",
]
def ha(open: object, high: object, low: object, close: object, offset: int = 0, **kwargs) -> object:
"""Heikin-Ashi Candles."""
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(o)
haOpenOut = _out(n)
haHighOut = _out(n)
haLowOut = _out(n)
haCloseOut = _out(n)
_check(_lib.qtl_ha(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(haOpenOut), _ptr(haHighOut), _ptr(haLowOut), _ptr(haCloseOut), n))
return _wrap_multi({"haOpenOut": haOpenOut, "haHighOut": haHighOut, "haLowOut": haLowOut, "haCloseOut": haCloseOut}, idx, "core", offset)
def midpoint(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Midpoint = src[i] over period."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_midpoint(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"MIDPOINT_{period}", "core", offset)
def midprice(high: object, low: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Mid Price = (High+Low)/2 over period."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low)
n = len(h)
output = _out(n)
_check(_lib.qtl_midprice(_ptr(h), _ptr(l), _ptr(output), n, period))
return _wrap(output, idx, f"MIDPRICE_{period}", "core", offset)
def wclprice(high: object, low: object, close: object, offset: int = 0, **kwargs) -> object:
"""Weighted Close Price = (H+L+2*C)/4."""
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
output = _out(n)
_check(_lib.qtl_wclprice(_ptr(h), _ptr(l), _ptr(c), _ptr(output), n))
return _wrap(output, idx, "WCLPRICE", "core", offset)
def avgprice(open: object, high: object, low: object, close: object,
offset: int = 0, **kwargs) -> object:
"""Average Price = (O+H+L+C)/4."""
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(o); dst = _out(n)
_check(_lib.qtl_avgprice(_ptr(o), _ptr(h), _ptr(l), _ptr(c), n, _ptr(dst)))
return _wrap(dst, idx, "AVGPRICE", "core", offset)
def medprice(high: object, low: object, offset: int = 0, **kwargs) -> object:
"""Median Price = (H+L)/2."""
h, idx = _arr(high); l, _ = _arr(low)
n = len(h); dst = _out(n)
_check(_lib.qtl_medprice(_ptr(h), _ptr(l), n, _ptr(dst)))
return _wrap(dst, idx, "MEDPRICE", "core", int(offset))
def typprice(open: object, high: object, low: object,
offset: int = 0, **kwargs) -> object:
"""Typical Price = (O+H+L)/3 (QuanTAlib variant)."""
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
n = len(o); dst = _out(n)
_check(_lib.qtl_typprice(_ptr(o), _ptr(h), _ptr(l), n, _ptr(dst)))
return _wrap(dst, idx, "TYPPRICE", "core", int(offset))
def midbody(open: object, close: object, offset: int = 0, **kwargs) -> object:
"""Mid Body = (O+C)/2."""
o, idx = _arr(open); c, _ = _arr(close)
n = len(o); dst = _out(n)
_check(_lib.qtl_midbody(_ptr(o), _ptr(c), n, _ptr(dst)))
return _wrap(dst, idx, "MIDBODY", "core", int(offset))
+152
View File
@@ -0,0 +1,152 @@
"""quantalib cycles indicators.
Auto-generated — DO NOT EDIT.
"""
from __future__ import annotations
from ._helpers import _arr, _ptr, _out, _wrap, _wrap_multi, _check, _lib
__all__ = [
"homod",
"ht_dcperiod",
"ht_dcphase",
"ht_phasor",
"ht_sine",
"lunar",
"solar",
"ssfdsp",
"cg",
"dsp",
"ccor",
"ebsw",
"eacp",
]
def homod(close: object, minPeriod: float = 6, maxPeriod: float = 48, offset: int = 0, **kwargs) -> object:
"""Homodyne Discriminator."""
minPeriod = float(minPeriod)
maxPeriod = float(maxPeriod)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_homod(_ptr(src), _ptr(output), n, minPeriod, maxPeriod))
return _wrap(output, idx, f"HOMOD_{minPeriod}", "cycles", offset)
def ht_dcperiod(close: object, offset: int = 0, **kwargs) -> object:
"""Hilbert Transform Dominant Cycle Period."""
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_htdcperiod(_ptr(src), _ptr(output), n))
return _wrap(output, idx, "HT_DCPERIOD", "cycles", offset)
def ht_dcphase(close: object, offset: int = 0, **kwargs) -> object:
"""Hilbert Transform Dominant Cycle Phase."""
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_htdcphase(_ptr(src), _ptr(output), n))
return _wrap(output, idx, "HT_DCPHASE", "cycles", offset)
def ht_phasor(close: object, offset: int = 0, **kwargs) -> object:
"""Hilbert Transform Phasor."""
offset = int(offset)
src, idx = _arr(close)
n = len(src)
inPhase = _out(n)
quadrature = _out(n)
_check(_lib.qtl_htphasor(_ptr(src), _ptr(inPhase), _ptr(quadrature), n))
return _wrap_multi({"inPhase": inPhase, "quadrature": quadrature}, idx, "cycles", offset)
def ht_sine(close: object, offset: int = 0, **kwargs) -> object:
"""Hilbert Transform Sine."""
offset = int(offset)
src, idx = _arr(close)
n = len(src)
sine = _out(n)
leadSine = _out(n)
_check(_lib.qtl_htsine(_ptr(src), _ptr(sine), _ptr(leadSine), n))
return _wrap_multi({"sine": sine, "leadSine": leadSine}, idx, "cycles", offset)
def lunar(close: object, offset: int = 0, **kwargs) -> object:
"""Lunar Cycle."""
offset = int(offset)
src, idx = _arr(close)
n = len(src)
dst = _out(n)
_check(_lib.qtl_lunar(_ptr(src), n, _ptr(dst)))
return _wrap(dst, idx, "LUNAR", "cycles", offset)
def solar(close: object, offset: int = 0, **kwargs) -> object:
"""Solar Cycle."""
offset = int(offset)
src, idx = _arr(close)
n = len(src)
dst = _out(n)
_check(_lib.qtl_solar(_ptr(src), n, _ptr(dst)))
return _wrap(dst, idx, "SOLAR", "cycles", offset)
def ssfdsp(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Supersmoother DSP."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_ssfdsp(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"SSFDSP_{period}", "cycles", offset)
def cg(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Center of Gravity."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_cg(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"CG_{length}", "cycles", offset)
def dsp(close: object, length: int = 20, offset: int = 0, **kwargs) -> object:
"""Dominant Cycle Period (DSP)."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_dsp(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"DSP_{length}", "cycles", offset)
def ccor(close: object, length: int = 20, alpha: float = 0.07,
offset: int = 0, **kwargs) -> object:
"""Circular Correlation."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_ccor(_ptr(src), n, _ptr(dst), length, float(alpha)))
return _wrap(dst, idx, f"CCOR_{length}", "cycles", offset)
def ebsw(close: object, hp_length: int = 40, ssf_length: int = 10,
offset: int = 0, **kwargs) -> object:
"""Even Better Sinewave."""
hp_length = int(hp_length); ssf_length = int(ssf_length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_ebsw(_ptr(src), n, _ptr(dst), hp_length, ssf_length))
return _wrap(dst, idx, f"EBSW_{hp_length}", "cycles", offset)
def eacp(close: object, min_period: int = 8, max_period: int = 48,
avg_length: int = 3, enhance: int = 1,
offset: int = 0, **kwargs) -> object:
"""Ehlers Autocorrelation Periodogram."""
offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_eacp(_ptr(src), n, _ptr(dst), int(min_period), int(max_period), int(avg_length), int(enhance)))
return _wrap(dst, idx, f"EACP_{min_period}_{max_period}", "cycles", offset)
+295
View File
@@ -0,0 +1,295 @@
"""quantalib dynamics indicators.
Auto-generated — DO NOT EDIT.
"""
from __future__ import annotations
from ._helpers import _arr, _ptr, _out, _wrap, _wrap_multi, _check, _lib
__all__ = [
"adx",
"adxr",
"alligator",
"amat",
"aroon",
"aroonosc",
"chop",
"dmx",
"dx",
"ghla",
"ht_trendmode",
"ichimoku",
"impulse",
"pfe",
"qstick",
"ravi",
"supertrend",
"ttm_squeeze",
"ttm_trend",
"vhf",
"vortex",
]
def adx(high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Average Directional Index."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
destination = _out(n)
_check(_lib.qtl_adx(_ptr(h), _ptr(l), _ptr(c), period, n, _ptr(destination)))
return _wrap(destination, idx, f"ADX_{period}", "dynamics", offset)
def adxr(high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""ADX Rating."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
destination = _out(n)
_check(_lib.qtl_adxr(_ptr(h), _ptr(l), _ptr(c), period, n, _ptr(destination)))
return _wrap(destination, idx, f"ADXR_{period}", "dynamics", offset)
def alligator(open: object, high: object, low: object, close: object, volume: object, jawPeriod: int = 13, jawOffset: int = 8, teethPeriod: int = 8, teethOffset: int = 5, lipsPeriod: int = 5, lipsOffset: int = 3, offset: int = 0, **kwargs) -> object:
"""Williams Alligator."""
jawPeriod = int(jawPeriod)
jawOffset = int(jawOffset)
teethPeriod = int(teethPeriod)
teethOffset = int(teethOffset)
lipsPeriod = int(lipsPeriod)
lipsOffset = int(lipsOffset)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(_lib.qtl_alligator(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), jawPeriod, jawOffset, teethPeriod, teethOffset, lipsPeriod, lipsOffset, n, _ptr(dst)))
return _wrap(dst, idx, f"ALLIGATOR_{jawPeriod}", "dynamics", offset)
def amat(close: object, fastPeriod: int = 12, slowPeriod: int = 26, offset: int = 0, **kwargs) -> object:
"""Archer Moving Average Trends."""
fastPeriod = int(fastPeriod)
slowPeriod = int(slowPeriod)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
trend = _out(n)
strength = _out(n)
_check(_lib.qtl_amat(_ptr(src), _ptr(trend), _ptr(strength), n, fastPeriod, slowPeriod))
return _wrap_multi({"trend": trend, "strength": strength}, idx, "dynamics", offset)
def aroon(high: object, low: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Aroon."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low)
n = len(h)
destination = _out(n)
_check(_lib.qtl_aroon(_ptr(h), _ptr(l), period, n, _ptr(destination)))
return _wrap(destination, idx, f"AROON_{period}", "dynamics", offset)
def aroonosc(high: object, low: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Aroon Oscillator."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low)
n = len(h)
destination = _out(n)
_check(_lib.qtl_aroonosc(_ptr(h), _ptr(l), period, n, _ptr(destination)))
return _wrap(destination, idx, f"AROONOSC_{period}", "dynamics", offset)
def chop(open: object, high: object, low: object, close: object, volume: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Choppiness Index."""
period = int(period)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(_lib.qtl_chop(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), period, n, _ptr(dst)))
return _wrap(dst, idx, f"CHOP_{period}", "dynamics", offset)
def dmx(high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Directional Movement Extended."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
destination = _out(n)
_check(_lib.qtl_dmx(_ptr(h), _ptr(l), _ptr(c), period, n, _ptr(destination)))
return _wrap(destination, idx, f"DMX_{period}", "dynamics", offset)
def dx(high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Directional Movement Index."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
destination = _out(n)
_check(_lib.qtl_dx(_ptr(h), _ptr(l), _ptr(c), period, n, _ptr(destination)))
return _wrap(destination, idx, f"DX_{period}", "dynamics", offset)
def ghla(high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Gann Hi-Lo Activator."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
output = _out(n)
_check(_lib.qtl_ghla(_ptr(h), _ptr(l), _ptr(c), _ptr(output), n, period))
return _wrap(output, idx, f"GHLA_{period}", "dynamics", offset)
def ht_trendmode(close: object, offset: int = 0, **kwargs) -> object:
"""Hilbert Transform Trend Mode."""
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_httrendmode(_ptr(src), _ptr(output), n))
return _wrap(output, idx, "HT_TRENDMODE", "dynamics", offset)
def ichimoku(open: object, high: object, low: object, close: object, volume: object, tenkanPeriod: int = 9, kijunPeriod: int = 26, senkouBPeriod: int = 52, displacement: int = 26, offset: int = 0, **kwargs) -> object:
"""Ichimoku Cloud."""
tenkanPeriod = int(tenkanPeriod)
kijunPeriod = int(kijunPeriod)
senkouBPeriod = int(senkouBPeriod)
displacement = int(displacement)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dstTenkan = _out(n)
dstKijun = _out(n)
dstSenkouA = _out(n)
dstSenkouB = _out(n)
dstChikou = _out(n)
_check(_lib.qtl_ichimoku(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), tenkanPeriod, kijunPeriod, senkouBPeriod, displacement, n, _ptr(dstTenkan), _ptr(dstKijun), _ptr(dstSenkouA), _ptr(dstSenkouB), _ptr(dstChikou)))
return _wrap_multi({"dstTenkan": dstTenkan, "dstKijun": dstKijun, "dstSenkouA": dstSenkouA, "dstSenkouB": dstSenkouB, "dstChikou": dstChikou}, idx, "dynamics", offset)
def impulse(close: object, emaPeriod: int = 13, macdFast: int = 12, macdSlow: int = 26, macdSignal: int = 9, offset: int = 0, **kwargs) -> object:
"""Elder Impulse System."""
emaPeriod = int(emaPeriod)
macdFast = int(macdFast)
macdSlow = int(macdSlow)
macdSignal = int(macdSignal)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
dst = _out(n)
_check(_lib.qtl_impulse(_ptr(src), emaPeriod, macdFast, macdSlow, macdSignal, n, _ptr(dst)))
return _wrap(dst, idx, f"IMPULSE_{emaPeriod}", "dynamics", offset)
def pfe(close: object, period: int = 14, smoothPeriod: int = 5, offset: int = 0, **kwargs) -> object:
"""Polarized Fractal Efficiency."""
period = int(period)
smoothPeriod = int(smoothPeriod)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_pfe(_ptr(src), _ptr(output), n, period, smoothPeriod))
return _wrap(output, idx, f"PFE_{period}", "dynamics", offset)
def qstick(open: object, high: object, low: object, close: object, volume: object, period: int = 14, useEma: int = 0, offset: int = 0, **kwargs) -> object:
"""QStick."""
period = int(period)
useEma = int(useEma)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(_lib.qtl_qstick(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), period, useEma, n, _ptr(dst)))
return _wrap(dst, idx, f"QSTICK_{period}", "dynamics", offset)
def ravi(close: object, shortPeriod: int = 12, longPeriod: int = 26, offset: int = 0, **kwargs) -> object:
"""Range Action Verification Index."""
shortPeriod = int(shortPeriod)
longPeriod = int(longPeriod)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_ravi(_ptr(src), _ptr(output), n, shortPeriod, longPeriod))
return _wrap(output, idx, f"RAVI_{shortPeriod}", "dynamics", offset)
def supertrend(open: object, high: object, low: object, close: object, volume: object, period: int = 14, multiplier: float = 2.0, offset: int = 0, **kwargs) -> object:
"""SuperTrend."""
period = int(period)
multiplier = float(multiplier)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(_lib.qtl_super(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), period, multiplier, n, _ptr(dst)))
return _wrap(dst, idx, f"SUPER_{period}", "dynamics", offset)
def ttm_squeeze(open: object, high: object, low: object, close: object, volume: object, bbPeriod: int = 20, bbMult: float = 2.0, kcPeriod: int = 10, kcMult: float = 1.5, momPeriod: int = 12, offset: int = 0, **kwargs) -> object:
"""TTM Squeeze."""
bbPeriod = int(bbPeriod)
bbMult = float(bbMult)
kcPeriod = int(kcPeriod)
kcMult = float(kcMult)
momPeriod = int(momPeriod)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(_lib.qtl_ttmsqueeze(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), bbPeriod, bbMult, kcPeriod, kcMult, momPeriod, n, _ptr(dst)))
return _wrap(dst, idx, f"TTM_SQUEEZE_{bbPeriod}", "dynamics", offset)
def ttm_trend(open: object, high: object, low: object, close: object, volume: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""TTM Trend."""
period = int(period)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(_lib.qtl_ttmtrend(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), period, n, _ptr(dst)))
return _wrap(dst, idx, f"TTM_TREND_{period}", "dynamics", offset)
def vhf(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Vertical Horizontal Filter."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_vhf(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"VHF_{period}", "dynamics", offset)
def vortex(high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Vortex Indicator."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
viPlus = _out(n)
viMinus = _out(n)
_check(_lib.qtl_vortex(_ptr(h), _ptr(l), _ptr(c), period, _ptr(viPlus), n, _ptr(viMinus)))
return _wrap_multi({"viPlus": viPlus, "viMinus": viMinus}, idx, "dynamics", offset)
+322
View File
@@ -0,0 +1,322 @@
"""quantalib errors indicators.
Auto-generated — DO NOT EDIT.
"""
from __future__ import annotations
from ._helpers import _arr, _ptr, _out, _wrap, _wrap_multi, _check, _lib
__all__ = [
"huber",
"logcosh",
"maape",
"mapd",
"mase",
"mdae",
"mdape",
"me",
"mpe",
"mrae",
"msle",
"pseudohuber",
"quantileloss",
"rae",
"rmsle",
"rse",
"rsquared",
"smape",
"theilu",
"tukeybiweight",
"wmape",
"wrmse",
"mse",
"rmse",
"mae",
"mape",
]
def huber(actual: object, predicted: object, period: int = 14, delta: float = 1.35, offset: int = 0, **kwargs) -> object:
"""Huber Loss."""
period = int(period)
delta = float(delta)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_huber(_ptr(a), _ptr(p), _ptr(output), n, period, delta))
return _wrap(output, idx, f"HUBER_{period}", "errors", offset)
def logcosh(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Log-Cosh Loss."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_logcosh(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"LOGCOSH_{period}", "errors", offset)
def maape(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Mean Arctangent Absolute Percentage Error."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_maape(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"MAAPE_{period}", "errors", offset)
def mapd(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Mean Absolute Percentage Deviation."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_mapd(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"MAPD_{period}", "errors", offset)
def mase(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Mean Absolute Scaled Error."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_mase(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"MASE_{period}", "errors", offset)
def mdae(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Median Absolute Error."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_mdae(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"MDAE_{period}", "errors", offset)
def mdape(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Median Absolute Percentage Error."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_mdape(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"MDAPE_{period}", "errors", offset)
def me(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Mean Error."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_me(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"ME_{period}", "errors", offset)
def mpe(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Mean Percentage Error."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_mpe(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"MPE_{period}", "errors", offset)
def mrae(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Mean Relative Absolute Error."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_mrae(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"MRAE_{period}", "errors", offset)
def msle(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Mean Squared Logarithmic Error."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_msle(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"MSLE_{period}", "errors", offset)
def pseudohuber(actual: object, predicted: object, period: int = 14, delta: float = 1.35, offset: int = 0, **kwargs) -> object:
"""Pseudo-Huber Loss."""
period = int(period)
delta = float(delta)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_pseudohuber(_ptr(a), _ptr(p), _ptr(output), n, period, delta))
return _wrap(output, idx, f"PSEUDOHUBER_{period}", "errors", offset)
def quantileloss(actual: object, predicted: object, period: int = 14, quantile: float = 0.5, offset: int = 0, **kwargs) -> object:
"""Quantile Loss (Pinball Loss)."""
period = int(period)
quantile = float(quantile)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_quantileloss(_ptr(a), _ptr(p), _ptr(output), n, period, quantile))
return _wrap(output, idx, f"QUANTILELOSS_{period}", "errors", offset)
def rae(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Relative Absolute Error."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_rae(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"RAE_{period}", "errors", offset)
def rmsle(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Root Mean Squared Logarithmic Error."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_rmsle(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"RMSLE_{period}", "errors", offset)
def rse(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Relative Squared Error."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_rse(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"RSE_{period}", "errors", offset)
def rsquared(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""R-Squared (Coefficient of Determination)."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_rsquared(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"RSQUARED_{period}", "errors", offset)
def smape(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Symmetric Mean Absolute Percentage Error."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_smape(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"SMAPE_{period}", "errors", offset)
def theilu(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Theil U Statistic (Error)."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_theilu(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"THEILU_{period}", "errors", offset)
def tukeybiweight(actual: object, predicted: object, period: int = 14, c: float = 4.685, offset: int = 0, **kwargs) -> object:
"""Tukey Biweight Loss."""
period = int(period)
c = float(c)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_tukeybiweight(_ptr(a), _ptr(p), _ptr(output), n, period, c))
return _wrap(output, idx, f"TUKEYBIWEIGHT_{period}", "errors", offset)
def wmape(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Weighted Mean Absolute Percentage Error."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_wmape(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"WMAPE_{period}", "errors", offset)
def wrmse(actual: object, predicted: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Weighted Root Mean Squared Error."""
period = int(period)
offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a)
output = _out(n)
_check(_lib.qtl_wrmse(_ptr(a), _ptr(p), _ptr(output), n, period))
return _wrap(output, idx, f"WRMSE_{period}", "errors", offset)
def mse(actual: object, predicted: object, length: int = 20,
offset: int = 0, **kwargs) -> object:
"""Mean Squared Error."""
length = int(length); offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a); dst = _out(n)
_check(_lib.qtl_mse(_ptr(a), _ptr(p), n, _ptr(dst), length))
return _wrap(dst, idx, f"MSE_{length}", "errors", offset)
def rmse(actual: object, predicted: object, length: int = 20,
offset: int = 0, **kwargs) -> object:
"""Root Mean Squared Error."""
length = int(length); offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a); dst = _out(n)
_check(_lib.qtl_rmse(_ptr(a), _ptr(p), n, _ptr(dst), length))
return _wrap(dst, idx, f"RMSE_{length}", "errors", offset)
def mae(actual: object, predicted: object, length: int = 20,
offset: int = 0, **kwargs) -> object:
"""Mean Absolute Error."""
length = int(length); offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a); dst = _out(n)
_check(_lib.qtl_mae(_ptr(a), _ptr(p), n, _ptr(dst), length))
return _wrap(dst, idx, f"MAE_{length}", "errors", offset)
def mape(actual: object, predicted: object, length: int = 20,
offset: int = 0, **kwargs) -> object:
"""Mean Absolute Percentage Error."""
length = int(length); offset = int(offset)
a, idx = _arr(actual); p, _ = _arr(predicted)
n = len(a); dst = _out(n)
_check(_lib.qtl_mape(_ptr(a), _ptr(p), n, _ptr(dst), length))
return _wrap(dst, idx, f"MAPE_{length}", "errors", offset)
+422
View File
@@ -0,0 +1,422 @@
"""quantalib filters indicators.
Auto-generated — DO NOT EDIT.
"""
from __future__ import annotations
from ._helpers import _arr, _ptr, _out, _wrap, _wrap_multi, _check, _lib
__all__ = [
"gauss",
"hann",
"hp",
"hpf",
"kalman",
"laguerre",
"lms",
"loess",
"modf",
"notch",
"nw",
"oneeuro",
"rls",
"rmed",
"roofing",
"sgf",
"spbf",
"ssf2",
"ssf3",
"usf",
"voss",
"wavelet",
"wiener",
"bessel",
"butter2",
"butter3",
"cheby1",
"cheby2",
"elliptic",
"edcf",
"bpf",
"alaguerre",
"bilateral",
"baxterking",
"cfitz",
]
def gauss(close: object, sigma: float = 6.0, offset: int = 0, **kwargs) -> object:
"""Gaussian Filter."""
sigma = float(sigma)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_gauss(_ptr(src), _ptr(output), n, sigma))
return _wrap(output, idx, "GAUSS", "filters", offset)
def hann(close: object, length: int = 14, offset: int = 0, **kwargs) -> object:
"""Hann Filter."""
length = int(length)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_hann(_ptr(src), _ptr(output), n, length))
return _wrap(output, idx, f"HANN_{length}", "filters", offset)
def hp(close: object, lam: float = 1600.0, offset: int = 0, **kwargs) -> object:
"""Hodrick-Prescott Filter."""
lam = float(lam)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_hp(_ptr(src), _ptr(output), n, lam))
return _wrap(output, idx, "HP", "filters", offset)
def hpf(close: object, length: int = 14, offset: int = 0, **kwargs) -> object:
"""High-Pass Filter."""
length = int(length)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_hpf(_ptr(src), _ptr(output), n, length))
return _wrap(output, idx, f"HPF_{length}", "filters", offset)
def kalman(close: object, q: float = 0.3, r: float = 1.0, offset: int = 0, **kwargs) -> object:
"""Kalman Filter."""
q = float(q)
r = float(r)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_kalman(_ptr(src), _ptr(output), n, q, r))
return _wrap(output, idx, "KALMAN", "filters", offset)
def laguerre(close: object, gamma: float = 0.7, offset: int = 0, **kwargs) -> object:
"""Laguerre Filter."""
gamma = float(gamma)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_laguerre(_ptr(src), _ptr(output), n, gamma))
return _wrap(output, idx, "LAGUERRE", "filters", offset)
def lms(close: object, order: int = 3, mu: float = 0.01, offset: int = 0, **kwargs) -> object:
"""Least Mean Squares Filter."""
order = int(order)
mu = float(mu)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_lms(_ptr(src), _ptr(output), n, order, mu))
return _wrap(output, idx, "LMS", "filters", offset)
def loess(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""LOESS Smoother."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_loess(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"LOESS_{period}", "filters", offset)
def modf(close: object, period: int = 14, beta: float = 2.0, feedback: int = 0, fbWeight: float = 0.5, offset: int = 0, **kwargs) -> object:
"""Modified Filter."""
period = int(period)
beta = float(beta)
feedback = int(feedback)
fbWeight = float(fbWeight)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_modf(_ptr(src), _ptr(output), n, period, beta, feedback, fbWeight))
return _wrap(output, idx, f"MODF_{period}", "filters", offset)
def notch(close: object, period: int = 14, q: float = 0.3, offset: int = 0, **kwargs) -> object:
"""Notch Filter."""
period = int(period)
q = float(q)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_notch(_ptr(src), _ptr(output), n, period, q))
return _wrap(output, idx, f"NOTCH_{period}", "filters", offset)
def nw(close: object, period: int = 14, bandwidth: float = 0.25, offset: int = 0, **kwargs) -> object:
"""Nadaraya-Watson Filter."""
period = int(period)
bandwidth = float(bandwidth)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_nw(_ptr(src), _ptr(output), n, period, bandwidth))
return _wrap(output, idx, f"NW_{period}", "filters", offset)
def oneeuro(close: object, minCutoff: float = 1.0, beta: float = 2.0, dCutoff: float = 1.0, offset: int = 0, **kwargs) -> object:
"""1€ Filter."""
minCutoff = float(minCutoff)
beta = float(beta)
dCutoff = float(dCutoff)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_oneeuro(_ptr(src), _ptr(output), n, minCutoff, beta, dCutoff))
return _wrap(output, idx, "ONEEURO", "filters", offset)
def rls(close: object, order: int = 3, lam: float = 1600.0, offset: int = 0, **kwargs) -> object:
"""Recursive Least Squares Filter."""
order = int(order)
lam = float(lam)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_rls(_ptr(src), _ptr(output), n, order, lam))
return _wrap(output, idx, "RLS", "filters", offset)
def rmed(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Running Median Filter."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_rmed(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"RMED_{period}", "filters", offset)
def roofing(close: object, hpLength: int = 40, ssLength: int = 10, offset: int = 0, **kwargs) -> object:
"""Roofing Filter."""
hpLength = int(hpLength)
ssLength = int(ssLength)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_roofing(_ptr(src), _ptr(output), n, hpLength, ssLength))
return _wrap(output, idx, f"ROOFING_{hpLength}", "filters", offset)
def sgf(close: object, period: int = 14, polyOrder: int = 3, offset: int = 0, **kwargs) -> object:
"""Savitzky-Golay Filter."""
period = int(period)
polyOrder = int(polyOrder)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_sgf(_ptr(src), _ptr(output), n, period, polyOrder))
return _wrap(output, idx, f"SGF_{period}", "filters", offset)
def spbf(close: object, shortPeriod: int = 12, longPeriod: int = 26, rmsPeriod: int = 20, offset: int = 0, **kwargs) -> object:
"""Short-Period Bandpass Filter."""
shortPeriod = int(shortPeriod)
longPeriod = int(longPeriod)
rmsPeriod = int(rmsPeriod)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_spbf(_ptr(src), _ptr(output), n, shortPeriod, longPeriod, rmsPeriod))
return _wrap(output, idx, f"SPBF_{shortPeriod}", "filters", offset)
def ssf2(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Super Smoother (2-pole)."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_ssf2(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"SSF2_{period}", "filters", offset)
def ssf3(close: object, period: int = 14, initialLast: float = 0.0, offset: int = 0, **kwargs) -> object:
"""Super Smoother (3-pole)."""
period = int(period)
initialLast = float(initialLast)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
destination = _out(n)
_check(_lib.qtl_ssf3(_ptr(src), _ptr(destination), n, period, initialLast))
return _wrap(destination, idx, f"SSF3_{period}", "filters", offset)
def usf(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Universal Smoother Filter."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_usf(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"USF_{period}", "filters", offset)
def voss(close: object, period: int = 14, predict: int = 3, bandwidth: float = 0.25, offset: int = 0, **kwargs) -> object:
"""Voss Predictor."""
period = int(period)
predict = int(predict)
bandwidth = float(bandwidth)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_voss(_ptr(src), _ptr(output), n, period, predict, bandwidth))
return _wrap(output, idx, f"VOSS_{period}", "filters", offset)
def wavelet(close: object, levels: int = 4, threshMult: float = 1.0, offset: int = 0, **kwargs) -> object:
"""Wavelet Filter."""
levels = int(levels)
threshMult = float(threshMult)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_wavelet(_ptr(src), _ptr(output), n, levels, threshMult))
return _wrap(output, idx, "WAVELET", "filters", offset)
def wiener(close: object, period: int = 14, smoothPeriod: int = 5, offset: int = 0, **kwargs) -> object:
"""Wiener Filter."""
period = int(period)
smoothPeriod = int(smoothPeriod)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
destination = _out(n)
_check(_lib.qtl_wiener(_ptr(src), _ptr(destination), n, period, smoothPeriod))
return _wrap(destination, idx, f"WIENER_{period}", "filters", offset)
def bessel(close: object, length: int = 14, offset: int = 0, **kwargs) -> object:
"""Bessel Filter."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_bessel(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"BESSEL_{length}", "filters", offset)
def butter2(close: object, length: int = 14, gain: float = 1.0,
offset: int = 0, **kwargs) -> object:
"""2nd-order Butterworth."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_butter2(_ptr(src), n, _ptr(dst), length, float(gain)))
return _wrap(dst, idx, f"BUTTER2_{length}", "filters", offset)
def butter3(close: object, length: int = 14, gain: float = 1.0,
offset: int = 0, **kwargs) -> object:
"""3rd-order Butterworth."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_butter3(_ptr(src), n, _ptr(dst), length, float(gain)))
return _wrap(dst, idx, f"BUTTER3_{length}", "filters", offset)
def cheby1(close: object, length: int = 14, ripple: float = 0.5,
offset: int = 0, **kwargs) -> object:
"""Chebyshev Type I."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_cheby1(_ptr(src), n, _ptr(dst), length, float(ripple)))
return _wrap(dst, idx, f"CHEBY1_{length}", "filters", offset)
def cheby2(close: object, length: int = 14, ripple: float = 0.5,
offset: int = 0, **kwargs) -> object:
"""Chebyshev Type II."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_cheby2(_ptr(src), n, _ptr(dst), length, float(ripple)))
return _wrap(dst, idx, f"CHEBY2_{length}", "filters", offset)
def elliptic(close: object, length: int = 14, offset: int = 0, **kwargs) -> object:
"""Elliptic (Cauer) Filter."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_elliptic(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"ELLIPTIC_{length}", "filters", offset)
def edcf(close: object, length: int = 14, offset: int = 0, **kwargs) -> object:
"""Ehlers Distance Coefficient Filter."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_edcf(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"EDCF_{length}", "filters", offset)
def bpf(close: object, length: int = 14, bandwidth: int = 5,
offset: int = 0, **kwargs) -> object:
"""Bandpass Filter."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_bpf(_ptr(src), n, _ptr(dst), length, int(bandwidth)))
return _wrap(dst, idx, f"BPF_{length}", "filters", offset)
def alaguerre(close: object, length: int = 20, order: int = 5,
offset: int = 0, **kwargs) -> object:
"""Adaptive Laguerre Filter."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_alaguerre(_ptr(src), n, _ptr(dst), length, int(order)))
return _wrap(dst, idx, f"ALAGUERRE_{length}", "filters", offset)
def bilateral(close: object, length: int = 14, sigma_s: float = 0.5,
sigma_r: float = 1.0, offset: int = 0, **kwargs) -> object:
"""Bilateral Filter."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_bilateral(_ptr(src), n, _ptr(dst), length, float(sigma_s), float(sigma_r)))
return _wrap(dst, idx, f"BILATERAL_{length}", "filters", offset)
def baxterking(close: object, length: int = 12, min_period: int = 6,
max_period: int = 32, offset: int = 0, **kwargs) -> object:
"""Baxter-King Filter."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_baxterking(_ptr(src), n, _ptr(dst), length, int(min_period), int(max_period)))
return _wrap(dst, idx, f"BAXTERKING_{length}", "filters", offset)
def cfitz(close: object, length: int = 6, bw_period: int = 32,
offset: int = 0, **kwargs) -> object:
"""Christiano-Fitzgerald Filter."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_cfitz(_ptr(src), n, _ptr(dst), length, int(bw_period)))
return _wrap(dst, idx, f"CFITZ_{length}", "filters", offset)
File diff suppressed because it is too large Load Diff
+233
View File
@@ -0,0 +1,233 @@
"""quantalib momentum indicators.
Auto-generated — DO NOT EDIT.
"""
from __future__ import annotations
from ._helpers import _arr, _ptr, _out, _wrap, _wrap_multi, _check, _lib
__all__ = [
"bop",
"cci",
"macd",
"pmo",
"ppo",
"prs",
"rocp",
"rocr",
"sam",
"vel",
"rsi",
"roc",
"mom",
"cmo",
"tsi",
"apo",
"bias",
"cfo",
"cfb",
"asi",
]
def bop(open: object, high: object, low: object, close: object, offset: int = 0, **kwargs) -> object:
"""Balance of Power."""
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(o)
destination = _out(n)
_check(_lib.qtl_bop(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(destination), n))
return _wrap(destination, idx, "BOP", "momentum", offset)
def cci(open: object, high: object, low: object, close: object, volume: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Commodity Channel Index."""
period = int(period)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(_lib.qtl_cci(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), period, n, _ptr(dst)))
return _wrap(dst, idx, f"CCI_{period}", "momentum", offset)
def macd(close: object, fastPeriod: int = 12, slowPeriod: int = 26, offset: int = 0, **kwargs) -> object:
"""Moving Average Convergence Divergence."""
fastPeriod = int(fastPeriod)
slowPeriod = int(slowPeriod)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
destination = _out(n)
_check(_lib.qtl_macd(_ptr(src), _ptr(destination), n, fastPeriod, slowPeriod))
return _wrap(destination, idx, f"MACD_{fastPeriod}", "momentum", offset)
def pmo(close: object, timePeriods: int = 14, smoothPeriods: int = 14, signalPeriods: int = 14, offset: int = 0, **kwargs) -> object:
"""Price Momentum Oscillator."""
timePeriods = int(timePeriods)
smoothPeriods = int(smoothPeriods)
signalPeriods = int(signalPeriods)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_pmo(_ptr(src), _ptr(output), n, timePeriods, smoothPeriods, signalPeriods))
return _wrap(output, idx, f"PMO_{timePeriods}", "momentum", offset)
def ppo(close: object, fastPeriod: int = 12, slowPeriod: int = 26, offset: int = 0, **kwargs) -> object:
"""Percentage Price Oscillator."""
fastPeriod = int(fastPeriod)
slowPeriod = int(slowPeriod)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
destination = _out(n)
_check(_lib.qtl_ppo(_ptr(src), _ptr(destination), n, fastPeriod, slowPeriod))
return _wrap(destination, idx, f"PPO_{fastPeriod}", "momentum", offset)
def prs(x: object, y: object, smoothPeriod: int = 5, offset: int = 0, **kwargs) -> object:
"""Price Relative Strength."""
smoothPeriod = int(smoothPeriod)
offset = int(offset)
xarr, idx = _arr(x); yarr, _ = _arr(y)
n = len(xarr)
output = _out(n)
_check(_lib.qtl_prs(_ptr(xarr), _ptr(yarr), _ptr(output), n, smoothPeriod))
return _wrap(output, idx, f"PRS_{smoothPeriod}", "momentum", offset)
def rocp(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Rate of Change (Percentage)."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_rocp(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"ROCP_{period}", "momentum", offset)
def rocr(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Rate of Change (Ratio)."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_rocr(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"ROCR_{period}", "momentum", offset)
def sam(close: object, alpha: float = 2.0, cutoff: int = 10, offset: int = 0, **kwargs) -> object:
"""Simple Alpha Momentum."""
alpha = float(alpha)
cutoff = int(cutoff)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_sam(_ptr(src), _ptr(output), n, alpha, cutoff))
return _wrap(output, idx, "SAM", "momentum", offset)
def vel(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Velocity."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_vel(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"VEL_{period}", "momentum", offset)
def rsi(close: object, length: int = 14, offset: int = 0, **kwargs) -> object:
"""Relative Strength Index."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_rsi(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"RSI_{length}", "momentum", offset)
def roc(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Rate of Change."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_roc(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"ROC_{length}", "momentum", offset)
def mom(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Momentum."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_mom(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"MOM_{length}", "momentum", offset)
def cmo(close: object, length: int = 14, offset: int = 0, **kwargs) -> object:
"""Chande Momentum Oscillator."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_cmo(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"CMO_{length}", "momentum", offset)
def tsi(close: object, long_period: int = 25, short_period: int = 13,
offset: int = 0, **kwargs) -> object:
"""True Strength Index."""
long_period = int(long_period); short_period = int(short_period); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_tsi(_ptr(src), n, _ptr(dst), long_period, short_period))
return _wrap(dst, idx, f"TSI_{long_period}_{short_period}", "momentum", offset)
def apo(close: object, fast: int = 12, slow: int = 26,
offset: int = 0, **kwargs) -> object:
"""Absolute Price Oscillator."""
fast = int(fast); slow = int(slow); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_apo(_ptr(src), n, _ptr(dst), fast, slow))
return _wrap(dst, idx, f"APO_{fast}_{slow}", "momentum", offset)
def bias(close: object, length: int = 26, offset: int = 0, **kwargs) -> object:
"""Bias."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_bias(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"BIAS_{length}", "momentum", offset)
def cfo(close: object, length: int = 14, offset: int = 0, **kwargs) -> object:
"""Chande Forecast Oscillator."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_cfo(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"CFO_{length}", "momentum", offset)
def cfb(close: object, lengths: list | None = None,
offset: int = 0, **kwargs) -> object:
"""Composite Fractal Behavior."""
offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
if lengths:
arr_t = (ctypes.c_int * len(lengths))(*lengths)
_check(_lib.qtl_cfb(_ptr(src), n, _ptr(dst), arr_t, len(lengths)))
else:
_check(_lib.qtl_cfb(_ptr(src), n, _ptr(dst), None, 0))
return _wrap(dst, idx, "CFB", "momentum", offset)
def asi(open: object, high: object, low: object, close: object,
limit: float = 3.0, offset: int = 0, **kwargs) -> object:
"""Accumulative Swing Index."""
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(o); dst = _out(n)
_check(_lib.qtl_asi(_ptr(o), _ptr(h), _ptr(l), _ptr(c), n, _ptr(dst), float(limit)))
return _wrap(dst, idx, "ASI", "momentum", int(offset))
+330
View File
@@ -0,0 +1,330 @@
"""quantalib numerics indicators.
Auto-generated — DO NOT EDIT.
"""
from __future__ import annotations
from ._helpers import _arr, _ptr, _out, _wrap, _wrap_multi, _check, _lib
__all__ = [
"accel",
"fdist",
"fft",
"gammadist",
"highest",
"ifft",
"jerk",
"lineartrans",
"lognormdist",
"logtrans",
"lowest",
"normalize",
"normdist",
"poissondist",
"relu",
"sigmoid",
"slope",
"sqrttrans",
"tdist",
"weibulldist",
"change",
"exptrans",
"betadist",
"expdist",
"binomdist",
"cwt",
"dwt",
]
def accel(close: object, offset: int = 0, **kwargs) -> object:
"""Acceleration."""
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_accel(_ptr(src), _ptr(output), n))
return _wrap(output, idx, "ACCEL", "numerics", offset)
def fdist(close: object, d1: int = 10, d2: int = 20, period: int = 14, offset: int = 0, **kwargs) -> object:
"""F-Distribution."""
d1 = int(d1)
d2 = int(d2)
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_fdist(_ptr(src), _ptr(output), n, d1, d2, period))
return _wrap(output, idx, f"FDIST_{period}", "numerics", offset)
def fft(close: object, windowSize: int = 256, minPeriod: int = 6, maxPeriod: int = 48, offset: int = 0, **kwargs) -> object:
"""Fast Fourier Transform."""
windowSize = int(windowSize)
minPeriod = int(minPeriod)
maxPeriod = int(maxPeriod)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_fft(_ptr(src), _ptr(output), n, windowSize, minPeriod, maxPeriod))
return _wrap(output, idx, f"FFT_{minPeriod}", "numerics", offset)
def gammadist(close: object, alpha: float = 2.0, beta: float = 2.0, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Gamma Distribution."""
alpha = float(alpha)
beta = float(beta)
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_gammadist(_ptr(src), _ptr(output), n, alpha, beta, period))
return _wrap(output, idx, f"GAMMADIST_{period}", "numerics", offset)
def highest(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Highest Value."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_highest(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"HIGHEST_{period}", "numerics", offset)
def ifft(close: object, windowSize: int = 256, numHarmonics: int = 10, offset: int = 0, **kwargs) -> object:
"""Inverse FFT."""
windowSize = int(windowSize)
numHarmonics = int(numHarmonics)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_ifft(_ptr(src), _ptr(output), n, windowSize, numHarmonics))
return _wrap(output, idx, "IFFT", "numerics", offset)
def jerk(close: object, offset: int = 0, **kwargs) -> object:
"""Jerk (3rd derivative)."""
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_jerk(_ptr(src), _ptr(output), n))
return _wrap(output, idx, "JERK", "numerics", offset)
def lineartrans(close: object, slope: float = 1.0, intercept: float = 0.0, offset: int = 0, **kwargs) -> object:
"""Linear Transform."""
slope = float(slope)
intercept = float(intercept)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_lineartrans(_ptr(src), _ptr(output), n, slope, intercept))
return _wrap(output, idx, "LINEARTRANS", "numerics", offset)
def lognormdist(close: object, mu: float = 0.01, sigma: float = 6.0, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Log-Normal Distribution."""
mu = float(mu)
sigma = float(sigma)
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_lognormdist(_ptr(src), _ptr(output), n, mu, sigma, period))
return _wrap(output, idx, f"LOGNORMDIST_{period}", "numerics", offset)
def logtrans(close: object, offset: int = 0, **kwargs) -> object:
"""Logarithmic Transform."""
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_logtrans(_ptr(src), _ptr(output), n))
return _wrap(output, idx, "LOGTRANS", "numerics", offset)
def lowest(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Lowest Value."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_lowest(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"LOWEST_{period}", "numerics", offset)
def normalize(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Normalization."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_normalize(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"NORMALIZE_{period}", "numerics", offset)
def normdist(close: object, mu: float = 0.01, sigma: float = 6.0, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Normal Distribution."""
mu = float(mu)
sigma = float(sigma)
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_normdist(_ptr(src), _ptr(output), n, mu, sigma, period))
return _wrap(output, idx, f"NORMDIST_{period}", "numerics", offset)
def poissondist(close: object, lam: float = 1600.0, period: int = 14, threshold: int = 10, offset: int = 0, **kwargs) -> object:
"""Poisson Distribution."""
lam = float(lam)
period = int(period)
threshold = int(threshold)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_poissondist(_ptr(src), _ptr(output), n, lam, period, threshold))
return _wrap(output, idx, f"POISSONDIST_{period}", "numerics", offset)
def relu(close: object, offset: int = 0, **kwargs) -> object:
"""ReLU Activation."""
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_relu(_ptr(src), _ptr(output), n))
return _wrap(output, idx, "RELU", "numerics", offset)
def sigmoid(close: object, k: float = 2.0, x0: float = 0.0, offset: int = 0, **kwargs) -> object:
"""Sigmoid Transform."""
k = float(k)
x0 = float(x0)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_sigmoid(_ptr(src), _ptr(output), n, k, x0))
return _wrap(output, idx, "SIGMOID", "numerics", offset)
def slope(close: object, offset: int = 0, **kwargs) -> object:
"""Slope (1st derivative)."""
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_slope(_ptr(src), _ptr(output), n))
return _wrap(output, idx, "SLOPE", "numerics", offset)
def sqrttrans(close: object, offset: int = 0, **kwargs) -> object:
"""Square Root Transform."""
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_sqrttrans(_ptr(src), _ptr(output), n))
return _wrap(output, idx, "SQRTTRANS", "numerics", offset)
def tdist(close: object, nu: int = 10, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Student's t-Distribution."""
nu = int(nu)
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_tdist(_ptr(src), _ptr(output), n, nu, period))
return _wrap(output, idx, f"TDIST_{period}", "numerics", offset)
def weibulldist(close: object, k: float = 2.0, lam: float = 1600.0, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Weibull Distribution."""
k = float(k)
lam = float(lam)
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_weibulldist(_ptr(src), _ptr(output), n, k, lam, period))
return _wrap(output, idx, f"WEIBULLDIST_{period}", "numerics", offset)
def change(close: object, length: int = 1, offset: int = 0, **kwargs) -> object:
"""Price Change."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_change(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"CHANGE_{length}", "numerics", offset)
def exptrans(close: object, offset: int = 0, **kwargs) -> object:
"""Exponential Transform."""
offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_exptrans(_ptr(src), n, _ptr(dst)))
return _wrap(dst, idx, "EXPTRANS", "numerics", offset)
def betadist(close: object, length: int = 50, alpha: float = 2.0,
beta: float = 2.0, offset: int = 0, **kwargs) -> object:
"""Beta Distribution."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_betadist(_ptr(src), n, _ptr(dst), length, float(alpha), float(beta)))
return _wrap(dst, idx, f"BETADIST_{length}", "numerics", offset)
def expdist(close: object, length: int = 50, lam: float = 3.0,
offset: int = 0, **kwargs) -> object:
"""Exponential Distribution."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_expdist(_ptr(src), n, _ptr(dst), length, float(lam)))
return _wrap(dst, idx, f"EXPDIST_{length}", "numerics", offset)
def binomdist(close: object, length: int = 50, trials: int = 20,
threshold: int = 10, offset: int = 0, **kwargs) -> object:
"""Binomial Distribution."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_binomdist(_ptr(src), n, _ptr(dst), length, int(trials), int(threshold)))
return _wrap(dst, idx, f"BINOMDIST_{length}", "numerics", offset)
def cwt(close: object, scale: float = 10.0, omega: float = 6.0,
offset: int = 0, **kwargs) -> object:
"""Continuous Wavelet Transform."""
offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_cwt(_ptr(src), n, _ptr(dst), float(scale), float(omega)))
return _wrap(dst, idx, "CWT", "numerics", offset)
def dwt(close: object, length: int = 4, levels: int = 0,
offset: int = 0, **kwargs) -> object:
"""Discrete Wavelet Transform."""
length = int(length); levels = int(levels); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_dwt(_ptr(src), n, _ptr(dst), length, levels))
return _wrap(dst, idx, f"DWT_{length}", "numerics", offset)
+553
View File
@@ -0,0 +1,553 @@
"""quantalib oscillators indicators.
Auto-generated — DO NOT EDIT.
"""
from __future__ import annotations
from ._helpers import _arr, _ptr, _out, _wrap, _wrap_multi, _check, _lib
__all__ = [
"ac",
"ao",
"bbs",
"coppock",
"eri",
"fi",
"gator",
"imi",
"kdj",
"kst",
"marketfi",
"mstoch",
"pgo",
"qqe",
"reverseema",
"rvgi",
"smi",
"squeeze",
"stc",
"stoch",
"stochf",
"stochrsi",
"ttm_wave",
"ultosc",
"willr",
"fisher",
"fisher04",
"dpo",
"trix",
"inertia",
"rsx",
"er",
"cti",
"reflex",
"trendflex",
"kri",
"psl",
"deco",
"dosc",
"dymoi",
"crsi",
"bbb",
"bbi",
"dem",
"brar",
]
def ac(high: object, low: object, fastPeriod: int = 12, slowPeriod: int = 26, acPeriod: int = 5, offset: int = 0, **kwargs) -> object:
"""Accelerator Oscillator."""
fastPeriod = int(fastPeriod)
slowPeriod = int(slowPeriod)
acPeriod = int(acPeriod)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low)
n = len(h)
destination = _out(n)
_check(_lib.qtl_ac(_ptr(h), _ptr(l), _ptr(destination), n, fastPeriod, slowPeriod, acPeriod))
return _wrap(destination, idx, f"AC_{fastPeriod}", "oscillators", offset)
def ao(high: object, low: object, fastPeriod: int = 12, slowPeriod: int = 26, offset: int = 0, **kwargs) -> object:
"""Awesome Oscillator."""
fastPeriod = int(fastPeriod)
slowPeriod = int(slowPeriod)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low)
n = len(h)
destination = _out(n)
_check(_lib.qtl_ao(_ptr(h), _ptr(l), _ptr(destination), n, fastPeriod, slowPeriod))
return _wrap(destination, idx, f"AO_{fastPeriod}", "oscillators", offset)
def bbs(high: object, low: object, close: object, bbPeriod: int = 20, bbMult: float = 2.0, offset: int = 0, **kwargs) -> object:
"""Bollinger Band Squeeze."""
bbPeriod = int(bbPeriod)
bbMult = float(bbMult)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
output = _out(n)
_check(_lib.qtl_bbs(_ptr(h), _ptr(l), _ptr(c), _ptr(output), n, bbPeriod, bbMult))
return _wrap(output, idx, f"BBS_{bbPeriod}", "oscillators", offset)
def coppock(close: object, longRoc: int = 14, shortRoc: int = 11, wmaPeriod: int = 10, offset: int = 0, **kwargs) -> object:
"""Coppock Curve."""
longRoc = int(longRoc)
shortRoc = int(shortRoc)
wmaPeriod = int(wmaPeriod)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_coppock(_ptr(src), _ptr(output), n, longRoc, shortRoc, wmaPeriod))
return _wrap(output, idx, f"COPPOCK_{wmaPeriod}", "oscillators", offset)
def eri(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Elder Ray Index."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
dst = _out(n)
_check(_lib.qtl_eri(_ptr(src), period, n, _ptr(dst)))
return _wrap(dst, idx, f"ERI_{period}", "oscillators", offset)
def fi(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Force Index."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
dst = _out(n)
_check(_lib.qtl_fi(_ptr(src), period, n, _ptr(dst)))
return _wrap(dst, idx, f"FI_{period}", "oscillators", offset)
def gator(close: object, jawPeriod: int = 13, jawShift: int = 8, teethPeriod: int = 8, teethShift: int = 5, lipsPeriod: int = 5, lipsShift: int = 3, offset: int = 0, **kwargs) -> object:
"""Gator Oscillator."""
jawPeriod = int(jawPeriod)
jawShift = int(jawShift)
teethPeriod = int(teethPeriod)
teethShift = int(teethShift)
lipsPeriod = int(lipsPeriod)
lipsShift = int(lipsShift)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_gator(_ptr(src), _ptr(output), n, jawPeriod, jawShift, teethPeriod, teethShift, lipsPeriod, lipsShift))
return _wrap(output, idx, f"GATOR_{jawPeriod}", "oscillators", offset)
def imi(open: object, high: object, low: object, close: object, volume: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Intraday Momentum Index."""
period = int(period)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(_lib.qtl_imi(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), period, n, _ptr(dst)))
return _wrap(dst, idx, f"IMI_{period}", "oscillators", offset)
def kdj(high: object, low: object, close: object, length: int = 14, signal: int = 3, offset: int = 0, **kwargs) -> object:
"""KDJ Indicator."""
length = int(length)
signal = int(signal)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
kOut = _out(n)
dOut = _out(n)
jOut = _out(n)
_check(_lib.qtl_kdj(_ptr(h), _ptr(l), _ptr(c), _ptr(kOut), _ptr(dOut), _ptr(jOut), n, length, signal))
return _wrap_multi({"kOut": kOut, "dOut": dOut, "jOut": jOut}, idx, "oscillators", offset)
def kst(close: object, r1: int = 10, r2: int = 15, r3: int = 20, r4: int = 30, s1: int = 10, s2: int = 10, s3: int = 10, s4: int = 15, sigPeriod: int = 9, offset: int = 0, **kwargs) -> object:
"""Know Sure Thing."""
r1 = int(r1)
r2 = int(r2)
r3 = int(r3)
r4 = int(r4)
s1 = int(s1)
s2 = int(s2)
s3 = int(s3)
s4 = int(s4)
sigPeriod = int(sigPeriod)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
kstOut = _out(n)
sigOut = _out(n)
_check(_lib.qtl_kst(_ptr(src), _ptr(kstOut), _ptr(sigOut), n, r1, r2, r3, r4, s1, s2, s3, s4, sigPeriod))
return _wrap_multi({"kstOut": kstOut, "sigOut": sigOut}, idx, "oscillators", offset)
def marketfi(high: object, low: object, volume: object, offset: int = 0, **kwargs) -> object:
"""Market Facilitation Index."""
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); v, _ = _arr(volume)
n = len(h)
output = _out(n)
_check(_lib.qtl_marketfi(_ptr(h), _ptr(l), _ptr(v), _ptr(output), n))
return _wrap(output, idx, "MARKETFI", "oscillators", offset)
def mstoch(close: object, stochLength: int = 14, hpLength: int = 40, ssLength: int = 10, offset: int = 0, **kwargs) -> object:
"""Modified Stochastic."""
stochLength = int(stochLength)
hpLength = int(hpLength)
ssLength = int(ssLength)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_mstoch(_ptr(src), _ptr(output), n, stochLength, hpLength, ssLength))
return _wrap(output, idx, f"MSTOCH_{stochLength}", "oscillators", offset)
def pgo(high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Pretty Good Oscillator."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
destination = _out(n)
_check(_lib.qtl_pgo(_ptr(h), _ptr(l), _ptr(c), _ptr(destination), n, period))
return _wrap(destination, idx, f"PGO_{period}", "oscillators", offset)
def qqe(close: object, rsiPeriod: int = 14, smoothFactor: int = 5, qqeFactor: float = 4.236, offset: int = 0, **kwargs) -> object:
"""Quantitative Qualitative Estimation."""
rsiPeriod = int(rsiPeriod)
smoothFactor = int(smoothFactor)
qqeFactor = float(qqeFactor)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_qqe(_ptr(src), _ptr(output), n, rsiPeriod, smoothFactor, qqeFactor))
return _wrap(output, idx, f"QQE_{rsiPeriod}", "oscillators", offset)
def reverseema(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Reverse EMA."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_reverseema(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"REVERSEEMA_{period}", "oscillators", offset)
def rvgi(open: object, high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Relative Vigor Index."""
period = int(period)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(o)
rvgiOutput = _out(n)
signalOutput = _out(n)
_check(_lib.qtl_rvgi(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(rvgiOutput), _ptr(signalOutput), n, period))
return _wrap_multi({"rvgiOutput": rvgiOutput, "signalOutput": signalOutput}, idx, "oscillators", offset)
def smi(high: object, low: object, close: object, kPeriod: int = 14, kSmooth: int = 3, dSmooth: int = 3, blau: int = 3, offset: int = 0, **kwargs) -> object:
"""Stochastic Momentum Index."""
kPeriod = int(kPeriod)
kSmooth = int(kSmooth)
dSmooth = int(dSmooth)
blau = int(blau)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
kOut = _out(n)
dOut = _out(n)
_check(_lib.qtl_smi(_ptr(h), _ptr(l), _ptr(c), _ptr(kOut), _ptr(dOut), n, kPeriod, kSmooth, dSmooth, blau))
return _wrap_multi({"kOut": kOut, "dOut": dOut}, idx, "oscillators", offset)
def squeeze(high: object, low: object, close: object, period: int = 14, bbMult: float = 2.0, kcMult: float = 1.5, offset: int = 0, **kwargs) -> object:
"""Squeeze Momentum."""
period = int(period)
bbMult = float(bbMult)
kcMult = float(kcMult)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
momOut = _out(n)
sqOut = _out(n)
_check(_lib.qtl_squeeze(_ptr(h), _ptr(l), _ptr(c), _ptr(momOut), _ptr(sqOut), n, period, bbMult, kcMult))
return _wrap_multi({"momOut": momOut, "sqOut": sqOut}, idx, "oscillators", offset)
def stc(close: object, kPeriod: int = 14, dPeriod: int = 3, fastLength: int = 23, slowLength: int = 50, smoothing: int = 10, offset: int = 0, **kwargs) -> object:
"""Schaff Trend Cycle."""
kPeriod = int(kPeriod)
dPeriod = int(dPeriod)
fastLength = int(fastLength)
slowLength = int(slowLength)
smoothing = int(smoothing)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_stc(_ptr(src), _ptr(output), n, kPeriod, dPeriod, fastLength, slowLength, smoothing))
return _wrap(output, idx, f"STC_{kPeriod}", "oscillators", offset)
def stoch(high: object, low: object, close: object, kLength: int = 14, dPeriod: int = 3, offset: int = 0, **kwargs) -> object:
"""Stochastic Oscillator."""
kLength = int(kLength)
dPeriod = int(dPeriod)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
kOut = _out(n)
dOut = _out(n)
_check(_lib.qtl_stoch(_ptr(h), _ptr(l), _ptr(c), _ptr(kOut), _ptr(dOut), n, kLength, dPeriod))
return _wrap_multi({"kOut": kOut, "dOut": dOut}, idx, "oscillators", offset)
def stochf(high: object, low: object, close: object, kLength: int = 14, dPeriod: int = 3, offset: int = 0, **kwargs) -> object:
"""Fast Stochastic."""
kLength = int(kLength)
dPeriod = int(dPeriod)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
kOut = _out(n)
dOut = _out(n)
_check(_lib.qtl_stochf(_ptr(h), _ptr(l), _ptr(c), _ptr(kOut), _ptr(dOut), n, kLength, dPeriod))
return _wrap_multi({"kOut": kOut, "dOut": dOut}, idx, "oscillators", offset)
def stochrsi(close: object, rsiLength: int = 14, stochLength: int = 14, kSmooth: int = 3, dSmooth: int = 3, offset: int = 0, **kwargs) -> object:
"""Stochastic RSI."""
rsiLength = int(rsiLength)
stochLength = int(stochLength)
kSmooth = int(kSmooth)
dSmooth = int(dSmooth)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_stochrsi(_ptr(src), _ptr(output), n, rsiLength, stochLength, kSmooth, dSmooth))
return _wrap(output, idx, f"STOCHRSI_{rsiLength}", "oscillators", offset)
def ttm_wave(close: object, offset: int = 0, **kwargs) -> object:
"""TTM Wave."""
offset = int(offset)
src, idx = _arr(close)
n = len(src)
dst = _out(n)
_check(_lib.qtl_ttmwave(_ptr(src), n, _ptr(dst)))
return _wrap(dst, idx, "TTM_WAVE", "oscillators", offset)
def ultosc(high: object, low: object, close: object, period1: int = 14, period2: int = 14, period3: int = 14, offset: int = 0, **kwargs) -> object:
"""Ultimate Oscillator."""
period1 = int(period1)
period2 = int(period2)
period3 = int(period3)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
output = _out(n)
_check(_lib.qtl_ultosc(_ptr(h), _ptr(l), _ptr(c), _ptr(output), n, period1, period2, period3))
return _wrap(output, idx, f"ULTOSC_{period1}", "oscillators", offset)
def willr(high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Williams %R."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
output = _out(n)
_check(_lib.qtl_willr(_ptr(h), _ptr(l), _ptr(c), _ptr(output), n, period))
return _wrap(output, idx, f"WILLR_{period}", "oscillators", offset)
def fisher(close: object, length: int = 9, offset: int = 0, **kwargs) -> object:
"""Fisher Transform."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_fisher(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"FISHER_{length}", "oscillators", offset)
def fisher04(close: object, length: int = 9, offset: int = 0, **kwargs) -> object:
"""Fisher Transform (0.4 variant)."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_fisher04(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"FISHER04_{length}", "oscillators", offset)
def dpo(close: object, length: int = 20, offset: int = 0, **kwargs) -> object:
"""Detrended Price Oscillator."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_dpo(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"DPO_{length}", "oscillators", offset)
def trix(close: object, length: int = 18, offset: int = 0, **kwargs) -> object:
"""Triple EMA Rate of Change."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_trix(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"TRIX_{length}", "oscillators", offset)
def inertia(close: object, length: int = 20, offset: int = 0, **kwargs) -> object:
"""Inertia."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_inertia(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"INERTIA_{length}", "oscillators", offset)
def rsx(close: object, length: int = 14, offset: int = 0, **kwargs) -> object:
"""Relative Strength Xtra."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_rsx(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"RSX_{length}", "oscillators", offset)
def er(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Efficiency Ratio."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_er(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"ER_{length}", "oscillators", offset)
def cti(close: object, length: int = 12, offset: int = 0, **kwargs) -> object:
"""Correlation Trend Indicator."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_cti(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"CTI_{length}", "oscillators", offset)
def reflex(close: object, length: int = 20, offset: int = 0, **kwargs) -> object:
"""Reflex."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_reflex(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"REFLEX_{length}", "oscillators", offset)
def trendflex(close: object, length: int = 20, offset: int = 0, **kwargs) -> object:
"""Trendflex."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_trendflex(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"TRENDFLEX_{length}", "oscillators", offset)
def kri(close: object, length: int = 20, offset: int = 0, **kwargs) -> object:
"""Kairi Relative Index."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_kri(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"KRI_{length}", "oscillators", offset)
def psl(close: object, length: int = 12, offset: int = 0, **kwargs) -> object:
"""Psychological Line."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_psl(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"PSL_{length}", "oscillators", offset)
def deco(close: object, short_period: int = 30, long_period: int = 60,
offset: int = 0, **kwargs) -> object:
"""DECO."""
short_period = int(short_period); long_period = int(long_period); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_deco(_ptr(src), n, _ptr(dst), short_period, long_period))
return _wrap(dst, idx, f"DECO_{short_period}_{long_period}", "oscillators", offset)
def dosc(close: object, rsi_period: int = 14, ema1_period: int = 5,
ema2_period: int = 3, signal_period: int = 9,
offset: int = 0, **kwargs) -> object:
"""DeMarker Oscillator."""
offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_dosc(_ptr(src), n, _ptr(dst),
int(rsi_period), int(ema1_period), int(ema2_period), int(signal_period)))
return _wrap(dst, idx, f"DOSC_{rsi_period}", "oscillators", offset)
def dymoi(close: object, base_period: int = 14, short_period: int = 5,
long_period: int = 10, min_period: int = 3, max_period: int = 30,
offset: int = 0, **kwargs) -> object:
"""Dynamic Momentum Index."""
offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_dymoi(_ptr(src), n, _ptr(dst),
int(base_period), int(short_period), int(long_period),
int(min_period), int(max_period)))
return _wrap(dst, idx, "DYMOI", "oscillators", offset)
def crsi(close: object, rsi_period: int = 3, streak_period: int = 2,
rank_period: int = 100, offset: int = 0, **kwargs) -> object:
"""Connors RSI."""
offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_crsi(_ptr(src), n, _ptr(dst),
int(rsi_period), int(streak_period), int(rank_period)))
return _wrap(dst, idx, f"CRSI_{rsi_period}", "oscillators", offset)
def bbb(close: object, length: int = 20, mult: float = 2.0,
offset: int = 0, **kwargs) -> object:
"""Bollinger Band Bounce."""
length = int(length); mult = float(mult); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_bbb(_ptr(src), n, _ptr(dst), length, mult))
return _wrap(dst, idx, f"BBB_{length}", "oscillators", offset)
def bbi(close: object, p1: int = 3, p2: int = 6, p3: int = 12, p4: int = 24,
offset: int = 0, **kwargs) -> object:
"""Bull Bear Index."""
offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_bbi(_ptr(src), n, _ptr(dst), int(p1), int(p2), int(p3), int(p4)))
return _wrap(dst, idx, "BBI", "oscillators", offset)
def dem(high: object, low: object, length: int = 14,
offset: int = 0, **kwargs) -> object:
"""DeMarker."""
length = int(length)
h, idx = _arr(high); l, _ = _arr(low)
n = len(h); dst = _out(n)
_check(_lib.qtl_dem(_ptr(h), _ptr(l), n, _ptr(dst), length))
return _wrap(dst, idx, f"DEM_{length}", "oscillators", int(offset))
def brar(open: object, high: object, low: object, close: object,
length: int = 26, offset: int = 0, **kwargs) -> object:
"""Bull-Bear Ratio (BRAR)."""
length = int(length); offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(o); br = _out(n); ar = _out(n)
_check(_lib.qtl_brar(_ptr(o), _ptr(h), _ptr(l), _ptr(c), n, _ptr(br), _ptr(ar), length))
return _wrap_multi({f"BR_{length}": br, f"AR_{length}": ar}, idx, "oscillators", offset)
+156
View File
@@ -0,0 +1,156 @@
"""quantalib reversals indicators.
Auto-generated — DO NOT EDIT.
"""
from __future__ import annotations
from ._helpers import _arr, _ptr, _out, _wrap, _wrap_multi, _check, _lib
__all__ = [
"chandelier",
"ckstop",
"fractals",
"pivot",
"pivotcam",
"pivotdem",
"pivotext",
"pivotfib",
"pivotwood",
"psar",
"swings",
"ttm_scalper",
]
def chandelier(open: object, high: object, low: object, close: object, period: int = 14, multiplier: float = 2.0, offset: int = 0, **kwargs) -> object:
"""Chandelier Exit."""
period = int(period)
multiplier = float(multiplier)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(o)
output = _out(n)
_check(_lib.qtl_chandelier(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(output), n, period, multiplier))
return _wrap(output, idx, f"CHANDELIER_{period}", "reversals", offset)
def ckstop(open: object, high: object, low: object, close: object, atrPeriod: int = 22, multiplier: float = 2.0, stopPeriod: int = 3, offset: int = 0, **kwargs) -> object:
"""Chuck LeBeau Stop."""
atrPeriod = int(atrPeriod)
multiplier = float(multiplier)
stopPeriod = int(stopPeriod)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(o)
output = _out(n)
_check(_lib.qtl_ckstop(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(output), n, atrPeriod, multiplier, stopPeriod))
return _wrap(output, idx, f"CKSTOP_{atrPeriod}", "reversals", offset)
def fractals(high: object, low: object, offset: int = 0, **kwargs) -> object:
"""Williams Fractals."""
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low)
n = len(h)
upOutput = _out(n)
downOutput = _out(n)
_check(_lib.qtl_fractals(_ptr(h), _ptr(l), _ptr(upOutput), _ptr(downOutput), n))
return _wrap_multi({"upOutput": upOutput, "downOutput": downOutput}, idx, "reversals", offset)
def pivot(high: object, low: object, close: object, offset: int = 0, **kwargs) -> object:
"""Pivot Points (Traditional)."""
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
ppOutput = _out(n)
_check(_lib.qtl_pivot(_ptr(h), _ptr(l), _ptr(c), _ptr(ppOutput), n))
return _wrap(ppOutput, idx, "PIVOT", "reversals", offset)
def pivotcam(high: object, low: object, close: object, offset: int = 0, **kwargs) -> object:
"""Camarilla Pivot Points."""
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
ppOutput = _out(n)
_check(_lib.qtl_pivotcam(_ptr(h), _ptr(l), _ptr(c), _ptr(ppOutput), n))
return _wrap(ppOutput, idx, "PIVOTCAM", "reversals", offset)
def pivotdem(open: object, high: object, low: object, close: object, offset: int = 0, **kwargs) -> object:
"""DeMark Pivot Points."""
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(o)
ppOutput = _out(n)
_check(_lib.qtl_pivotdem(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(ppOutput), n))
return _wrap(ppOutput, idx, "PIVOTDEM", "reversals", offset)
def pivotext(high: object, low: object, close: object, offset: int = 0, **kwargs) -> object:
"""Extended Pivot Points."""
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
ppOutput = _out(n)
_check(_lib.qtl_pivotext(_ptr(h), _ptr(l), _ptr(c), _ptr(ppOutput), n))
return _wrap(ppOutput, idx, "PIVOTEXT", "reversals", offset)
def pivotfib(high: object, low: object, close: object, offset: int = 0, **kwargs) -> object:
"""Fibonacci Pivot Points."""
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
ppOutput = _out(n)
_check(_lib.qtl_pivotfib(_ptr(h), _ptr(l), _ptr(c), _ptr(ppOutput), n))
return _wrap(ppOutput, idx, "PIVOTFIB", "reversals", offset)
def pivotwood(high: object, low: object, close: object, offset: int = 0, **kwargs) -> object:
"""Woodie Pivot Points."""
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
ppOutput = _out(n)
_check(_lib.qtl_pivotwood(_ptr(h), _ptr(l), _ptr(c), _ptr(ppOutput), n))
return _wrap(ppOutput, idx, "PIVOTWOOD", "reversals", offset)
def psar(open: object, high: object, low: object, close: object, afStart: float = 0.02, afIncrement: float = 0.02, afMax: float = 0.2, offset: int = 0, **kwargs) -> object:
"""Parabolic SAR."""
afStart = float(afStart)
afIncrement = float(afIncrement)
afMax = float(afMax)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(o)
output = _out(n)
_check(_lib.qtl_psar(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(output), n, afStart, afIncrement, afMax))
return _wrap(output, idx, "PSAR", "reversals", offset)
def swings(high: object, low: object, lookback: int = 5, offset: int = 0, **kwargs) -> object:
"""Swing High/Low."""
lookback = int(lookback)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low)
n = len(h)
highOutput = _out(n)
lowOutput = _out(n)
_check(_lib.qtl_swings(_ptr(h), _ptr(l), _ptr(highOutput), _ptr(lowOutput), n, lookback))
return _wrap_multi({"highOutput": highOutput, "lowOutput": lowOutput}, idx, "reversals", offset)
def ttm_scalper(high: object, low: object, close: object, useCloses: int = 0, offset: int = 0, **kwargs) -> object:
"""TTM Scalper."""
useCloses = int(useCloses)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
highOutput = _out(n)
lowOutput = _out(n)
_check(_lib.qtl_ttmscalper(_ptr(h), _ptr(l), _ptr(c), _ptr(highOutput), _ptr(lowOutput), n, useCloses))
return _wrap_multi({"highOutput": highOutput, "lowOutput": lowOutput}, idx, "reversals", offset)
+394
View File
@@ -0,0 +1,394 @@
"""quantalib statistics indicators.
Auto-generated — DO NOT EDIT.
"""
from __future__ import annotations
from ._helpers import _arr, _ptr, _out, _wrap, _wrap_multi, _check, _lib
__all__ = [
"acf",
"geomean",
"granger",
"harmean",
"hurst",
"iqr",
"jb",
"kendall",
"kurtosis",
"linreg",
"meandev",
"median",
"mode",
"pacf",
"percentile",
"polyfit",
"quantile",
"skew",
"spearman",
"stderr",
"sum",
"theil",
"trim",
"wavg",
"wins",
"ztest",
"zscore",
"cma",
"entropy",
"correlation",
"covariance",
"cointegration",
]
def acf(close: object, period: int = 14, lag: int = 10, offset: int = 0, **kwargs) -> object:
"""Autocorrelation Function."""
period = int(period)
lag = int(lag)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_acf(_ptr(src), _ptr(output), n, period, lag))
return _wrap(output, idx, f"ACF_{period}", "statistics", offset)
def geomean(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Geometric Mean."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_geomean(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"GEOMEAN_{period}", "statistics", offset)
def granger(x: object, y: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Granger Causality."""
period = int(period)
offset = int(offset)
xarr, idx = _arr(x); yarr, _ = _arr(y)
n = len(xarr)
output = _out(n)
_check(_lib.qtl_granger(_ptr(yarr), _ptr(xarr), _ptr(output), n, period))
return _wrap(output, idx, f"GRANGER_{period}", "statistics", offset)
def harmean(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Harmonic Mean."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_harmean(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"HARMEAN_{period}", "statistics", offset)
def hurst(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Hurst Exponent."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_hurst(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"HURST_{period}", "statistics", offset)
def iqr(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Interquartile Range."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_iqr(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"IQR_{period}", "statistics", offset)
def jb(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Jarque-Bera Test."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_jb(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"JB_{period}", "statistics", offset)
def kendall(x: object, y: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Kendall Rank Correlation."""
period = int(period)
offset = int(offset)
xarr, idx = _arr(x); yarr, _ = _arr(y)
n = len(xarr)
output = _out(n)
_check(_lib.qtl_kendall(_ptr(xarr), _ptr(yarr), _ptr(output), n, period))
return _wrap(output, idx, f"KENDALL_{period}", "statistics", offset)
def kurtosis(close: object, period: int = 14, isPopulation: int = 0, offset: int = 0, **kwargs) -> object:
"""Kurtosis."""
period = int(period)
isPopulation = int(isPopulation)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_kurtosis(_ptr(src), _ptr(output), n, period, isPopulation))
return _wrap(output, idx, f"KURTOSIS_{period}", "statistics", offset)
def linreg(close: object, period: int = 14, initialLastValid: float = 0.0, offset: int = 0, **kwargs) -> object:
"""Linear Regression."""
period = int(period)
initialLastValid = float(initialLastValid)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_linreg(_ptr(src), _ptr(output), n, period, initialLastValid))
return _wrap(output, idx, f"LINREG_{period}", "statistics", offset)
def meandev(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Mean Deviation."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_meandev(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"MEANDEV_{period}", "statistics", offset)
def median(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Rolling Median."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_median(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"MEDIAN_{period}", "statistics", offset)
def mode(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Rolling Mode."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_mode(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"MODE_{period}", "statistics", offset)
def pacf(close: object, period: int = 14, lag: int = 10, offset: int = 0, **kwargs) -> object:
"""Partial Autocorrelation Function."""
period = int(period)
lag = int(lag)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_pacf(_ptr(src), _ptr(output), n, period, lag))
return _wrap(output, idx, f"PACF_{period}", "statistics", offset)
def percentile(close: object, period: int = 14, percent: float = 50.0, offset: int = 0, **kwargs) -> object:
"""Rolling Percentile."""
period = int(period)
percent = float(percent)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_percentile(_ptr(src), _ptr(output), n, period, percent))
return _wrap(output, idx, f"PERCENTILE_{period}", "statistics", offset)
def polyfit(close: object, period: int = 14, degree: int = 2, initialLastValid: float = 0.0, offset: int = 0, **kwargs) -> object:
"""Polynomial Fit."""
period = int(period)
degree = int(degree)
initialLastValid = float(initialLastValid)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_polyfit(_ptr(src), _ptr(output), n, period, degree, initialLastValid))
return _wrap(output, idx, f"POLYFIT_{period}", "statistics", offset)
def quantile(close: object, period: int = 14, quantileLevel: float = 0.5, offset: int = 0, **kwargs) -> object:
"""Rolling Quantile."""
period = int(period)
quantileLevel = float(quantileLevel)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_quantile(_ptr(src), _ptr(output), n, period, quantileLevel))
return _wrap(output, idx, f"QUANTILE_{period}", "statistics", offset)
def skew(close: object, period: int = 14, isPopulation: int = 0, offset: int = 0, **kwargs) -> object:
"""Skewness."""
period = int(period)
isPopulation = int(isPopulation)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_skew(_ptr(src), _ptr(output), n, period, isPopulation))
return _wrap(output, idx, f"SKEW_{period}", "statistics", offset)
def spearman(x: object, y: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Spearman Rank Correlation."""
period = int(period)
offset = int(offset)
xarr, idx = _arr(x); yarr, _ = _arr(y)
n = len(xarr)
output = _out(n)
_check(_lib.qtl_spearman(_ptr(xarr), _ptr(yarr), _ptr(output), n, period))
return _wrap(output, idx, f"SPEARMAN_{period}", "statistics", offset)
def stderr(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Standard Error."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_stderr(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"STDERR_{period}", "statistics", offset)
def sum(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Rolling Sum."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_sum(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"SUM_{period}", "statistics", offset)
def theil(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Theil U Statistic."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_theil(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"THEIL_{period}", "statistics", offset)
def trim(close: object, period: int = 14, trimPct: float = 0.1, offset: int = 0, **kwargs) -> object:
"""Trimmed Mean."""
period = int(period)
trimPct = float(trimPct)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_trim(_ptr(src), _ptr(output), n, period, trimPct))
return _wrap(output, idx, f"TRIM_{period}", "statistics", offset)
def wavg(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Weighted Average."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_wavg(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"WAVG_{period}", "statistics", offset)
def wins(close: object, period: int = 14, winPct: float = 0.05, offset: int = 0, **kwargs) -> object:
"""Winsorized Mean."""
period = int(period)
winPct = float(winPct)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_wins(_ptr(src), _ptr(output), n, period, winPct))
return _wrap(output, idx, f"WINS_{period}", "statistics", offset)
def ztest(close: object, period: int = 14, mu0: float = 0.0, offset: int = 0, **kwargs) -> object:
"""Z-Test."""
period = int(period)
mu0 = float(mu0)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_ztest(_ptr(src), _ptr(output), n, period, mu0))
return _wrap(output, idx, f"ZTEST_{period}", "statistics", offset)
def zscore(close: object, length: int = 20, offset: int = 0, **kwargs) -> object:
"""Z-Score."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_zscore(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"ZSCORE_{length}", "statistics", offset)
def cma(close: object, offset: int = 0, **kwargs) -> object:
"""Cumulative Moving Average."""
offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_cma(_ptr(src), n, _ptr(dst)))
return _wrap(dst, idx, "CMA", "statistics", offset)
def entropy(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Shannon Entropy."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_entropy(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"ENTROPY_{length}", "statistics", offset)
def correlation(x: object, y: object, length: int = 20,
offset: int = 0, **kwargs) -> object:
"""Pearson Correlation."""
length = int(length); offset = int(offset)
xarr, idx = _arr(x); yarr, _ = _arr(y)
n = len(xarr); dst = _out(n)
_check(_lib.qtl_correlation(_ptr(xarr), _ptr(yarr), n, _ptr(dst), length))
return _wrap(dst, idx, f"CORR_{length}", "statistics", offset)
def covariance(x: object, y: object, length: int = 20,
is_sample: bool = True, offset: int = 0, **kwargs) -> object:
"""Covariance."""
length = int(length); offset = int(offset)
xarr, idx = _arr(x); yarr, _ = _arr(y)
n = len(xarr); dst = _out(n)
_check(_lib.qtl_covariance(_ptr(xarr), _ptr(yarr), n, _ptr(dst), length, int(is_sample)))
return _wrap(dst, idx, f"COV_{length}", "statistics", offset)
def cointegration(x: object, y: object, length: int = 20,
offset: int = 0, **kwargs) -> object:
"""Cointegration."""
length = int(length); offset = int(offset)
xarr, idx = _arr(x); yarr, _ = _arr(y)
n = len(xarr); dst = _out(n)
_check(_lib.qtl_cointegration(_ptr(xarr), _ptr(yarr), n, _ptr(dst), length))
return _wrap(dst, idx, f"COINT_{length}", "statistics", offset)
+371
View File
@@ -0,0 +1,371 @@
"""quantalib trends_fir indicators.
Auto-generated — DO NOT EDIT.
"""
from __future__ import annotations
from ._helpers import _arr, _ptr, _out, _wrap, _wrap_multi, _check, _lib
__all__ = [
"fwma",
"gwma",
"hamma",
"hend",
"ilrs",
"kaiser",
"lanczos",
"nlma",
"nyqma",
"pma",
"pwma",
"qrma",
"rwma",
"sma",
"wma",
"hma",
"trima",
"swma",
"dwma",
"blma",
"alma",
"lsma",
"sgma",
"sinema",
"hanma",
"parzen",
"tsf",
"conv",
"bwma",
"crma",
"sp15",
"tukey_w",
"rain",
"afirma",
]
def fwma(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Fibonacci Weighted Moving Average."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_fwma(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"FWMA_{period}", "trends_fir", offset)
def gwma(close: object, period: int = 14, sigma: float = 6.0, offset: int = 0, **kwargs) -> object:
"""Gaussian Weighted Moving Average."""
period = int(period)
sigma = float(sigma)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_gwma(_ptr(src), _ptr(output), n, period, sigma))
return _wrap(output, idx, f"GWMA_{period}", "trends_fir", offset)
def hamma(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Hamming Moving Average."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_hamma(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"HAMMA_{period}", "trends_fir", offset)
def hend(close: object, period: int = 14, nanValue: float = 0.0, offset: int = 0, **kwargs) -> object:
"""Henderson Moving Average."""
period = int(period)
nanValue = float(nanValue)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_hend(_ptr(src), _ptr(output), n, period, nanValue))
return _wrap(output, idx, f"HEND_{period}", "trends_fir", offset)
def ilrs(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Integral of Linear Regression Slope."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_ilrs(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"ILRS_{period}", "trends_fir", offset)
def kaiser(close: object, period: int = 14, beta: float = 2.0, nanValue: float = 0.0, offset: int = 0, **kwargs) -> object:
"""Kaiser Window Moving Average."""
period = int(period)
beta = float(beta)
nanValue = float(nanValue)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_kaiser(_ptr(src), _ptr(output), n, period, beta, nanValue))
return _wrap(output, idx, f"KAISER_{period}", "trends_fir", offset)
def lanczos(close: object, period: int = 14, nanValue: float = 0.0, offset: int = 0, **kwargs) -> object:
"""Lanczos Moving Average."""
period = int(period)
nanValue = float(nanValue)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_lanczos(_ptr(src), _ptr(output), n, period, nanValue))
return _wrap(output, idx, f"LANCZOS_{period}", "trends_fir", offset)
def nlma(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Non-Lag Moving Average."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_nlma(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"NLMA_{period}", "trends_fir", offset)
def nyqma(close: object, period: int = 14, nyquistPeriod: int = 2, offset: int = 0, **kwargs) -> object:
"""Nyquist Moving Average."""
period = int(period)
nyquistPeriod = int(nyquistPeriod)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_nyqma(_ptr(src), _ptr(output), n, period, nyquistPeriod))
return _wrap(output, idx, f"NYQMA_{period}", "trends_fir", offset)
def pma(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Predictive Moving Average."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
pmaOutput = _out(n)
triggerOutput = _out(n)
_check(_lib.qtl_pma(_ptr(src), _ptr(pmaOutput), _ptr(triggerOutput), n, period))
return _wrap_multi({"pmaOutput": pmaOutput, "triggerOutput": triggerOutput}, idx, "trends_fir", offset)
def pwma(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Pascal Weighted Moving Average."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_pwma(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"PWMA_{period}", "trends_fir", offset)
def qrma(close: object, period: int = 14, initialLastValid: float = 0.0, offset: int = 0, **kwargs) -> object:
"""Quick Reaction Moving Average."""
period = int(period)
initialLastValid = float(initialLastValid)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_qrma(_ptr(src), _ptr(output), n, period, initialLastValid))
return _wrap(output, idx, f"QRMA_{period}", "trends_fir", offset)
def rwma(high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Range Weighted Moving Average."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
output = _out(n)
_check(_lib.qtl_rwma(_ptr(c), _ptr(h), _ptr(l), _ptr(output), n, period))
return _wrap(output, idx, f"RWMA_{period}", "trends_fir", offset)
def sma(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Simple Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_sma(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"SMA_{length}", "trends_fir", offset)
def wma(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Weighted Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_wma(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"WMA_{length}", "trends_fir", offset)
def hma(close: object, length: int = 9, offset: int = 0, **kwargs) -> object:
"""Hull Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_hma(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"HMA_{length}", "trends_fir", offset)
def trima(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Triangular Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_trima(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"TRIMA_{length}", "trends_fir", offset)
def swma(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Symmetric Weighted Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_swma(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"SWMA_{length}", "trends_fir", offset)
def dwma(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Double Weighted Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_dwma(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"DWMA_{length}", "trends_fir", offset)
def blma(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Blackman Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_blma(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"BLMA_{length}", "trends_fir", offset)
def alma(close: object, length: int = 10, alma_offset: float = 0.85,
sigma: float = 6.0, offset: int = 0, **kwargs) -> object:
"""Arnaud Legoux Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_alma(_ptr(src), n, _ptr(dst), length, float(alma_offset), float(sigma)))
return _wrap(dst, idx, f"ALMA_{length}", "trends_fir", offset)
def lsma(close: object, length: int = 25, offset: int = 0, **kwargs) -> object:
"""Least Squares Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_lsma(_ptr(src), n, _ptr(dst), length, 0, 1.0))
return _wrap(dst, idx, f"LSMA_{length}", "trends_fir", offset)
def sgma(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Savitzky-Golay Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_sgma(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"SGMA_{length}", "trends_fir", offset)
def sinema(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Sine-weighted Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_sinema(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"SINEMA_{length}", "trends_fir", offset)
def hanma(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Hann-weighted Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_hanma(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"HANMA_{length}", "trends_fir", offset)
def parzen(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Parzen-weighted Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_parzen(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"PARZEN_{length}", "trends_fir", offset)
def tsf(close: object, length: int = 14, offset: int = 0, **kwargs) -> object:
"""Time Series Forecast."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_tsf(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"TSF_{length}", "trends_fir", offset)
def conv(close: object, kernel: list | None = None,
offset: int = 0, **kwargs) -> object:
"""Convolution with custom kernel."""
offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
if kernel is None:
kernel = [1.0]
k = np.ascontiguousarray(kernel, dtype=_F64)
_check(_lib.qtl_conv(_ptr(src), n, _ptr(dst), _ptr(k), len(k)))
return _wrap(dst, idx, "CONV", "trends_fir", offset)
def bwma(close: object, length: int = 10, order: int = 0,
offset: int = 0, **kwargs) -> object:
"""Butterworth-weighted Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_bwma(_ptr(src), n, _ptr(dst), length, int(order)))
return _wrap(dst, idx, f"BWMA_{length}", "trends_fir", offset)
def crma(close: object, length: int = 10, volume_factor: float = 1.0,
offset: int = 0, **kwargs) -> object:
"""Cosine-Ramp Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_crma(_ptr(src), n, _ptr(dst), length, float(volume_factor)))
return _wrap(dst, idx, f"CRMA_{length}", "trends_fir", offset)
def sp15(close: object, length: int = 15, offset: int = 0, **kwargs) -> object:
"""SP-15 Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_sp15(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"SP15_{length}", "trends_fir", offset)
def tukey_w(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Tukey-windowed Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_tukey_w(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"TUKEY_{length}", "trends_fir", offset)
def rain(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""RAIN Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_rain(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"RAIN_{length}", "trends_fir", offset)
def afirma(close: object, length: int = 10, window_type: int = 0,
use_simd: bool = False, offset: int = 0, **kwargs) -> object:
"""Adaptive FIR Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_afirma(_ptr(src), n, _ptr(dst), length, int(window_type), int(use_simd)))
return _wrap(dst, idx, f"AFIRMA_{length}", "trends_fir", offset)
+473
View File
@@ -0,0 +1,473 @@
"""quantalib trends_iir indicators.
Auto-generated DO NOT EDIT.
"""
from __future__ import annotations
from ._helpers import _arr, _ptr, _out, _wrap, _wrap_multi, _check, _lib
__all__ = [
"adxvma",
"frama",
"holt",
"htit",
"hwma",
"jma",
"kama",
"ltma",
"mama",
"mavp",
"mcnma",
"mgdi",
"mma",
"nma",
"qema",
"rema",
"rgma",
"rma",
"t3",
"trama",
"vama",
"vidya",
"yzvama",
"zldema",
"zlema",
"zltema",
"ema",
"ema_alpha",
"dema",
"dema_alpha",
"tema",
"lema",
"hema",
"ahrens",
"decycler",
"dsma",
"gdema",
"coral",
"agc",
"ccyc",
]
def adxvma(open: object, high: object, low: object, close: object, volume: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""ADX Variable Moving Average."""
period = int(period)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(_lib.qtl_adxvma(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), period, n, _ptr(dst)))
return _wrap(dst, idx, f"ADXVMA_{period}", "trends_iir", offset)
def frama(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Fractal Adaptive Moving Average."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_frama(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"FRAMA_{period}", "trends_iir", offset)
def holt(close: object, period: int = 14, gamma: float = 0.7, offset: int = 0, **kwargs) -> object:
"""Holt Exponential Smoothing."""
period = int(period)
gamma = float(gamma)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_holt(_ptr(src), _ptr(output), n, period, gamma))
return _wrap(output, idx, f"HOLT_{period}", "trends_iir", offset)
def htit(close: object, offset: int = 0, **kwargs) -> object:
"""Hilbert Transform Instantaneous Trendline."""
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_htit(_ptr(src), _ptr(output), n))
return _wrap(output, idx, "HTIT", "trends_iir", offset)
def hwma(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Holt-Winter Moving Average."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_hwma(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"HWMA_{period}", "trends_iir", offset)
def jma(close: object, period: int = 14, phase: int = 0, power: float = 1.0, offset: int = 0, **kwargs) -> object:
"""Jurik Moving Average."""
period = int(period)
phase = int(phase)
power = float(power)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_jma(_ptr(src), _ptr(output), n, period, phase, power))
return _wrap(output, idx, f"JMA_{period}", "trends_iir", offset)
def kama(close: object, period: int = 14, fastPeriod: int = 12, slowPeriod: int = 26, offset: int = 0, **kwargs) -> object:
"""Kaufman Adaptive Moving Average."""
period = int(period)
fastPeriod = int(fastPeriod)
slowPeriod = int(slowPeriod)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_kama(_ptr(src), _ptr(output), n, period, fastPeriod, slowPeriod))
return _wrap(output, idx, f"KAMA_{period}", "trends_iir", offset)
def ltma(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Low-Lag Triple Moving Average."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_ltma(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"LTMA_{period}", "trends_iir", offset)
def mama(close: object, fastLimit: float = 0.5, slowLimit: float = 0.05, offset: int = 0, **kwargs) -> object:
"""MESA Adaptive Moving Average."""
fastLimit = float(fastLimit)
slowLimit = float(slowLimit)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
famaOutput = _out(n)
_check(_lib.qtl_mama(_ptr(src), _ptr(output), fastLimit, n, slowLimit, _ptr(famaOutput)))
return _wrap_multi({"output": output, "famaOutput": famaOutput}, idx, "trends_iir", offset)
def mavp(x: object, periods: object, minPeriod: int = 6, maxPeriod: int = 48, offset: int = 0, **kwargs) -> object:
"""Moving Average Variable Period."""
minPeriod = int(minPeriod)
maxPeriod = int(maxPeriod)
offset = int(offset)
xarr, idx = _arr(x); yarr, _ = _arr(periods)
n = len(xarr)
output = _out(n)
_check(_lib.qtl_mavp(_ptr(xarr), _ptr(yarr), _ptr(output), n, minPeriod, maxPeriod))
return _wrap(output, idx, f"MAVP_{minPeriod}", "trends_iir", offset)
def mcnma(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""McNicholl Moving Average."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_mcnma(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"MCNMA_{period}", "trends_iir", offset)
def mgdi(close: object, period: int = 14, k: float = 2.0, offset: int = 0, **kwargs) -> object:
"""McGinley Dynamic."""
period = int(period)
k = float(k)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_mgdi(_ptr(src), _ptr(output), n, period, k))
return _wrap(output, idx, f"MGDI_{period}", "trends_iir", offset)
def mma(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Modified Moving Average."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_mma(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"MMA_{period}", "trends_iir", offset)
def nma(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Normalized Moving Average."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_nma(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"NMA_{period}", "trends_iir", offset)
def qema(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Quadruple EMA."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_qema(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"QEMA_{period}", "trends_iir", offset)
def rema(close: object, period: int = 14, lam: float = 1600.0, offset: int = 0, **kwargs) -> object:
"""Regularized EMA."""
period = int(period)
lam = float(lam)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_rema(_ptr(src), _ptr(output), n, period, lam))
return _wrap(output, idx, f"REMA_{period}", "trends_iir", offset)
def rgma(close: object, period: int = 14, passes: int = 3, offset: int = 0, **kwargs) -> object:
"""Recursive Gaussian Moving Average."""
period = int(period)
passes = int(passes)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_rgma(_ptr(src), _ptr(output), n, period, passes))
return _wrap(output, idx, f"RGMA_{period}", "trends_iir", offset)
def rma(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Rolling Moving Average."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_rma(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"RMA_{period}", "trends_iir", offset)
def t3(close: object, period: int = 14, vfactor: float = 0.7, offset: int = 0, **kwargs) -> object:
"""Tillson T3."""
period = int(period)
vfactor = float(vfactor)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_t3(_ptr(src), _ptr(output), n, period, vfactor))
return _wrap(output, idx, f"T3_{period}", "trends_iir", offset)
def trama(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Triangular Adaptive Moving Average."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_trama(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"TRAMA_{period}", "trends_iir", offset)
def vama(open: object, high: object, low: object, close: object, volume: object, baseLength: int = 20, shortAtrPeriod: int = 14, longAtrPeriod: int = 50, minLength: int = 5, maxLength: int = 50, offset: int = 0, **kwargs) -> object:
"""Volume Adjusted Moving Average."""
baseLength = int(baseLength)
shortAtrPeriod = int(shortAtrPeriod)
longAtrPeriod = int(longAtrPeriod)
minLength = int(minLength)
maxLength = int(maxLength)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(_lib.qtl_vama(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), baseLength, shortAtrPeriod, longAtrPeriod, minLength, maxLength, n, _ptr(dst)))
return _wrap(dst, idx, f"VAMA_{baseLength}", "trends_iir", offset)
def vidya(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Variable Index Dynamic Average."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_vidya(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"VIDYA_{period}", "trends_iir", offset)
def yzvama(open: object, high: object, low: object, close: object, volume: object, yzvShortPeriod: int = 10, yzvLongPeriod: int = 100, percentileLookback: int = 252, minLength: int = 5, maxLength: int = 50, offset: int = 0, **kwargs) -> object:
"""Yang Zhang Volatility Adaptive MA."""
yzvShortPeriod = int(yzvShortPeriod)
yzvLongPeriod = int(yzvLongPeriod)
percentileLookback = int(percentileLookback)
minLength = int(minLength)
maxLength = int(maxLength)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(_lib.qtl_yzvama(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), yzvShortPeriod, yzvLongPeriod, percentileLookback, minLength, maxLength, n, _ptr(dst)))
return _wrap(dst, idx, f"YZVAMA_{yzvShortPeriod}", "trends_iir", offset)
def zldema(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Zero-Lag Double EMA."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_zldema(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"ZLDEMA_{period}", "trends_iir", offset)
def zlema(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Zero-Lag EMA."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_zlema(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"ZLEMA_{period}", "trends_iir", offset)
def zltema(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Zero-Lag Triple EMA."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_zltema(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"ZLTEMA_{period}", "trends_iir", offset)
def ema(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Exponential Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_ema(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"EMA_{length}", "trends_iir", offset)
def ema_alpha(close: object, alpha: float = 0.1, offset: int = 0, **kwargs) -> object:
"""EMA with explicit alpha."""
offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_ema_alpha(_ptr(src), n, _ptr(dst), float(alpha)))
return _wrap(dst, idx, f"EMA_a{alpha:.4f}", "trends_iir", offset)
def dema(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Double Exponential Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_dema(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"DEMA_{length}", "trends_iir", offset)
def dema_alpha(close: object, alpha: float = 0.1, offset: int = 0, **kwargs) -> object:
"""DEMA with explicit alpha."""
offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_dema_alpha(_ptr(src), n, _ptr(dst), float(alpha)))
return _wrap(dst, idx, f"DEMA_a{alpha:.4f}", "trends_iir", offset)
def tema(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Triple Exponential Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_tema(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"TEMA_{length}", "trends_iir", offset)
def lema(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Laguerre-based EMA."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_lema(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"LEMA_{length}", "trends_iir", offset)
def hema(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Henderson EMA."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_hema(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"HEMA_{length}", "trends_iir", offset)
def ahrens(close: object, length: int = 10, offset: int = 0, **kwargs) -> object:
"""Ahrens Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_ahrens(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"AHRENS_{length}", "trends_iir", offset)
def decycler(close: object, length: int = 20, offset: int = 0, **kwargs) -> object:
"""Simple Decycler."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_decycler(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"DECYCLER_{length}", "trends_iir", offset)
def dsma(close: object, length: int = 10, factor: float = 0.5,
offset: int = 0, **kwargs) -> object:
"""Deviation-Scaled Moving Average."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_dsma(_ptr(src), n, _ptr(dst), length, float(factor)))
return _wrap(dst, idx, f"DSMA_{length}", "trends_iir", offset)
def gdema(close: object, length: int = 10, vfactor: float = 1.0,
offset: int = 0, **kwargs) -> object:
"""Generalized DEMA."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_gdema(_ptr(src), n, _ptr(dst), length, float(vfactor)))
return _wrap(dst, idx, f"GDEMA_{length}", "trends_iir", offset)
def coral(close: object, length: int = 10, friction: float = 0.4,
offset: int = 0, **kwargs) -> object:
"""CORAL Trend."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_coral(_ptr(src), n, _ptr(dst), length, float(friction)))
return _wrap(dst, idx, f"CORAL_{length}", "trends_iir", offset)
def agc(close: object, alpha: float = 0.1, offset: int = 0, **kwargs) -> object:
"""Automatic Gain Control."""
offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_agc(_ptr(src), n, _ptr(dst), float(alpha)))
return _wrap(dst, idx, f"AGC_a{alpha:.4f}", "trends_iir", offset)
def ccyc(close: object, alpha: float = 0.1, offset: int = 0, **kwargs) -> object:
"""Cyber Cycle."""
offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_ccyc(_ptr(src), n, _ptr(dst), float(alpha)))
return _wrap(dst, idx, f"CCYC_a{alpha:.4f}", "trends_iir", offset)
+341
View File
@@ -0,0 +1,341 @@
"""quantalib volatility indicators.
Auto-generated DO NOT EDIT.
"""
from __future__ import annotations
from ._helpers import _arr, _ptr, _out, _wrap, _wrap_multi, _check, _lib
__all__ = [
"adr",
"atr",
"atrn",
"gkv",
"hlv",
"hv",
"jvolty",
"jvoltyn",
"massi",
"natr",
"rsv",
"rv",
"rvi",
"ui",
"vov",
"vr",
"yzv",
"tr",
"bbw",
"bbwn",
"bbwp",
"stddev",
"variance",
"etherm",
"ccv",
"cv",
"cvi",
"ewma",
]
def adr(open: object, high: object, low: object, close: object, volume: object, period: int = 14, method: int = 0, offset: int = 0, **kwargs) -> object:
"""Average Daily Range."""
period = int(period)
method = int(method)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(_lib.qtl_adr(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), period, method, n, _ptr(dst)))
return _wrap(dst, idx, f"ADR_{period}", "volatility", offset)
def atr(open: object, high: object, low: object, close: object, volume: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Average True Range."""
period = int(period)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(_lib.qtl_atr(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), period, n, _ptr(dst)))
return _wrap(dst, idx, f"ATR_{period}", "volatility", offset)
def atrn(open: object, high: object, low: object, close: object, volume: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Normalized ATR."""
period = int(period)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(_lib.qtl_atrn(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), period, n, _ptr(dst)))
return _wrap(dst, idx, f"ATRN_{period}", "volatility", offset)
def gkv(open: object, high: object, low: object, close: object, period: int = 14, annualize: int = 1, annualPeriods: int = 252, offset: int = 0, **kwargs) -> object:
"""Garman-Klass Volatility."""
period = int(period)
annualize = int(annualize)
annualPeriods = int(annualPeriods)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(o)
output = _out(n)
_check(_lib.qtl_gkv(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(output), n, period, annualize, annualPeriods))
return _wrap(output, idx, f"GKV_{period}", "volatility", offset)
def hlv(high: object, low: object, period: int = 14, annualize: int = 1, annualPeriods: int = 252, offset: int = 0, **kwargs) -> object:
"""High-Low Volatility."""
period = int(period)
annualize = int(annualize)
annualPeriods = int(annualPeriods)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low)
n = len(h)
output = _out(n)
_check(_lib.qtl_hlv(_ptr(h), _ptr(l), _ptr(output), n, period, annualize, annualPeriods))
return _wrap(output, idx, f"HLV_{period}", "volatility", offset)
def hv(close: object, period: int = 14, annualize: int = 1, annualPeriods: int = 252, offset: int = 0, **kwargs) -> object:
"""Historical Volatility."""
period = int(period)
annualize = int(annualize)
annualPeriods = int(annualPeriods)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_hv(_ptr(src), _ptr(output), n, period, annualize, annualPeriods))
return _wrap(output, idx, f"HV_{period}", "volatility", offset)
def jvolty(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Jurik Volatility."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_jvolty(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"JVOLTY_{period}", "volatility", offset)
def jvoltyn(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Jurik Volatility Normalized."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_jvoltyn(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"JVOLTYN_{period}", "volatility", offset)
def massi(close: object, emaLength: int = 9, sumLength: int = 25, offset: int = 0, **kwargs) -> object:
"""Mass Index."""
emaLength = int(emaLength)
sumLength = int(sumLength)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_massi(_ptr(src), _ptr(output), n, emaLength, sumLength))
return _wrap(output, idx, f"MASSI_{emaLength}", "volatility", offset)
def natr(open: object, high: object, low: object, close: object, volume: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Normalized ATR."""
period = int(period)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)
c, _ = _arr(close); v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(_lib.qtl_natr(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), period, n, _ptr(dst)))
return _wrap(dst, idx, f"NATR_{period}", "volatility", offset)
def rsv(open: object, high: object, low: object, close: object, period: int = 14, annualize: int = 1, annualPeriods: int = 252, offset: int = 0, **kwargs) -> object:
"""Rogers-Satchell Volatility."""
period = int(period)
annualize = int(annualize)
annualPeriods = int(annualPeriods)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(o)
output = _out(n)
_check(_lib.qtl_rsv(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(output), n, period, annualize, annualPeriods))
return _wrap(output, idx, f"RSV_{period}", "volatility", offset)
def rv(close: object, period: int = 14, smoothingPeriod: int = 14, annualize: int = 1, annualPeriods: int = 252, offset: int = 0, **kwargs) -> object:
"""Realized Volatility."""
period = int(period)
smoothingPeriod = int(smoothingPeriod)
annualize = int(annualize)
annualPeriods = int(annualPeriods)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_rv(_ptr(src), _ptr(output), n, period, smoothingPeriod, annualize, annualPeriods))
return _wrap(output, idx, f"RV_{period}", "volatility", offset)
def rvi(close: object, stdevLength: int = 10, rmaLength: int = 14, offset: int = 0, **kwargs) -> object:
"""Relative Volatility Index."""
stdevLength = int(stdevLength)
rmaLength = int(rmaLength)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_rvi(_ptr(src), _ptr(output), n, stdevLength, rmaLength))
return _wrap(output, idx, f"RVI_{stdevLength}", "volatility", offset)
def ui(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Ulcer Index."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_ui(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"UI_{period}", "volatility", offset)
def vov(close: object, volatilityPeriod: int = 20, vovPeriod: int = 20, offset: int = 0, **kwargs) -> object:
"""Volatility of Volatility."""
volatilityPeriod = int(volatilityPeriod)
vovPeriod = int(vovPeriod)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_vov(_ptr(src), _ptr(output), n, volatilityPeriod, vovPeriod))
return _wrap(output, idx, f"VOV_{volatilityPeriod}", "volatility", offset)
def vr(high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Volatility Ratio."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
output = _out(n)
_check(_lib.qtl_vr(_ptr(h), _ptr(l), _ptr(c), _ptr(output), n, period))
return _wrap(output, idx, f"VR_{period}", "volatility", offset)
def yzv(open: object, high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Yang-Zhang Volatility."""
period = int(period)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(o)
output = _out(n)
_check(_lib.qtl_yzv(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(output), n, period))
return _wrap(output, idx, f"YZV_{period}", "volatility", offset)
def tr(high: object, low: object, close: object, offset: int = 0, **kwargs) -> object:
"""True Range."""
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h); dst = _out(n)
_check(_lib.qtl_tr(_ptr(h), _ptr(l), _ptr(c), n, _ptr(dst)))
return _wrap(dst, idx, "TR", "volatility", int(offset))
def bbw(close: object, length: int = 20, mult: float = 2.0,
offset: int = 0, **kwargs) -> object:
"""Bollinger Band Width."""
length = int(length); mult = float(mult); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_bbw(_ptr(src), n, _ptr(dst), length, mult))
return _wrap(dst, idx, f"BBW_{length}", "volatility", offset)
def bbwn(close: object, length: int = 20, mult: float = 2.0,
lookback: int = 252, offset: int = 0, **kwargs) -> object:
"""Bollinger Band Width Normalized."""
length = int(length); mult = float(mult); lookback = int(lookback); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_bbwn(_ptr(src), n, _ptr(dst), length, mult, lookback))
return _wrap(dst, idx, f"BBWN_{length}", "volatility", offset)
def bbwp(close: object, length: int = 20, mult: float = 2.0,
lookback: int = 252, offset: int = 0, **kwargs) -> object:
"""Bollinger Band Width Percentile."""
length = int(length); mult = float(mult); lookback = int(lookback); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_bbwp(_ptr(src), n, _ptr(dst), length, mult, lookback))
return _wrap(dst, idx, f"BBWP_{length}", "volatility", offset)
def stddev(close: object, length: int = 20, offset: int = 0, **kwargs) -> object:
"""Standard Deviation."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_stddev(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"STDDEV_{length}", "volatility", offset)
def variance(close: object, length: int = 20, offset: int = 0, **kwargs) -> object:
"""Variance."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_variance(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"VAR_{length}", "volatility", offset)
def etherm(high: object, low: object, length: int = 14,
offset: int = 0, **kwargs) -> object:
"""Elder Thermometer."""
length = int(length)
h, idx = _arr(high); l, _ = _arr(low)
n = len(h); dst = _out(n)
_check(_lib.qtl_etherm(_ptr(h), _ptr(l), n, _ptr(dst), length))
return _wrap(dst, idx, f"ETHERM_{length}", "volatility", int(offset))
def ccv(close: object, short_period: int = 20, long_period: int = 1,
offset: int = 0, **kwargs) -> object:
"""Close-to-Close Volatility."""
short_period = int(short_period); long_period = int(long_period); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_ccv(_ptr(src), n, _ptr(dst), short_period, long_period))
return _wrap(dst, idx, f"CCV_{short_period}", "volatility", offset)
def cv(close: object, length: int = 20, min_vol: float = 0.2,
max_vol: float = 0.7, offset: int = 0, **kwargs) -> object:
"""Coefficient of Variation."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_cv(_ptr(src), n, _ptr(dst), length, float(min_vol), float(max_vol)))
return _wrap(dst, idx, f"CV_{length}", "volatility", offset)
def cvi(close: object, ema_period: int = 10, roc_period: int = 10,
offset: int = 0, **kwargs) -> object:
"""Chaikin Volatility Index."""
ema_period = int(ema_period); roc_period = int(roc_period); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_cvi(_ptr(src), n, _ptr(dst), ema_period, roc_period))
return _wrap(dst, idx, f"CVI_{ema_period}", "volatility", offset)
def ewma(close: object, length: int = 20, is_pop: int = 1,
ann_factor: int = 252, offset: int = 0, **kwargs) -> object:
"""Exponentially Weighted Moving Average (volatility)."""
length = int(length); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_ewma(_ptr(src), n, _ptr(dst), length, int(is_pop), int(ann_factor)))
return _wrap(dst, idx, f"EWMA_{length}", "volatility", offset)
+317
View File
@@ -0,0 +1,317 @@
"""quantalib volume indicators.
Auto-generated DO NOT EDIT.
"""
from __future__ import annotations
from ._helpers import _arr, _ptr, _out, _wrap, _wrap_multi, _check, _lib
__all__ = [
"adl",
"adosc",
"iii",
"kvo",
"twap",
"va",
"vo",
"vroc",
"vwad",
"vwap",
"wad",
"obv",
"pvt",
"pvr",
"vf",
"nvi",
"pvi",
"tvi",
"pvd",
"vwma",
"evwma",
"efi",
"aobv",
"mfi",
"cmf",
"eom",
"pvo",
]
def adl(high: object, low: object, close: object, volume: object, offset: int = 0, **kwargs) -> object:
"""Accumulation/Distribution Line."""
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close); v, _ = _arr(volume)
n = len(h)
output = _out(n)
_check(_lib.qtl_adl(_ptr(h), _ptr(l), _ptr(c), _ptr(v), _ptr(output), n))
return _wrap(output, idx, "ADL", "volume", offset)
def adosc(high: object, low: object, close: object, volume: object, fastPeriod: int = 12, slowPeriod: int = 26, offset: int = 0, **kwargs) -> object:
"""Accumulation/Distribution Oscillator."""
fastPeriod = int(fastPeriod)
slowPeriod = int(slowPeriod)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close); v, _ = _arr(volume)
n = len(h)
output = _out(n)
_check(_lib.qtl_adosc(_ptr(h), _ptr(l), _ptr(c), _ptr(v), _ptr(output), n, fastPeriod, slowPeriod))
return _wrap(output, idx, f"ADOSC_{fastPeriod}", "volume", offset)
def iii(high: object, low: object, close: object, volume: object, period: int = 14, cumulative: int = 0, offset: int = 0, **kwargs) -> object:
"""Intraday Intensity Index."""
period = int(period)
cumulative = int(cumulative)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close); v, _ = _arr(volume)
n = len(h)
output = _out(n)
_check(_lib.qtl_iii(_ptr(h), _ptr(l), _ptr(c), _ptr(v), _ptr(output), n, period, cumulative))
return _wrap(output, idx, f"III_{period}", "volume", offset)
def kvo(high: object, low: object, close: object, volume: object, fastPeriod: int = 12, slowPeriod: int = 26, signalPeriod: int = 9, offset: int = 0, **kwargs) -> object:
"""Klinger Volume Oscillator."""
fastPeriod = int(fastPeriod)
slowPeriod = int(slowPeriod)
signalPeriod = int(signalPeriod)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close); v, _ = _arr(volume)
n = len(h)
output = _out(n)
signal = _out(n)
_check(_lib.qtl_kvo(_ptr(h), _ptr(l), _ptr(c), _ptr(v), _ptr(output), _ptr(signal), n, fastPeriod, slowPeriod, signalPeriod))
return _wrap_multi({"output": output, "signal": signal}, idx, "volume", offset)
def twap(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Time Weighted Average Price."""
period = int(period)
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_twap(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"TWAP_{period}", "volume", offset)
def va(high: object, low: object, close: object, volume: object, offset: int = 0, **kwargs) -> object:
"""Volume Accumulation."""
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close); v, _ = _arr(volume)
n = len(h)
output = _out(n)
_check(_lib.qtl_va(_ptr(h), _ptr(l), _ptr(c), _ptr(v), _ptr(output), n))
return _wrap(output, idx, "VA", "volume", offset)
def vo(volume: object, shortPeriod: int = 12, longPeriod: int = 26, offset: int = 0, **kwargs) -> object:
"""Volume Oscillator."""
shortPeriod = int(shortPeriod)
longPeriod = int(longPeriod)
offset = int(offset)
src, idx = _arr(volume)
n = len(src)
output = _out(n)
_check(_lib.qtl_vo(_ptr(src), _ptr(output), n, shortPeriod, longPeriod))
return _wrap(output, idx, f"VO_{shortPeriod}", "volume", offset)
def vroc(volume: object, period: int = 14, usePercent: int = 1, offset: int = 0, **kwargs) -> object:
"""Volume Rate of Change."""
period = int(period)
usePercent = int(usePercent)
offset = int(offset)
src, idx = _arr(volume)
n = len(src)
output = _out(n)
_check(_lib.qtl_vroc(_ptr(src), _ptr(output), n, period, usePercent))
return _wrap(output, idx, f"VROC_{period}", "volume", offset)
def vwad(high: object, low: object, close: object, volume: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Volume Weighted Accumulation/Distribution."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close); v, _ = _arr(volume)
n = len(h)
output = _out(n)
_check(_lib.qtl_vwad(_ptr(h), _ptr(l), _ptr(c), _ptr(v), _ptr(output), n, period))
return _wrap(output, idx, f"VWAD_{period}", "volume", offset)
def vwap(high: object, low: object, close: object, volume: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Volume Weighted Average Price."""
period = int(period)
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close); v, _ = _arr(volume)
n = len(h)
output = _out(n)
_check(_lib.qtl_vwap(_ptr(h), _ptr(l), _ptr(c), _ptr(v), _ptr(output), n, period))
return _wrap(output, idx, f"VWAP_{period}", "volume", offset)
def wad(high: object, low: object, close: object, volume: object, offset: int = 0, **kwargs) -> object:
"""Williams Accumulation/Distribution."""
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close); v, _ = _arr(volume)
n = len(h)
output = _out(n)
_check(_lib.qtl_wad(_ptr(h), _ptr(l), _ptr(c), _ptr(v), _ptr(output), n))
return _wrap(output, idx, "WAD", "volume", offset)
def obv(close: object, volume: object, offset: int = 0, **kwargs) -> object:
"""On-Balance Volume."""
offset = int(offset)
c, idx = _arr(close); v, _ = _arr(volume)
n = len(c); dst = _out(n)
_check(_lib.qtl_obv(_ptr(c), _ptr(v), n, _ptr(dst)))
return _wrap(dst, idx, "OBV", "volume", offset)
def pvt(close: object, volume: object, offset: int = 0, **kwargs) -> object:
"""Price Volume Trend."""
offset = int(offset)
c, idx = _arr(close); v, _ = _arr(volume)
n = len(c); dst = _out(n)
_check(_lib.qtl_pvt(_ptr(c), _ptr(v), n, _ptr(dst)))
return _wrap(dst, idx, "PVT", "volume", offset)
def pvr(close: object, volume: object, offset: int = 0, **kwargs) -> object:
"""Price Volume Rank."""
offset = int(offset)
c, idx = _arr(close); v, _ = _arr(volume)
n = len(c); dst = _out(n)
_check(_lib.qtl_pvr(_ptr(c), _ptr(v), n, _ptr(dst)))
return _wrap(dst, idx, "PVR", "volume", offset)
def vf(close: object, volume: object, offset: int = 0, **kwargs) -> object:
"""Volume Flow."""
offset = int(offset)
c, idx = _arr(close); v, _ = _arr(volume)
n = len(c); dst = _out(n)
_check(_lib.qtl_vf(_ptr(c), _ptr(v), n, _ptr(dst)))
return _wrap(dst, idx, "VF", "volume", offset)
def nvi(close: object, volume: object, offset: int = 0, **kwargs) -> object:
"""Negative Volume Index."""
offset = int(offset)
c, idx = _arr(close); v, _ = _arr(volume)
n = len(c); dst = _out(n)
_check(_lib.qtl_nvi(_ptr(c), _ptr(v), n, _ptr(dst)))
return _wrap(dst, idx, "NVI", "volume", offset)
def pvi(close: object, volume: object, offset: int = 0, **kwargs) -> object:
"""Positive Volume Index."""
offset = int(offset)
c, idx = _arr(close); v, _ = _arr(volume)
n = len(c); dst = _out(n)
_check(_lib.qtl_pvi(_ptr(c), _ptr(v), n, _ptr(dst)))
return _wrap(dst, idx, "PVI", "volume", offset)
def tvi(close: object, volume: object, length: int = 14,
offset: int = 0, **kwargs) -> object:
"""Trade Volume Index."""
length = int(length); offset = int(offset)
c, idx = _arr(close); v, _ = _arr(volume)
n = len(c); dst = _out(n)
_check(_lib.qtl_tvi(_ptr(c), _ptr(v), n, _ptr(dst), length))
return _wrap(dst, idx, f"TVI_{length}", "volume", offset)
def pvd(close: object, volume: object, length: int = 14,
offset: int = 0, **kwargs) -> object:
"""Price Volume Divergence."""
length = int(length); offset = int(offset)
c, idx = _arr(close); v, _ = _arr(volume)
n = len(c); dst = _out(n)
_check(_lib.qtl_pvd(_ptr(c), _ptr(v), n, _ptr(dst), length))
return _wrap(dst, idx, f"PVD_{length}", "volume", offset)
def vwma(close: object, volume: object, length: int = 20,
offset: int = 0, **kwargs) -> object:
"""Volume Weighted Moving Average."""
length = int(length); offset = int(offset)
c, idx = _arr(close); v, _ = _arr(volume)
n = len(c); dst = _out(n)
_check(_lib.qtl_vwma(_ptr(c), _ptr(v), n, _ptr(dst), length))
return _wrap(dst, idx, f"VWMA_{length}", "volume", offset)
def evwma(close: object, volume: object, length: int = 20,
offset: int = 0, **kwargs) -> object:
"""Elastic Volume Weighted Moving Average."""
length = int(length); offset = int(offset)
c, idx = _arr(close); v, _ = _arr(volume)
n = len(c); dst = _out(n)
_check(_lib.qtl_evwma(_ptr(c), _ptr(v), n, _ptr(dst), length))
return _wrap(dst, idx, f"EVWMA_{length}", "volume", offset)
def efi(close: object, volume: object, length: int = 13,
offset: int = 0, **kwargs) -> object:
"""Elder Force Index."""
length = int(length); offset = int(offset)
c, idx = _arr(close); v, _ = _arr(volume)
n = len(c); dst = _out(n)
_check(_lib.qtl_efi(_ptr(c), _ptr(v), n, _ptr(dst), length))
return _wrap(dst, idx, f"EFI_{length}", "volume", offset)
def aobv(close: object, volume: object, offset: int = 0, **kwargs) -> object:
"""Archer OBV -> (fast, slow) or DataFrame."""
offset = int(offset)
c, idx = _arr(close); v, _ = _arr(volume)
n = len(c); obv_out = _out(n); sig = _out(n)
_check(_lib.qtl_aobv(_ptr(c), _ptr(v), n, _ptr(obv_out), _ptr(sig)))
return _wrap_multi({"AOBV": obv_out, "AOBV_SIG": sig}, idx, "volume", offset)
def mfi(high: object, low: object, close: object, volume: object,
length: int = 14, offset: int = 0, **kwargs) -> object:
"""Money Flow Index."""
length = int(length); offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close); v, _ = _arr(volume)
n = len(h); dst = _out(n)
_check(_lib.qtl_mfi(_ptr(h), _ptr(l), _ptr(c), _ptr(v), n, _ptr(dst), length))
return _wrap(dst, idx, f"MFI_{length}", "volume", offset)
def cmf(high: object, low: object, close: object, volume: object,
length: int = 20, offset: int = 0, **kwargs) -> object:
"""Chaikin Money Flow."""
length = int(length); offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close); v, _ = _arr(volume)
n = len(h); dst = _out(n)
_check(_lib.qtl_cmf(_ptr(h), _ptr(l), _ptr(c), _ptr(v), n, _ptr(dst), length))
return _wrap(dst, idx, f"CMF_{length}", "volume", offset)
def eom(high: object, low: object, volume: object,
length: int = 14, offset: int = 0, **kwargs) -> object:
"""Ease of Movement."""
length = int(length); offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); v, _ = _arr(volume)
n = len(h); dst = _out(n)
_check(_lib.qtl_eom(_ptr(h), _ptr(l), _ptr(v), n, _ptr(dst), length, 1e9))
return _wrap(dst, idx, f"EOM_{length}", "volume", offset)
def pvo(volume: object, fast: int = 12, slow: int = 26, signal: int = 9,
offset: int = 0, **kwargs) -> object:
"""Percentage Volume Oscillator -> (pvo, signal, histogram) or DataFrame."""
fast = int(fast); slow = int(slow); signal = int(signal); offset = int(offset)
v, idx = _arr(volume); n = len(v)
pvo_out = _out(n); sig = _out(n); hist = _out(n)
_check(_lib.qtl_pvo(_ptr(v), n, _ptr(pvo_out), _ptr(sig), _ptr(hist), fast, slow, signal))
return _wrap_multi(
{f"PVO_{fast}_{slow}_{signal}": pvo_out, f"PVOs_{fast}_{slow}_{signal}": sig, f"PVOh_{fast}_{slow}_{signal}": hist},
idx, "volume", offset)
+44
View File
@@ -0,0 +1,44 @@
"""test_category_labels.py — Verify consistent category labels across all modules."""
from __future__ import annotations
import importlib
import inspect
import re
import pytest
CATEGORY_MODULES = {
"quantalib.channels": "channels",
"quantalib.core": "core",
"quantalib.cycles": "cycles",
"quantalib.dynamics": "dynamics",
"quantalib.errors": "errors",
"quantalib.filters": "filters",
"quantalib.momentum": "momentum",
"quantalib.numerics": "numerics",
"quantalib.oscillators": "oscillators",
"quantalib.reversals": "reversals",
"quantalib.statistics": "statistics",
"quantalib.trends_fir": "trends_fir",
"quantalib.trends_iir": "trends_iir",
"quantalib.volatility": "volatility",
"quantalib.volume": "volume",
}
# Regex to match _wrap(..., "CATEGORY", ...) or _wrap_multi(..., "CATEGORY", ...)
LABEL_PATTERN = re.compile(r'_wrap(?:_multi)?\(.*?,\s*"([^"]+)",\s*(?:offset|[\w]+)\)')
@pytest.mark.parametrize("modname,expected", CATEGORY_MODULES.items(), ids=lambda x: x.split(".")[-1] if "." in x else x)
def test_category_labels_lowercase(modname: str, expected: str) -> None:
"""Category labels passed to _wrap/_wrap_multi must be lowercase."""
mod = importlib.import_module(modname)
source_file = inspect.getfile(mod)
with open(source_file, "r", encoding="utf-8") as f:
source = f.read()
# Find all category labels in source
labels = LABEL_PATTERN.findall(source)
bad = [lbl for lbl in labels if lbl != expected]
assert bad == [], (
f"{modname}: expected category label '{expected}', found non-matching: {set(bad)}"
)
+45
View File
@@ -0,0 +1,45 @@
"""test_compat.py — pandas-ta compatibility alias tests."""
from __future__ import annotations
import pytest
from quantalib._compat import ALIASES, get_compat
class TestAliases:
"""Validate ALIASES mapping and get_compat resolution."""
def test_aliases_is_dict(self) -> None:
assert isinstance(ALIASES, dict)
assert len(ALIASES) > 0
def test_all_aliases_are_strings(self) -> None:
for key, val in ALIASES.items():
assert isinstance(key, str), f"Key {key!r} is not str"
assert isinstance(val, str), f"Value {val!r} for key {key!r} is not str"
@pytest.mark.parametrize(
"alias,target",
[
("midprice", "medprice"),
("momentum", "mom"),
("simple_moving_average", "sma"),
("true_range", "tr"),
("on_balance_volume", "obv"),
("bollinger_bands", "bbands"),
("z_score", "zscore"),
],
)
def test_known_aliases(self, alias: str, target: str) -> None:
assert ALIASES[alias] == target
def test_get_compat_unknown_returns_none(self) -> None:
result = get_compat("nonexistent_indicator_xyz")
assert result is None
def test_get_compat_known_returns_callable(self) -> None:
fn = get_compat("simple_moving_average")
# May be None if native lib not available, but function itself resolves
# We just test the lookup mechanism works
if fn is not None:
assert callable(fn)
+194
View File
@@ -0,0 +1,194 @@
"""test_helpers.py — Unit tests for quantalib._helpers (no native lib needed)."""
from __future__ import annotations
import numpy as np
import pytest
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _has_pandas() -> bool:
try:
import pandas # noqa: F401
return True
except ImportError:
return False
# ---------------------------------------------------------------------------
# _arr
# ---------------------------------------------------------------------------
class TestArr:
"""Tests for _arr() input coercion and validation."""
def test_list_to_float64(self) -> None:
from quantalib._helpers import _arr
arr, idx = _arr([1.0, 2.0, 3.0])
assert arr.dtype == np.float64
assert idx is None
np.testing.assert_array_equal(arr, [1.0, 2.0, 3.0])
def test_int_array_coerced(self) -> None:
from quantalib._helpers import _arr
arr, _ = _arr(np.array([1, 2, 3]))
assert arr.dtype == np.float64
def test_contiguous_no_copy(self) -> None:
from quantalib._helpers import _arr
src = np.array([1.0, 2.0, 3.0], dtype=np.float64)
arr, _ = _arr(src)
# Already contiguous float64 — should share memory
assert np.shares_memory(arr, src)
def test_non_contiguous_made_contiguous(self) -> None:
from quantalib._helpers import _arr
src = np.array([1.0, 2.0, 3.0, 4.0], dtype=np.float64)[::2]
assert not src.flags["C_CONTIGUOUS"]
arr, _ = _arr(src)
assert arr.flags["C_CONTIGUOUS"]
def test_none_raises(self) -> None:
from quantalib._helpers import _arr
with pytest.raises(ValueError, match="must not be None"):
_arr(None)
def test_empty_raises(self) -> None:
from quantalib._helpers import _arr
with pytest.raises(ValueError, match="must not be empty"):
_arr(np.array([], dtype=np.float64))
def test_scalar_raises(self) -> None:
from quantalib._helpers import _arr
with pytest.raises(ValueError, match="must not be empty"):
_arr(np.float64(42.0))
@pytest.mark.skipif(not _has_pandas(), reason="pandas not installed")
def test_pandas_series_preserves_index(self) -> None:
import pandas as pd
from quantalib._helpers import _arr
idx = pd.date_range("2020-01-01", periods=5)
s = pd.Series([1.0, 2.0, 3.0, 4.0, 5.0], index=idx)
arr, ridx = _arr(s)
assert arr.dtype == np.float64
assert ridx is idx
@pytest.mark.skipif(not _has_pandas(), reason="pandas not installed")
def test_pandas_dataframe_uses_first_col(self) -> None:
import pandas as pd
from quantalib._helpers import _arr
df = pd.DataFrame({"a": [1.0, 2.0], "b": [3.0, 4.0]})
arr, idx = _arr(df)
np.testing.assert_array_equal(arr, [1.0, 2.0])
# ---------------------------------------------------------------------------
# _offset
# ---------------------------------------------------------------------------
class TestOffset:
"""Tests for _offset() roll + NaN fill."""
def test_zero_offset_noop(self) -> None:
from quantalib._helpers import _offset
arr = np.array([1.0, 2.0, 3.0])
result = _offset(arr, 0)
np.testing.assert_array_equal(result, arr)
def test_positive_offset(self) -> None:
from quantalib._helpers import _offset
arr = np.array([1.0, 2.0, 3.0, 4.0])
result = _offset(arr, 2)
assert np.isnan(result[0])
assert np.isnan(result[1])
assert result[2] == 1.0
assert result[3] == 2.0
def test_negative_offset(self) -> None:
from quantalib._helpers import _offset
arr = np.array([1.0, 2.0, 3.0, 4.0])
result = _offset(arr, -1)
assert result[0] == 2.0
assert result[1] == 3.0
assert result[2] == 4.0
assert np.isnan(result[3])
# ---------------------------------------------------------------------------
# _wrap and _wrap_multi
# ---------------------------------------------------------------------------
class TestWrap:
"""Tests for _wrap() and _wrap_multi()."""
def test_wrap_numpy_no_offset(self) -> None:
from quantalib._helpers import _wrap
arr = np.array([10.0, 20.0, 30.0])
result = _wrap(arr, None, "TEST", "cat", 0)
assert isinstance(result, np.ndarray)
np.testing.assert_array_equal(result, arr)
def test_wrap_numpy_with_offset(self) -> None:
from quantalib._helpers import _wrap
arr = np.array([10.0, 20.0, 30.0])
result = _wrap(arr, None, "TEST", "cat", 1)
assert np.isnan(result[0])
assert result[1] == 10.0
@pytest.mark.skipif(not _has_pandas(), reason="pandas not installed")
def test_wrap_pandas_series_category_in_attrs(self) -> None:
import pandas as pd
from quantalib._helpers import _wrap
idx = pd.RangeIndex(3)
arr = np.array([10.0, 20.0, 30.0])
result = _wrap(arr, idx, "SMA_10", "trends_fir", 0)
assert isinstance(result, pd.Series)
assert result.name == "SMA_10"
assert result.attrs["category"] == "trends_fir"
def test_wrap_multi_numpy(self) -> None:
from quantalib._helpers import _wrap_multi
arrays = {
"upper": np.array([1.0, 2.0]),
"lower": np.array([0.5, 1.0]),
}
result = _wrap_multi(arrays, None, "cat", 0)
assert isinstance(result, tuple)
assert len(result) == 2
@pytest.mark.skipif(not _has_pandas(), reason="pandas not installed")
def test_wrap_multi_pandas_attrs(self) -> None:
import pandas as pd
from quantalib._helpers import _wrap_multi
idx = pd.RangeIndex(2)
arrays = {
"upper": np.array([1.0, 2.0]),
"lower": np.array([0.5, 1.0]),
}
result = _wrap_multi(arrays, idx, "channels", 0)
assert isinstance(result, pd.DataFrame)
assert result.attrs["category"] == "channels"
# ---------------------------------------------------------------------------
# _out
# ---------------------------------------------------------------------------
class TestOut:
"""Tests for _out() allocation."""
def test_out_shape_and_dtype(self) -> None:
from quantalib._helpers import _out
arr = _out(100)
assert arr.shape == (100,)
assert arr.dtype == np.float64
# ---------------------------------------------------------------------------
# _ptr
# ---------------------------------------------------------------------------
class TestPtr:
"""Tests for _ptr() ctypes pointer extraction."""
def test_ptr_not_none(self) -> None:
from quantalib._helpers import _ptr
arr = np.array([1.0, 2.0, 3.0], dtype=np.float64)
p = _ptr(arr)
assert p is not None
+41
View File
@@ -0,0 +1,41 @@
"""test_module_imports.py — Verify all category modules import without SyntaxError."""
from __future__ import annotations
import importlib
import pytest
# Every module that must be importable (no native lib required at import time
# because all native calls are deferred to function invocation).
MODULES = [
"quantalib._helpers",
"quantalib._compat",
"quantalib._loader",
"quantalib._bridge",
"quantalib.channels",
"quantalib.core",
"quantalib.cycles",
"quantalib.dynamics",
"quantalib.errors",
"quantalib.filters",
"quantalib.momentum",
"quantalib.numerics",
"quantalib.oscillators",
"quantalib.reversals",
"quantalib.statistics",
"quantalib.trends_fir",
"quantalib.trends_iir",
"quantalib.volatility",
"quantalib.volume",
"quantalib.indicators",
]
@pytest.mark.parametrize("modname", MODULES, ids=lambda m: m.split(".")[-1])
def test_module_imports(modname: str) -> None:
"""Each module must import without SyntaxError or ImportError.
This catches reserved-keyword parameter names (lambda), duplicate
parameter names, and broken imports.
"""
mod = importlib.import_module(modname)
assert mod is not None
+117
View File
@@ -0,0 +1,117 @@
"""test_signatures.py — Verify function signatures have no reserved keywords or duplicates."""
from __future__ import annotations
import importlib
import inspect
import keyword
import pytest
# All category modules with public indicator functions
CATEGORY_MODULES = [
"quantalib.channels",
"quantalib.core",
"quantalib.cycles",
"quantalib.dynamics",
"quantalib.errors",
"quantalib.filters",
"quantalib.momentum",
"quantalib.numerics",
"quantalib.oscillators",
"quantalib.reversals",
"quantalib.statistics",
"quantalib.trends_fir",
"quantalib.trends_iir",
"quantalib.volatility",
"quantalib.volume",
]
def _get_public_functions():
"""Yield (module_name, func_name, func) for all public functions."""
for modname in CATEGORY_MODULES:
mod = importlib.import_module(modname)
all_names = getattr(mod, "__all__", [])
for name in all_names:
fn = getattr(mod, name, None)
if fn is not None and callable(fn):
yield modname, name, fn
@pytest.fixture(scope="module")
def all_functions():
return list(_get_public_functions())
class TestNoReservedKeywords:
"""No function parameter should use a Python reserved keyword."""
def test_no_reserved_keyword_params(self, all_functions) -> None:
violations = []
for modname, fname, fn in all_functions:
sig = inspect.signature(fn)
for pname in sig.parameters:
if keyword.iskeyword(pname):
violations.append(f"{modname}.{fname}(... {pname} ...)")
assert violations == [], (
f"Reserved keyword used as parameter name:\n"
+ "\n".join(f" - {v}" for v in violations)
)
class TestNoDuplicateParams:
"""No function should have duplicate parameter names (caught at parse time,
but this validates post-fix)."""
def test_no_duplicate_params(self, all_functions) -> None:
violations = []
for modname, fname, fn in all_functions:
sig = inspect.signature(fn)
params = list(sig.parameters.keys())
if len(params) != len(set(params)):
seen = set()
dupes = [p for p in params if p in seen or seen.add(p)] # type: ignore[func-returns-value]
violations.append(f"{modname}.{fname}: duplicates={dupes}")
assert violations == [], (
f"Duplicate parameter names found:\n"
+ "\n".join(f" - {v}" for v in violations)
)
class TestNoBuiltinShadowing:
"""Public function names should not shadow critical Python builtins."""
CRITICAL_BUILTINS = {"super", "type", "id", "input", "print", "open", "list", "dict", "set", "map", "filter"}
def test_no_builtin_function_names(self, all_functions) -> None:
violations = []
for modname, fname, fn in all_functions:
if fname in self.CRITICAL_BUILTINS:
violations.append(f"{modname}.{fname}")
assert violations == [], (
f"Function names shadow Python builtins:\n"
+ "\n".join(f" - {v}" for v in violations)
)
class TestVolumeIndicatorsHaveVolumeParam:
"""Volume indicators that use _ptr(volume) must have volume in their signature."""
VOLUME_REQUIRED = [
"adl", "adosc", "iii", "kvo", "va", "vwad", "vwap", "wad",
"obv", "pvt", "pvr", "vf", "nvi", "pvi", "tvi", "pvd",
"vwma", "evwma", "efi", "aobv", "mfi", "cmf", "eom", "pvo",
]
def test_volume_funcs_have_volume_param(self) -> None:
import quantalib.volume as vol
violations = []
for fname in self.VOLUME_REQUIRED:
fn = getattr(vol, fname, None)
if fn is None:
continue
sig = inspect.signature(fn)
if "volume" not in sig.parameters:
violations.append(fname)
assert violations == [], (
f"Volume functions missing 'volume' parameter: {violations}"
)
File diff suppressed because it is too large Load Diff
+9
View File
@@ -0,0 +1,9 @@
import re, os
total = 0
for f in sorted(os.listdir('python/quantalib')):
if f.endswith('.py') and not f.startswith('_') and f != 'indicators.py':
content = open(f'python/quantalib/{f}', encoding='utf-8').read()
defs = re.findall(r'^def (\w+)\(', content, re.MULTILINE)
total += len(defs)
print(f'{f}: {len(defs)} functions - {", ".join(defs[:10])}{"..." if len(defs) > 10 else ""}')
print(f'\nTotal: {total} wrapper functions across {len([f for f in os.listdir("python/quantalib") if f.endswith(".py") and not f.startswith("_") and f != "indicators.py"])} files')
+28
View File
@@ -0,0 +1,28 @@
import re, os
# Collect all function names from new category files
new_fns = set()
for f in sorted(os.listdir('python/quantalib')):
if f.endswith('.py') and not f.startswith('_') and f != 'indicators.py':
content = open(f'python/quantalib/{f}', encoding='utf-8').read()
new_fns.update(re.findall(r'^def (\w+)\(', content, re.MULTILINE))
# Collect from old indicators.py
old_content = open('python/quantalib/indicators.py', encoding='utf-8').read()
old_fns = set(re.findall(r'^def (\w+)\(', old_content, re.MULTILINE))
old_fns = {f for f in old_fns if not f.startswith('_')}
missing = sorted(old_fns - new_fns)
extra = sorted(new_fns - old_fns)
with open('python/tools/diff_report.txt', 'w') as out:
out.write(f'Old indicators.py: {len(old_fns)} public functions\n')
out.write(f'New category files: {len(new_fns)} functions\n\n')
out.write(f'Missing from new ({len(missing)}):\n')
for m in missing:
out.write(f' {m}\n')
out.write(f'\nNew indicators not in old ({len(extra)}):\n')
for e in extra:
out.write(f' {e}\n')
print('Done - see python/tools/diff_report.txt')
+18
View File
@@ -0,0 +1,18 @@
"""Extract C# export signatures for category module generation."""
import re
cs = open('python/src/Exports.Generated.cs', encoding='utf-8').read()
# Extract each function: entry point name + full C# parameter list
pattern = r'\[UnmanagedCallersOnly\(EntryPoint\s*=\s*"qtl_(\w+)"\)\]\s+public static int \w+\(([^)]+)\)'
matches = re.findall(pattern, cs)
for name, params in matches:
# Parse param types + names
parts = []
for p in params.split(','):
p = p.strip()
tokens = p.split()
if len(tokens) >= 2:
parts.append(f"{tokens[0]} {tokens[1]}")
print(f"qtl_{name}|{'|'.join(parts)}")
+767
View File
@@ -0,0 +1,767 @@
#!/usr/bin/env python3
"""Generate per-category Python indicator modules from Exports.Generated.cs.
Reads the C# exports file and the lib/ directory structure to produce:
- python/quantalib/_helpers.py (shared wrapper infrastructure)
- python/quantalib/_bridge.py (ALL ctypes bindings)
- python/quantalib/{category}.py (one per lib/ category)
- python/quantalib/indicators.py (re-exports everything)
- python/quantalib/__init__.py (package root)
Usage:
python python/tools/generate_category_modules.py
"""
from __future__ import annotations
import os
import re
import sys
from dataclasses import dataclass, field
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[2]
LIB_DIR = REPO_ROOT / "lib"
EXPORTS_CS = REPO_ROOT / "python" / "src" / "Exports.Generated.cs"
OUT_DIR = REPO_ROOT / "python" / "quantalib"
# ---------------------------------------------------------------------------
# Category mapping: lib/ subdirectory → Python module name
# ---------------------------------------------------------------------------
CATEGORY_PY_NAME: dict[str, str] = {
"channels": "channels",
"core": "core",
"cycles": "cycles",
"dynamics": "dynamics",
"errors": "errors",
"filters": "filters",
"forecasts": "forecasts",
"momentum": "momentum",
"numerics": "numerics",
"oscillators": "oscillators",
"reversals": "reversals",
"statistics": "statistics_", # avoid shadowing stdlib 'statistics'
"trends_FIR": "trends_fir",
"trends_IIR": "trends_iir",
"volatility": "volatility",
"volume": "volume",
}
# Subdirectories in lib/core/ that are NOT indicators (infrastructure)
CORE_SKIP = {
"collections", "ringbuffer", "simd", "tbar", "tbarseries",
"tests", "tseries", "tvalue", "_index.md",
}
# Export names that don't map cleanly to a lib/ indicator dir
EXPORT_RENAMES: dict[str, str] = {
"htdcperiod": "ht_dcperiod",
"htdcphase": "ht_dcphase",
"htphasor": "ht_phasor",
"htsine": "ht_sine",
"httrendmode": "ht_trendmode",
"htit": "htit",
"ttmsqueeze": "ttm_squeeze",
"ttmtrend": "ttm_trend",
"ttmscalper": "ttm_scalper",
"ttmwave": "ttm_wave",
"ttmlrc": "ttm_lrc",
}
# ---------------------------------------------------------------------------
# Data model
# ---------------------------------------------------------------------------
@dataclass
class ExportInfo:
"""Parsed info for a single [UnmanagedCallersOnly] export."""
entry_name: str # e.g. "qtl_sma"
func_name: str # e.g. "sma"
cs_params: list[tuple[str, str]] # [(type, name), ...]
category: str = "" # resolved lib/ category
lib_indicator: str = "" # indicator dir name in lib/
@property
def py_module(self) -> str:
return CATEGORY_PY_NAME.get(self.category, self.category)
# ---------------------------------------------------------------------------
# Step 1: Build category lookup {indicator_name → category}
# ---------------------------------------------------------------------------
def build_category_map() -> dict[str, str]:
"""Scan lib/ subdirectories to build indicator→category mapping."""
cat_map: dict[str, str] = {}
for cat_dir in sorted(LIB_DIR.iterdir()):
if not cat_dir.is_dir():
continue
cat_name = cat_dir.name
if cat_name in ("bin", "obj", "feeds") or cat_name.startswith("_") or cat_name.startswith("."):
continue
for ind_dir in sorted(cat_dir.iterdir()):
if not ind_dir.is_dir():
continue
ind_name = ind_dir.name
if ind_name.startswith("_") or ind_name.startswith("."):
continue
if cat_name == "core" and ind_name in CORE_SKIP:
continue
# Normalize: indicator directory names are lowercase
cat_map[ind_name.lower()] = cat_name
return cat_map
# ---------------------------------------------------------------------------
# Step 2: Parse Exports.Generated.cs
# ---------------------------------------------------------------------------
RE_ENTRY = re.compile(
r'\[UnmanagedCallersOnly\(EntryPoint\s*=\s*"(qtl_\w+)"\)\]'
)
RE_FUNC = re.compile(
r'public\s+static\s+int\s+\w+\(([^)]*)\)'
)
def parse_cs_param(raw: str) -> tuple[str, str]:
"""Parse 'double* source' → ('double*', 'source')."""
raw = raw.strip()
parts = raw.rsplit(None, 1)
if len(parts) == 2:
return (parts[0], parts[1])
return (raw, "")
def parse_exports(cs_path: Path) -> list[ExportInfo]:
"""Parse all [UnmanagedCallersOnly] exports from the C# file."""
text = cs_path.read_text(encoding="utf-8")
lines = text.splitlines()
exports: list[ExportInfo] = []
i = 0
while i < len(lines):
m = RE_ENTRY.search(lines[i])
if m:
entry_name = m.group(1) # e.g. "qtl_sma"
func_name = entry_name[4:] # strip "qtl_"
# Find the function signature (may be on next line)
for j in range(i + 1, min(i + 5, len(lines))):
fm = RE_FUNC.search(lines[j])
if fm:
raw_params = fm.group(1)
params = [parse_cs_param(p) for p in raw_params.split(",")]
exports.append(ExportInfo(
entry_name=entry_name,
func_name=func_name,
cs_params=params,
))
break
i = j + 1
else:
i += 1
return exports
# ---------------------------------------------------------------------------
# Step 3: Resolve categories
# ---------------------------------------------------------------------------
def resolve_categories(exports: list[ExportInfo], cat_map: dict[str, str]) -> None:
"""Assign each export to its lib/ category."""
for exp in exports:
name = exp.func_name
# Check rename mapping first
mapped = EXPORT_RENAMES.get(name, name)
if mapped in cat_map:
exp.category = cat_map[mapped]
exp.lib_indicator = mapped
else:
# Try underscore variants
for variant in [mapped.replace("_", ""), mapped]:
if variant in cat_map:
exp.category = cat_map[variant]
exp.lib_indicator = variant
break
# Special cases
if name == "ema_alpha":
exp.category = "trends_IIR"
exp.lib_indicator = "ema"
elif name == "dema_alpha":
exp.category = "trends_IIR"
exp.lib_indicator = "dema"
elif name in ("wclprice", "midpoint", "midprice", "medprice",
"avgprice", "typprice", "midbody", "ha"):
exp.category = "core"
exp.lib_indicator = name
elif name == "skeleton_noop":
exp.category = "_internal"
if not exp.category and name != "skeleton_noop":
print(f" WARNING: No category for export '{name}'", file=sys.stderr)
# ---------------------------------------------------------------------------
# Step 4: Classify parameter patterns for ctypes/Python wrappers
# ---------------------------------------------------------------------------
def classify_params(exp: ExportInfo) -> dict:
"""Classify the export's parameter pattern for code generation."""
params = exp.cs_params
ptypes = [p[0] for p in params]
pnames = [p[1] for p in params]
info: dict = {
"inputs": [], # list of (cs_type, name, py_name)
"outputs": [], # list of (cs_type, name, py_name)
"int_params": [], # list of (name, py_name, default)
"double_params": [], # list of (name, py_name, default)
"n_param": None, # name of the length param
"pattern": "custom",
"argtypes": [],
}
# Identify inputs (double*) that appear before outputs
# Heuristic: inputs come before 'n', outputs after
n_idx = None
for i, (t, n) in enumerate(params):
if t == "int" and n in ("n", "length") and n_idx is None:
# Special: some have 'n' later
pass
if n == "n" and t == "int":
n_idx = i
break
if n_idx is None:
# n might be at different position, find it
for i, (t, n) in enumerate(params):
if t == "int" and n == "n":
n_idx = i
break
return info
# ---------------------------------------------------------------------------
# Step 5: Generate ctypes argtypes string
# ---------------------------------------------------------------------------
def cs_type_to_ctypes(cs_type: str) -> str:
"""Convert C# parameter type to ctypes constant."""
mapping = {
"double*": "_dp",
"int": "_ci",
"double": "_cd",
"int*": "_ip",
"long*": "_lp",
}
return mapping.get(cs_type, f"# UNKNOWN: {cs_type}")
def gen_argtypes(exp: ExportInfo) -> str:
"""Generate the ctypes argtypes list for a binding."""
parts = [cs_type_to_ctypes(t) for t, _ in exp.cs_params]
return "[" + ", ".join(parts) + "]"
# ---------------------------------------------------------------------------
# Step 6: Generate _bridge.py
# ---------------------------------------------------------------------------
def gen_bridge(exports: list[ExportInfo], by_cat: dict[str, list[ExportInfo]]) -> str:
"""Generate the complete _bridge.py file."""
lines = [
'"""Low-level ctypes bindings for every quantalib NativeAOT export.',
'',
'Auto-generated by generate_category_modules.py — DO NOT EDIT.',
'',
'Each native function is bound via ``_bind`` at module load. If the shared',
'library was compiled without a particular export the binding is silently',
'skipped (the corresponding ``HAS_*`` flag stays False).',
'"""',
'from __future__ import annotations',
'',
'import ctypes',
'from ctypes import c_double, c_int, POINTER',
'from typing import Final',
'',
'from ._loader import load_native_library',
'',
'# ---------------------------------------------------------------------------',
'# Status codes (mirror StatusCodes.cs)',
'# ---------------------------------------------------------------------------',
'QTL_OK: Final[int] = 0',
'QTL_ERR_NULL_PTR: Final[int] = 1',
'QTL_ERR_INVALID_LENGTH: Final[int] = 2',
'QTL_ERR_INVALID_PARAM: Final[int] = 3',
'QTL_ERR_INTERNAL: Final[int] = 4',
'',
'',
'class QtlError(Exception):',
' """Base exception for quantalib native errors."""',
'',
'',
'class QtlNullPointerError(QtlError):',
' pass',
'',
'',
'class QtlInvalidLengthError(QtlError):',
' pass',
'',
'',
'class QtlInvalidParamError(QtlError):',
' pass',
'',
'',
'class QtlInternalError(QtlError):',
' pass',
'',
'',
'_STATUS_MAP: dict[int, type[QtlError]] = {',
' QTL_ERR_NULL_PTR: QtlNullPointerError,',
' QTL_ERR_INVALID_LENGTH: QtlInvalidLengthError,',
' QTL_ERR_INVALID_PARAM: QtlInvalidParamError,',
' QTL_ERR_INTERNAL: QtlInternalError,',
'}',
'',
'',
'def _check(status: int) -> None:',
' """Raise if *status* is not QTL_OK."""',
' if status == QTL_OK:',
' return',
' exc_type = _STATUS_MAP.get(status, QtlError)',
' raise exc_type(f"quantalib native call failed (status={status})")',
'',
'',
'# ---------------------------------------------------------------------------',
'# Load native library',
'# ---------------------------------------------------------------------------',
'_lib = load_native_library()',
'',
'# Shorthand type aliases',
'_dp = POINTER(c_double) # double*',
'_ip = POINTER(c_int) # int*',
'_lp = POINTER(ctypes.c_long) # long*',
'_ci = c_int',
'_cd = c_double',
'',
'',
'def _bind(name: str, argtypes: list[object]) -> bool:',
' """Bind a single native function. Returns True if found."""',
' fn = getattr(_lib, name, None)',
' if fn is None:',
' return False',
' fn.argtypes = argtypes',
' fn.restype = _ci',
' return True',
'',
'',
'# ---------------------------------------------------------------------------',
'# Health check',
'# ---------------------------------------------------------------------------',
'HAS_SKELETON = _bind("qtl_skeleton_noop", [_dp, _ci, _dp])',
'',
]
# Category order
CAT_ORDER = [
"core", "momentum", "oscillators", "trends_FIR", "trends_IIR",
"channels", "volatility", "volume", "statistics", "errors",
"filters", "cycles", "dynamics", "numerics", "reversals", "forecasts",
]
cat_labels = {
"core": "Core",
"momentum": "Momentum",
"oscillators": "Oscillators",
"trends_FIR": "Trends — FIR",
"trends_IIR": "Trends — IIR",
"channels": "Channels",
"volatility": "Volatility",
"volume": "Volume",
"statistics": "Statistics",
"errors": "Errors",
"filters": "Filters",
"cycles": "Cycles",
"dynamics": "Dynamics",
"numerics": "Numerics",
"reversals": "Reversals",
"forecasts": "Forecasts",
}
for cat in CAT_ORDER:
if cat not in by_cat:
continue
exps = by_cat[cat]
label = cat_labels.get(cat, cat)
lines.append(f'# {"" * 75}')
lines.append(f'# {label}')
lines.append(f'# {"" * 75}')
for exp in sorted(exps, key=lambda e: e.func_name):
varname = f"HAS_{exp.func_name.upper()}"
argtypes = gen_argtypes(exp)
lines.append(f'{varname} = _bind("{exp.entry_name}", {argtypes})')
lines.append('')
return "\n".join(lines)
# ---------------------------------------------------------------------------
# Step 7: Generate _helpers.py
# ---------------------------------------------------------------------------
def gen_helpers() -> str:
return '''"""Shared wrapper helpers for quantalib indicator modules.
Auto-generated by generate_category_modules.py DO NOT EDIT.
"""
from __future__ import annotations
import numpy as np
from numpy.typing import NDArray
from ._bridge import _lib, _check, _dp, _ci, _cd
# Optional pandas support
try:
import pandas as pd # type: ignore[import-untyped]
except ImportError: # pragma: no cover
pd = None # type: ignore[assignment]
# ---------------------------------------------------------------------------
# Internal helpers
# ---------------------------------------------------------------------------
_F64 = np.float64
def _arr(x: object) -> tuple[NDArray[np.float64], object]:
"""Return (contiguous float64 array, original_index_or_None)."""
idx = None
if pd is not None and isinstance(x, pd.Series):
idx = x.index
x = x.to_numpy(dtype=_F64, copy=False)
elif pd is not None and isinstance(x, pd.DataFrame):
idx = x.index
x = x.iloc[:, 0].to_numpy(dtype=_F64, copy=False)
return np.ascontiguousarray(x, dtype=_F64), idx # type: ignore[arg-type]
def _ptr(a: NDArray[np.float64]): # noqa: ANN202
"""Get ctypes double* from array."""
return a.ctypes.data_as(_dp)
def _out(n: int) -> NDArray[np.float64]:
"""Allocate output array."""
return np.empty(n, dtype=_F64)
def _offset(arr: NDArray[np.float64], off: int) -> NDArray[np.float64]:
"""Apply offset (roll + NaN fill)."""
if off and off != 0:
arr = np.roll(arr, off)
if off > 0:
arr[:off] = np.nan
else:
arr[off:] = np.nan
return arr
def _wrap(
arr: NDArray[np.float64],
idx: object,
name: str,
category: str,
offset: int = 0,
):
"""Wrap result: apply offset, optionally convert to pd.Series."""
arr = _offset(arr, offset)
if idx is not None and pd is not None:
s = pd.Series(arr, index=idx, name=name)
s.category = category
return s
return arr
def _wrap_multi(
arrays: dict[str, NDArray[np.float64]],
idx: object,
category: str,
offset: int = 0,
):
"""Wrap multi-output result into tuple or DataFrame."""
for k in arrays:
arrays[k] = _offset(arrays[k], offset)
if idx is not None and pd is not None:
df = pd.DataFrame(arrays, index=idx)
df.category = category
return df
return tuple(arrays.values())
# ═══════════════════════════════════════════════════════════════════════════
# Generic pattern helpers
# ═══════════════════════════════════════════════════════════════════════════
def _pa(
fn_name: str, close: object, length: int, offset: int,
default_length: int, label: str, category: str,
) -> object:
"""Generic Pattern A wrapper: single-input + period."""
length = int(length) if length is not None else default_length
offset = int(offset) if offset is not None else 0
src, idx = _arr(close)
n = len(src)
dst = _out(n)
_check(getattr(_lib, fn_name)(_ptr(src), n, _ptr(dst), length))
return _wrap(dst, idx, f"{label}_{length}", category, offset)
def _pa3(
fn_name: str, close: object, offset: int,
label: str, category: str,
) -> object:
"""Generic Pattern A3 wrapper: single-input, no params."""
offset = int(offset) if offset is not None else 0
src, idx = _arr(close)
n = len(src)
dst = _out(n)
_check(getattr(_lib, fn_name)(_ptr(src), n, _ptr(dst)))
return _wrap(dst, idx, label, category, offset)
def _pf(
fn_name: str, actual: object, predicted: object,
length: int, offset: int, default_length: int,
label: str, category: str,
) -> object:
"""Generic Pattern F wrapper: actual+predicted+period."""
length = int(length) if length is not None else default_length
offset = int(offset) if offset is not None else 0
a, idx = _arr(actual)
p, _ = _arr(predicted)
n = len(a)
dst = _out(n)
_check(getattr(_lib, fn_name)(_ptr(a), _ptr(p), n, _ptr(dst), length))
return _wrap(dst, idx, f"{label}_{length}", category, offset)
def _pg(
fn_name: str, close: object, volume: object,
offset: int, label: str, category: str,
) -> object:
"""Pattern G: source+volume, no period."""
offset = int(offset) if offset is not None else 0
c, idx = _arr(close)
v, _ = _arr(volume)
n = len(c)
dst = _out(n)
_check(getattr(_lib, fn_name)(_ptr(c), _ptr(v), n, _ptr(dst)))
return _wrap(dst, idx, label, category, offset)
def _pg2(
fn_name: str, close: object, volume: object, length: int,
offset: int, default_length: int, label: str, category: str,
) -> object:
"""Pattern G2: source+volume+period."""
length = int(length) if length is not None else default_length
offset = int(offset) if offset is not None else 0
c, idx = _arr(close)
v, _ = _arr(volume)
n = len(c)
dst = _out(n)
_check(getattr(_lib, fn_name)(_ptr(c), _ptr(v), n, _ptr(dst), length))
return _wrap(dst, idx, f"{label}_{length}", category, offset)
def _ph(
fn_name: str, x: object, y: object, length: int,
offset: int, default_length: int, label: str, category: str,
) -> object:
"""Pattern H: X+Y+period."""
length = int(length) if length is not None else default_length
offset = int(offset) if offset is not None else 0
xarr, idx = _arr(x)
yarr, _ = _arr(y)
n = len(xarr)
dst = _out(n)
_check(getattr(_lib, fn_name)(_ptr(xarr), _ptr(yarr), n, _ptr(dst), length))
return _wrap(dst, idx, f"{label}_{length}", category, offset)
def _ohlcv_bars_period(
fn_name: str, open: object, high: object, low: object,
close: object, volume: object, period: int,
offset: int, default_period: int, label: str, category: str,
) -> object:
"""OHLCV bars + period → single output (BuildBars pattern)."""
period = int(period) if period is not None else default_period
offset = int(offset) if offset is not None else 0
o, idx = _arr(open)
h, _ = _arr(high)
l, _ = _arr(low)
c, _ = _arr(close)
v, _ = _arr(volume)
n = len(o)
dst = _out(n)
_check(getattr(_lib, fn_name)(
_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(v), period, n, _ptr(dst)))
return _wrap(dst, idx, f"{label}_{period}", category, offset)
def _hlc_period(
fn_name: str, high: object, low: object, close: object,
period: int, offset: int, default_period: int,
label: str, category: str,
) -> object:
"""HLC + period → single output."""
period = int(period) if period is not None else default_period
offset = int(offset) if offset is not None else 0
h, idx = _arr(high)
l, _ = _arr(low)
c, _ = _arr(close)
n = len(h)
dst = _out(n)
_check(getattr(_lib, fn_name)(
_ptr(h), _ptr(l), _ptr(c), period, n, _ptr(dst)))
return _wrap(dst, idx, f"{label}_{period}", category, offset)
def _src_period(
fn_name: str, source: object, period: int,
offset: int, default_period: int, label: str, category: str,
) -> object:
"""source + period → single output (BuildSeries pattern, src,period,n,dst)."""
period = int(period) if period is not None else default_period
offset = int(offset) if offset is not None else 0
src, idx = _arr(source)
n = len(src)
dst = _out(n)
_check(getattr(_lib, fn_name)(_ptr(src), period, n, _ptr(dst)))
return _wrap(dst, idx, f"{label}_{period}", category, offset)
'''
# ---------------------------------------------------------------------------
# Step 8: Build per-category wrapper functions
# ---------------------------------------------------------------------------
# We derive wrapper signatures from the C# export signatures.
# Manual mappings for export names that need specific Python wrapper treatment
# This defines the "known" wrappers. Anything not here gets auto-generated.
# Map of lib/ directory name → default period for Pattern A indicators
DEFAULT_PERIODS: dict[str, int] = {
# Trends FIR
"sma": 10, "wma": 10, "hma": 9, "trima": 10, "swma": 10, "dwma": 10,
"blma": 10, "lsma": 25, "sgma": 10, "sinema": 10, "hanma": 10,
"parzen": 10, "tsf": 14, "sp15": 15, "tukey_w": 10, "rain": 10,
"fwma": 10, "gwma": 10, "hamma": 10, "hend": 10, "ilrs": 10,
"kaiser": 10, "lanczos": 10, "nlma": 10, "nyqma": 10, "pma": 10,
"pwma": 10, "qrma": 10, "rwma": 10, "bwma": 10,
# Trends IIR
"ema": 10, "dema": 10, "tema": 10, "lema": 10, "hema": 10,
"ahrens": 10, "decycler": 20, "frama": 10, "hwma": 10,
"jma": 10, "kama": 10, "ltma": 10, "mama": 10, "mavp": 10,
"mcnma": 10, "mgdi": 10, "mma": 10, "nma": 10, "qema": 10,
"rema": 10, "rgma": 10, "rma": 10, "t3": 10, "trama": 10,
"vidya": 10, "zldema": 10, "zlema": 10, "zltema": 10,
"adxvma": 14, "vama": 14, "yzvama": 14,
# Momentum
"rsi": 14, "roc": 10, "mom": 10, "cmo": 14, "bias": 26,
"cfo": 14, "rsx": 14, "pmo": 35,
"rocp": 10, "rocr": 10, "vel": 10,
# Oscillators
"fisher": 9, "fisher04": 9, "dpo": 20, "trix": 18, "inertia": 20,
"er": 10, "cti": 12, "reflex": 20, "trendflex": 20, "kri": 20,
"psl": 12, "lrsi": 14,
# Volatility
"bbw": 20, "stddev": 20, "variance": 20, "natr": 14, "massi": 14,
"ui": 14, "jvolty": 14, "jvoltyn": 14, "rsv": 14, "rv": 14,
"rvi": 14, "vov": 14, "vr": 14,
# Cycles
"cg": 10, "dsp": 20, "ccor": 20,
# Statistics
"zscore": 20, "entropy": 10, "geomean": 10, "harmean": 10,
"hurst": 100, "iqr": 20, "kurtosis": 20, "linreg": 14,
"meandev": 20, "median": 20, "mode": 20, "percentile": 20,
"polyfit": 20, "quantile": 20, "skew": 20, "spearman": 20,
"stddev": 20, "stderr": 20, "sum": 20, "theil": 20,
"trim": 20, "wavg": 20, "wins": 20, "ztest": 20,
"kendall": 20, "pacf": 20,
# Filters
"bessel": 14, "butter2": 14, "butter3": 14, "cheby1": 14,
"cheby2": 14, "elliptic": 14, "edcf": 14, "bpf": 14,
"loess": 14, "nw": 14, "rmed": 14, "sgf": 14, "spbf": 14,
"ssf2": 14, "ssf3": 14, "usf": 14, "voss": 14,
"wavelet": 14, "wiener": 14,
# Numerics
"change": 1, "highest": 14, "lowest": 14, "slope": 14,
"accel": 0, "jerk": 0,
# Errors (all pattern F, default 20)
"mse": 20, "rmse": 20, "mae": 20, "mape": 20, "smape": 20,
"msle": 20, "rmsle": 20, "me": 20, "mpe": 20, "mrae": 20,
"rse": 20, "rae": 20, "rsquared": 20, "wmape": 20, "wrmse": 20,
"mdae": 20, "mdape": 20, "mase": 20, "maape": 20, "mapd": 20,
"huber": 20, "logcosh": 20, "pseudohuber": 20, "tukeybiweight": 20,
"quantileloss": 20, "theilu": 20,
}
def main() -> None:
print("=== Generating quantalib per-category Python modules ===")
# Step 1: Build category map
cat_map = build_category_map()
print(f" Found {len(cat_map)} indicators across {len(set(cat_map.values()))} categories")
# Step 2: Parse exports
exports = parse_exports(EXPORTS_CS)
print(f" Parsed {len(exports)} exports from Exports.Generated.cs")
# Step 3: Resolve categories
resolve_categories(exports, cat_map)
# Group by category
by_cat: dict[str, list[ExportInfo]] = {}
uncategorized: list[ExportInfo] = []
for exp in exports:
if exp.category and exp.category != "_internal":
by_cat.setdefault(exp.category, []).append(exp)
elif exp.category != "_internal":
uncategorized.append(exp)
for cat in sorted(by_cat):
inds = sorted(e.func_name for e in by_cat[cat])
print(f" {cat}: {len(inds)} indicators")
if uncategorized:
print(f" UNCATEGORIZED: {[e.func_name for e in uncategorized]}")
# Step 4: Generate _helpers.py
helpers_path = OUT_DIR / "_helpers.py"
helpers_path.write_text(gen_helpers(), encoding="utf-8")
print(f" Wrote {helpers_path}")
# Step 5: Generate _bridge.py
bridge_path = OUT_DIR / "_bridge.py"
bridge_path.write_text(gen_bridge(exports, by_cat), encoding="utf-8")
print(f" Wrote {bridge_path}")
# Step 6-8: will print summary
print("\n=== Summary ===")
print(f" Total exports: {len(exports)}")
print(f" Categorized: {sum(len(v) for v in by_cat.values())}")
print(f" Categories: {len(by_cat)}")
if __name__ == "__main__":
main()
+927
View File
@@ -0,0 +1,927 @@
#!/usr/bin/env python3
"""Generate per-category Python wrapper modules from C# export signatures.
Reads Exports.Generated.cs, maps exports to lib/ categories,
and generates one .py file per category under python/quantalib/.
Run from repo root:
python python/tools/generate_wrappers.py
"""
from __future__ import annotations
import os
import re
import textwrap
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent.parent
CS_FILE = ROOT / "python" / "src" / "Exports.Generated.cs"
LIB_DIR = ROOT / "lib"
OUT_DIR = ROOT / "python" / "quantalib"
# ── Category mapping ──────────────────────────────────────────────────────
# Scan lib/ subdirs to build export→category map
def build_category_map() -> dict[str, str]:
"""Map indicator name (lowercase) → category folder name."""
m: dict[str, str] = {}
for cat_dir in sorted(LIB_DIR.iterdir()):
if not cat_dir.is_dir() or cat_dir.name.startswith("."):
continue
cat = cat_dir.name
for ind_dir in sorted(cat_dir.iterdir()):
if ind_dir.is_dir() and not ind_dir.name.startswith("_"):
m[ind_dir.name.lower()] = cat
return m
CAT_MAP = build_category_map()
# Manual overrides for export names that differ from lib/ dir names
EXPORT_TO_LIB = {
"abber": "aberr",
"htdcperiod": "ht_dcperiod",
"htdcphase": "ht_dcphase",
"htphasor": "ht_phasor",
"htsine": "ht_sine",
"httrendmode": "ht_trendmode",
"htit": "htit",
"ttmlrc": "ttm_lrc",
"ttmscalper": "ttm_scalper",
"ttmsqueeze": "ttm_squeeze",
"ttmtrend": "ttm_trend",
"ttmwave": "ttm_wave",
}
def get_category(export_name: str) -> str:
"""Return category for an export name."""
lib_name = EXPORT_TO_LIB.get(export_name, export_name)
if lib_name in CAT_MAP:
return CAT_MAP[lib_name]
# Some exports have _ removed vs lib dir (e.g. td_seq → tdseq)
for k, v in CAT_MAP.items():
if k.replace("_", "") == export_name.replace("_", ""):
return v
return "uncategorized"
# ── Parse C# exports ─────────────────────────────────────────────────────
def parse_exports() -> list[dict]:
"""Parse all exports from Exports.Generated.cs."""
cs = CS_FILE.read_text(encoding="utf-8")
pattern = r'\[UnmanagedCallersOnly\(EntryPoint\s*=\s*"qtl_(\w+)"\)\]\s+public static int \w+\(([^)]+)\)'
exports = []
for name, params_str in re.findall(pattern, cs):
params = []
for p in params_str.split(","):
p = p.strip()
tokens = p.split()
if len(tokens) >= 2:
ptype = tokens[0]
pname = tokens[1]
params.append({"type": ptype, "name": pname})
exports.append({
"name": name,
"params": params,
"category": get_category(name),
})
return exports
# ── Classify param roles ─────────────────────────────────────────────────
def classify_params(params):
"""Identify inputs, outputs, scalars in a param list."""
inputs = []
outputs = []
n_idx = None
scalars = []
for i, p in enumerate(params):
name = p["name"]
ptype = p["type"]
if name == "n":
n_idx = i
continue
if ptype == "double*":
# Heuristic: if name contains output/dst/destination/Out/middle/upper/lower etc.
out_names = {"output", "dst", "destination", "middle", "upper", "lower",
"haOpenOut", "haHighOut", "haLowOut", "haCloseOut",
"dstMiddle", "dstUpper", "dstLower", "dstTenkan", "dstKijun",
"dstSenkouA", "dstSenkouB", "dstChikou",
"kOut", "dOut", "jOut", "kstOut", "sigOut",
"rvgiOutput", "signalOutput", "signalOutput",
"momOut", "sqOut", "trend", "strength",
"sine", "leadSine", "inPhase", "quadrature", "ppOutput",
"upOutput", "downOutput", "highOutput", "lowOutput",
"pmaOutput", "triggerOutput", "famaOutput",
"upper1", "lower1", "upper2", "lower2", "vwap", "stdDev",
"viPlus", "viMinus", "midline",
"signal"}
if name in out_names or name.endswith("Out") or name.endswith("Output"):
outputs.append(p)
else:
inputs.append(p)
elif ptype == "int" or ptype == "double":
scalars.append(p)
return inputs, outputs, n_idx, scalars
# ── Generate wrapper function ────────────────────────────────────────────
# Description map for well-known indicators
DESCRIPTIONS = {
# Core
"avgprice": "Average Price = (O+H+L+C)/4",
"ha": "Heikin-Ashi Candles",
"medprice": "Median Price = (H+L)/2",
"midbody": "Mid Body = (O+C)/2",
"midpoint": "Midpoint = src[i] over period",
"midprice": "Mid Price = (High+Low)/2 over period",
"typprice": "Typical Price = (H+L+C)/3",
"wclprice": "Weighted Close Price = (H+L+2*C)/4",
# Momentum
"asi": "Accumulative Swing Index",
"bias": "Bias Indicator",
"bop": "Balance of Power",
"cci": "Commodity Channel Index",
"cfb": "Composite Fractal Behavior",
"cmo": "Chande Momentum Oscillator",
"macd": "Moving Average Convergence Divergence",
"mom": "Momentum",
"pmo": "Price Momentum Oscillator",
"ppo": "Percentage Price Oscillator",
"prs": "Price Relative Strength",
"roc": "Rate of Change",
"rocp": "Rate of Change (Percentage)",
"rocr": "Rate of Change (Ratio)",
"rsi": "Relative Strength Index",
"rsx": "Relative Strength Xtra",
"sam": "Simple Alpha Momentum",
"tsi": "True Strength Index",
"vel": "Velocity",
# Oscillators
"ac": "Accelerator Oscillator",
"ao": "Awesome Oscillator",
"apo": "Absolute Price Oscillator",
"bbb": "Bollinger Band Bounce",
"bbi": "Bull Bear Index",
"bbs": "Bollinger Band Squeeze",
"brar": "Bull-Bear Ratio",
"cfo": "Chande Forecast Oscillator",
"coppock": "Coppock Curve",
"crsi": "Connors RSI",
"cti": "Correlation Trend Indicator",
"deco": "DECO Oscillator",
"dem": "DeMarker",
"dosc": "Derivative Oscillator",
"dpo": "Detrended Price Oscillator",
"dymoi": "Dynamic Momentum Index",
"er": "Efficiency Ratio",
"eri": "Elder Ray Index",
"fi": "Force Index",
"fisher": "Fisher Transform",
"fisher04": "Fisher Transform (0.4 variant)",
"gator": "Gator Oscillator",
"imi": "Intraday Momentum Index",
"inertia": "Inertia",
"kdj": "KDJ Indicator",
"kri": "Kairi Relative Index",
"kst": "Know Sure Thing",
"lrsi": "Laguerre RSI",
"marketfi": "Market Facilitation Index",
"mstoch": "Modified Stochastic",
"pgo": "Pretty Good Oscillator",
"psl": "Psychological Line",
"qqe": "Quantitative Qualitative Estimation",
"reflex": "Reflex",
"reverseema": "Reverse EMA",
"rvgi": "Relative Vigor Index",
"smi": "Stochastic Momentum Index",
"squeeze": "Squeeze Momentum",
"stc": "Schaff Trend Cycle",
"stoch": "Stochastic Oscillator",
"stochf": "Fast Stochastic",
"stochrsi": "Stochastic RSI",
"td_seq": "Tom DeMark Sequential",
"trendflex": "Trendflex",
"trix": "Triple EMA Rate of Change",
"ttmwave": "TTM Wave",
"ultosc": "Ultimate Oscillator",
"willr": "Williams %R",
# Trends FIR
"alma": "Arnaud Legoux Moving Average",
"blma": "Blackman Moving Average",
"bwma": "Butterworth-weighted Moving Average",
"conv": "Convolution Filter",
"crma": "Cosine-Ramp Moving Average",
"dwma": "Double Weighted Moving Average",
"fwma": "Fibonacci Weighted Moving Average",
"gwma": "Gaussian Weighted Moving Average",
"hamma": "Hamming Moving Average",
"hanma": "Hann Moving Average",
"hend": "Henderson Moving Average",
"hma": "Hull Moving Average",
"ilrs": "Integral of Linear Regression Slope",
"kaiser": "Kaiser Window Moving Average",
"lanczos": "Lanczos Moving Average",
"lsma": "Least Squares Moving Average",
"nlma": "Non-Lag Moving Average",
"nyqma": "Nyquist Moving Average",
"parzen": "Parzen Moving Average",
"pma": "Predictive Moving Average",
"pwma": "Pascal Weighted Moving Average",
"qrma": "Quick Reaction Moving Average",
"rain": "RAIN Moving Average",
"rwma": "Range Weighted Moving Average",
"sgma": "Savitzky-Golay Moving Average",
"sinema": "Sine Weighted Moving Average",
"sma": "Simple Moving Average",
"sp15": "SP-15 Moving Average",
"swma": "Symmetric Weighted Moving Average",
"trima": "Triangular Moving Average",
"tsf": "Time Series Forecast",
"tukey_w": "Tukey-windowed Moving Average",
"wma": "Weighted Moving Average",
# Trends IIR
"adxvma": "ADX Variable Moving Average",
"ahrens": "Ahrens Moving Average",
"coral": "CORAL Trend",
"decycler": "Simple Decycler",
"dema": "Double Exponential Moving Average",
"dsma": "Deviation-Scaled Moving Average",
"ema": "Exponential Moving Average",
"frama": "Fractal Adaptive Moving Average",
"gdema": "Generalized Double EMA",
"hema": "Henderson EMA",
"holt": "Holt Exponential Smoothing",
"htit": "Hilbert Transform Instantaneous Trendline",
"hwma": "Holt-Winter Moving Average",
"jma": "Jurik Moving Average",
"kama": "Kaufman Adaptive Moving Average",
"lema": "Laguerre EMA",
"ltma": "Low-Lag Triple Moving Average",
"mama": "MESA Adaptive Moving Average",
"mavp": "Moving Average Variable Period",
"mcnma": "McNicholl Moving Average",
"mgdi": "McGinley Dynamic",
"mma": "Modified Moving Average",
"nma": "Normalized Moving Average",
"qema": "Quadruple EMA",
"rema": "Regularized EMA",
"rgma": "Recursive Gaussian Moving Average",
"rma": "Rolling Moving Average",
"t3": "Tillson T3",
"tema": "Triple Exponential Moving Average",
"trama": "Triangular Adaptive Moving Average",
"vama": "Volume Adjusted Moving Average",
"vidya": "Variable Index Dynamic Average",
"yzvama": "Yang Zhang Volatility Adaptive MA",
"zldema": "Zero-Lag Double EMA",
"zlema": "Zero-Lag EMA",
"zltema": "Zero-Lag Triple EMA",
# Channels
"abber": "Aberration Bands",
"accbands": "Acceleration Bands",
"apchannel": "Average Price Channel",
"apz": "Adaptive Price Zone",
"atrbands": "ATR Bands",
"bbands": "Bollinger Bands",
"dchannel": "Donchian Channel",
"decaychannel": "Decay Channel",
"fcb": "Fractal Chaos Bands",
"jbands": "J-Line Bands",
"kchannel": "Keltner Channel",
"maenv": "Moving Average Envelope",
"mmchannel": "Min-Max Channel",
"pchannel": "Price Channel",
"regchannel": "Regression Channel",
"sdchannel": "Standard Deviation Channel",
"starchannel": "Stoller Average Range Channel (STARC)",
"stbands": "SuperTrend Bands",
"ttmlrc": "TTM Linear Regression Channel",
"ubands": "Upper/Lower Bands",
"uchannel": "Ulcer Channel",
"vwapbands": "VWAP Bands",
"vwapsd": "VWAP Standard Deviation",
# Volatility
"adr": "Average Daily Range",
"atr": "Average True Range",
"atrn": "Normalized ATR",
"bbw": "Bollinger Band Width",
"bbwn": "Bollinger Band Width Normalized",
"bbwp": "Bollinger Band Width Percentile",
"ccv": "Close-to-Close Volatility",
"cv": "Coefficient of Variation",
"cvi": "Chaikin Volatility Index",
"etherm": "Elder Thermometer",
"ewma": "Exponentially Weighted Moving Average Volatility",
"gkv": "Garman-Klass Volatility",
"hlv": "High-Low Volatility",
"hv": "Historical Volatility",
"jvolty": "Jurik Volatility",
"jvoltyn": "Jurik Volatility Normalized",
"massi": "Mass Index",
"natr": "Normalized ATR",
"rsv": "Rogers-Satchell Volatility",
"rv": "Realized Volatility",
"rvi": "Relative Volatility Index",
"tr": "True Range",
"ui": "Ulcer Index",
"vov": "Volatility of Volatility",
"vr": "Volatility Ratio",
"yzv": "Yang-Zhang Volatility",
# Volume
"adl": "Accumulation/Distribution Line",
"adosc": "Accumulation/Distribution Oscillator",
"aobv": "Archer On-Balance Volume",
"cmf": "Chaikin Money Flow",
"efi": "Elder Force Index",
"eom": "Ease of Movement",
"evwma": "Elastic Volume Weighted Moving Average",
"iii": "Intraday Intensity Index",
"kvo": "Klinger Volume Oscillator",
"mfi": "Money Flow Index",
"nvi": "Negative Volume Index",
"obv": "On-Balance Volume",
"pvd": "Price Volume Divergence",
"pvi": "Positive Volume Index",
"pvo": "Percentage Volume Oscillator",
"pvr": "Price Volume Rank",
"pvt": "Price Volume Trend",
"tvi": "Trade Volume Index",
"twap": "Time Weighted Average Price",
"va": "Volume Accumulation",
"vf": "Volume Flow",
"vo": "Volume Oscillator",
"vroc": "Volume Rate of Change",
"vwad": "Volume Weighted Accumulation/Distribution",
"vwap": "Volume Weighted Average Price",
"vwma": "Volume Weighted Moving Average",
"wad": "Williams Accumulation/Distribution",
# Statistics
"acf": "Autocorrelation Function",
"beta": "Beta Coefficient",
"cma": "Cumulative Moving Average",
"cointegration": "Cointegration",
"correlation": "Pearson Correlation",
"covariance": "Covariance",
"entropy": "Shannon Entropy",
"geomean": "Geometric Mean",
"granger": "Granger Causality",
"harmean": "Harmonic Mean",
"hurst": "Hurst Exponent",
"iqr": "Interquartile Range",
"jb": "Jarque-Bera Test",
"kendall": "Kendall Rank Correlation",
"kurtosis": "Kurtosis",
"linreg": "Linear Regression",
"meandev": "Mean Deviation",
"median": "Rolling Median",
"mode": "Rolling Mode",
"pacf": "Partial Autocorrelation Function",
"percentile": "Rolling Percentile",
"polyfit": "Polynomial Fit",
"quantile": "Rolling Quantile",
"skew": "Skewness",
"spearman": "Spearman Rank Correlation",
"stddev": "Standard Deviation",
"stderr": "Standard Error",
"sum": "Rolling Sum",
"theil": "Theil U Statistic",
"trim": "Trimmed Mean",
"variance": "Variance",
"wavg": "Weighted Average",
"wins": "Winsorized Mean",
"zscore": "Z-Score",
"ztest": "Z-Test",
# Errors
"huber": "Huber Loss",
"logcosh": "Log-Cosh Loss",
"maape": "Mean Arctangent Absolute Percentage Error",
"mae": "Mean Absolute Error",
"mapd": "Mean Absolute Percentage Deviation",
"mape": "Mean Absolute Percentage Error",
"mase": "Mean Absolute Scaled Error",
"mdae": "Median Absolute Error",
"mdape": "Median Absolute Percentage Error",
"me": "Mean Error",
"mpe": "Mean Percentage Error",
"mrae": "Mean Relative Absolute Error",
"mse": "Mean Squared Error",
"msle": "Mean Squared Logarithmic Error",
"pseudohuber": "Pseudo-Huber Loss",
"quantileloss": "Quantile Loss (Pinball Loss)",
"rae": "Relative Absolute Error",
"rmse": "Root Mean Squared Error",
"rmsle": "Root Mean Squared Logarithmic Error",
"rse": "Relative Squared Error",
"rsquared": "R-Squared (Coefficient of Determination)",
"smape": "Symmetric Mean Absolute Percentage Error",
"theilu": "Theil U Statistic (Error)",
"tukeybiweight": "Tukey Biweight Loss",
"wmape": "Weighted Mean Absolute Percentage Error",
"wrmse": "Weighted Root Mean Squared Error",
# Filters
"agc": "Automatic Gain Control",
"alaguerre": "Adaptive Laguerre Filter",
"baxterking": "Baxter-King Filter",
"bessel": "Bessel Filter",
"bilateral": "Bilateral Filter",
"bpf": "Bandpass Filter",
"butter2": "2nd-Order Butterworth Filter",
"butter3": "3rd-Order Butterworth Filter",
"cfitz": "Christiano-Fitzgerald Filter",
"cheby1": "Chebyshev Type I Filter",
"cheby2": "Chebyshev Type II Filter",
"edcf": "Ehlers Distance Coefficient Filter",
"elliptic": "Elliptic (Cauer) Filter",
"gauss": "Gaussian Filter",
"hann": "Hann Filter",
"hp": "Hodrick-Prescott Filter",
"hpf": "High-Pass Filter",
"kalman": "Kalman Filter",
"laguerre": "Laguerre Filter",
"lms": "Least Mean Squares Filter",
"loess": "LOESS Smoother",
"modf": "Modified Filter",
"notch": "Notch Filter",
"nw": "Nadaraya-Watson Filter",
"oneeuro": "1€ Filter",
"rls": "Recursive Least Squares Filter",
"rmed": "Running Median Filter",
"roofing": "Roofing Filter",
"sgf": "Savitzky-Golay Filter",
"spbf": "Short-Period Bandpass Filter",
"ssf2": "Super Smoother (2-pole)",
"ssf3": "Super Smoother (3-pole)",
"usf": "Universal Smoother Filter",
"voss": "Voss Predictor",
"wavelet": "Wavelet Filter",
"wiener": "Wiener Filter",
# Cycles
"ccor": "Circular Correlation",
"ccyc": "Cyber Cycle",
"cg": "Center of Gravity",
"dsp": "Dominant Cycle Period",
"eacp": "Ehlers Autocorrelation Periodogram",
"ebsw": "Even Better Sinewave",
"homod": "Homodyne Discriminator",
"ht_dcperiod": "Hilbert Transform Dominant Cycle Period",
"ht_dcphase": "Hilbert Transform Dominant Cycle Phase",
"ht_phasor": "Hilbert Transform Phasor",
"ht_sine": "Hilbert Transform Sine",
"lunar": "Lunar Cycle",
"solar": "Solar Cycle",
"ssfdsp": "Supersmoother DSP",
# Dynamics
"adx": "Average Directional Index",
"adxr": "ADX Rating",
"alligator": "Williams Alligator",
"amat": "Archer Moving Average Trends",
"aroon": "Aroon",
"aroonosc": "Aroon Oscillator",
"chop": "Choppiness Index",
"dmx": "Directional Movement Extended",
"dx": "Directional Movement Index",
"ghla": "Gann Hi-Lo Activator",
"ht_trendmode": "Hilbert Transform Trend Mode",
"ichimoku": "Ichimoku Cloud",
"impulse": "Elder Impulse System",
"pfe": "Polarized Fractal Efficiency",
"qstick": "QStick",
"ravi": "Range Action Verification Index",
"super": "SuperTrend",
"ttmsqueeze": "TTM Squeeze",
"ttmtrend": "TTM Trend",
"vhf": "Vertical Horizontal Filter",
"vortex": "Vortex Indicator",
# Reversals
"chandelier": "Chandelier Exit",
"ckstop": "Chuck LeBeau Stop",
"fractals": "Williams Fractals",
"pivot": "Pivot Points (Traditional)",
"pivotcam": "Camarilla Pivot Points",
"pivotdem": "DeMark Pivot Points",
"pivotext": "Extended Pivot Points",
"pivotfib": "Fibonacci Pivot Points",
"pivotwood": "Woodie Pivot Points",
"psar": "Parabolic SAR",
"swings": "Swing High/Low",
"ttmscalper": "TTM Scalper",
# Forecasts
"afirma": "Adaptive FIR Moving Average",
# Numerics
"accel": "Acceleration",
"betadist": "Beta Distribution",
"binomdist": "Binomial Distribution",
"change": "Price Change",
"cwt": "Continuous Wavelet Transform",
"dwt": "Discrete Wavelet Transform",
"expdist": "Exponential Distribution",
"exptrans": "Exponential Transform",
"fdist": "F-Distribution",
"fft": "Fast Fourier Transform",
"gammadist": "Gamma Distribution",
"highest": "Highest Value",
"ifft": "Inverse FFT",
"jerk": "Jerk (3rd derivative)",
"lineartrans": "Linear Transform",
"lognormdist": "Log-Normal Distribution",
"logtrans": "Logarithmic Transform",
"lowest": "Lowest Value",
"normalize": "Normalization",
"normdist": "Normal Distribution",
"poissondist": "Poisson Distribution",
"relu": "ReLU Activation",
"sigmoid": "Sigmoid Transform",
"slope": "Slope (1st derivative)",
"sqrttrans": "Square Root Transform",
"tdist": "Student's t-Distribution",
"weibulldist": "Weibull Distribution",
}
# Python function name overrides (export_name → python_name)
PY_NAME = {
"abber": "aberr", # fix typo in C# export
"htdcperiod": "ht_dcperiod",
"htdcphase": "ht_dcphase",
"htphasor": "ht_phasor",
"htsine": "ht_sine",
"httrendmode": "ht_trendmode",
"ttmlrc": "ttm_lrc",
"ttmscalper": "ttm_scalper",
"ttmsqueeze": "ttm_squeeze",
"ttmtrend": "ttm_trend",
"ttmwave": "ttm_wave",
}
def gen_wrapper(export: dict) -> str | None:
"""Generate a Python wrapper function for one export."""
name = export["name"]
params = export["params"]
py_name = PY_NAME.get(name, name)
label = py_name.upper()
cat = export["category"]
desc = DESCRIPTIONS.get(name, DESCRIPTIONS.get(py_name, f"{label} indicator"))
inputs, outputs, n_idx, scalars = classify_params(params)
# Build Python function signature and body
lines = []
# Determine input pattern and generate accordingly
input_names = [p["name"] for p in inputs]
output_names = [p["name"] for p in outputs]
scalar_specs = [(p["name"], p["type"]) for p in scalars]
# Build Python params
py_params = []
py_body = []
# Categorize input types
has_ohlcv = all(x in [p["name"] for p in inputs] for x in ["sourceOpen", "sourceHigh", "sourceLow", "sourceClose", "sourceVolume"])
has_ohlc = all(x in [p["name"] for p in inputs] for x in ["open", "high", "low", "close"]) and not has_ohlcv
has_hlc = all(x in [p["name"] for p in inputs] for x in ["high", "low", "close"]) and not has_ohlc and not has_ohlcv
has_hl = {"high", "low"}.issubset(set(input_names)) and "close" not in input_names and not has_ohlcv
has_actual_predicted = {"actual", "predicted"}.issubset(set(input_names))
has_xy = {"seriesX", "seriesY"}.issubset(set(input_names)) or {"x", "y"}.issubset(set(input_names))
has_src_vol = (len(inputs) == 2 and any("volume" in p["name"].lower() or p["name"] == "volume" for p in inputs))
has_price_vol = (len(inputs) == 2 and any(p["name"] == "price" for p in inputs) and any(p["name"] == "volume" for p in inputs))
single_src = len(inputs) == 1 and inputs[0]["type"] == "double*"
# Generate function
# Decide function signature
sig_params = []
# Add input params
if has_ohlcv:
sig_params.extend([
"open: object", "high: object", "low: object",
"close: object", "volume: object",
])
elif has_ohlc:
sig_params.extend([
"open: object", "high: object", "low: object", "close: object",
])
elif has_hlc:
sig_params.extend(["high: object", "low: object", "close: object"])
elif has_hl:
sig_params.extend(["high: object", "low: object"])
elif has_actual_predicted:
sig_params.extend(["actual: object", "predicted: object"])
elif has_xy:
sig_params.extend(["x: object", "y: object"])
elif has_price_vol:
sig_params.extend(["price: object", "volume: object"])
elif has_src_vol:
# Figure out which is source, which is volume
src_name = [p["name"] for p in inputs if p["name"] != "volume"][0] if inputs else "source"
sig_params.extend([f"close: object", "volume: object"])
elif single_src:
src_name = inputs[0]["name"] if inputs else "source"
py_input_name = "close" if src_name in ("source", "src", "prices", "price") else src_name
sig_params.append(f"{py_input_name}: object")
elif len(inputs) == 2:
# Two inputs (e.g. prs: baseSeries, compSeries)
for p in inputs:
pn = p["name"]
if pn.startswith("source") or pn.startswith("base"):
pn = "x"
elif pn.startswith("comp"):
pn = "y"
sig_params.append(f"{pn}: object")
elif len(inputs) == 0 and len(outputs) == 0:
# Weird case
return None
else:
for p in inputs:
sig_params.append(f"{p['name']}: object")
# Add scalar params with defaults
scalar_defaults = {
"period": 14, "length": 14, "hpLength": 40, "ssLength": 10,
"fastPeriod": 12, "slowPeriod": 26, "acPeriod": 5,
"bbPeriod": 20, "bbMult": 2.0, "kcPeriod": 10, "kcMult": 1.5,
"multiplier": 2.0, "factor": 2.0, "sigma": 6.0,
"rsiPeriod": 14, "smoothFactor": 5, "qqeFactor": 4.236,
"kPeriod": 14, "dPeriod": 3, "kSmooth": 3, "dSmooth": 3,
"kLength": 14, "windowSize": 256, "minPeriod": 6, "maxPeriod": 48,
"longRoc": 14, "shortRoc": 11, "wmaPeriod": 10,
"r1": 10, "r2": 15, "r3": 20, "r4": 30,
"s1": 10, "s2": 10, "s3": 10, "s4": 15, "sigPeriod": 9,
"jawPeriod": 13, "jawShift": 8, "jawOffset": 8,
"teethPeriod": 8, "teethShift": 5, "teethOffset": 5,
"lipsPeriod": 5, "lipsShift": 3, "lipsOffset": 3,
"tenkanPeriod": 9, "kijunPeriod": 26, "senkouBPeriod": 52, "displacement": 26,
"emaPeriod": 13, "macdFast": 12, "macdSlow": 26, "macdSignal": 9,
"signalPeriod": 9, "signal": 3,
"numHarmonics": 10,
"atrPeriod": 22, "stopPeriod": 3,
"alpha": 2.0, "beta": 2.0, "gamma": 0.7, "k": 2.0,
"lambda": 1600.0, "mu": 0.01, "mu0": 0.0,
"delta": 1.35, "c": 4.685,
"q": 0.3, "r": 1.0,
"vfactor": 0.7, "vovPeriod": 20, "volatilityPeriod": 20,
"d1": 10, "d2": 20, "nu": 10,
"order": 3, "polyOrder": 3, "feedback": 0, "fbWeight": 0.5,
"annualize": 1, "annualPeriods": 252, "isPopulation": 0,
"predict": 3, "bandwidth": 0.25,
"nanValue": 0.0, "initialLastValid": 0.0, "initialLast": 0.0,
"x0": 0.0, "intercept": 0.0, "slope_val": 1.0,
"minCutoff": 1.0, "dCutoff": 1.0,
"method": 0, "maType": 0,
"percentage": 2.5, "percent": 50.0,
"quantileLevel": 0.5, "quantile": 0.5,
"trimPct": 0.1, "winPct": 0.05,
"offset": 0,
"shortPeriod": 12, "longPeriod": 26, "sumLength": 25,
"emaLength": 9, "rmaLength": 14, "stdevLength": 10,
"stochLength": 14, "rsiLength": 14,
"fastLength": 23, "slowLength": 50, "smoothing": 10,
"lookback": 5, "useCloses": 0,
"levels": 4, "threshMult": 1.0, "smoothPeriod": 5,
"blau": 3, "phase": 0, "power": 1.0,
"rmsPeriod": 20,
"nyquistPeriod": 2, "passes": 3,
"cumulative": 0, "usePercent": 1, "useEma": 0,
"base": 2.0, "degree": 2,
"minLength": 5, "maxLength": 50,
"yzvShortPeriod": 10, "yzvLongPeriod": 100, "percentileLookback": 252,
"baseLength": 20, "shortAtrPeriod": 14, "longAtrPeriod": 50,
"strPeriod": 14, "centerPeriod": 20,
"stPeriod": 14, "momPeriod": 12,
"scale": 10.0, "omega": 6.0,
"trials": 20, "threshold": 10,
"lam": 3.0, "afStart": 0.02, "afIncrement": 0.02, "afMax": 0.2,
"cutoff": 10, "fastLimit": 0.5, "slowLimit": 0.05,
"minVol": 0.2, "maxVol": 0.7,
"friction": 0.4,
"avgLength": 3, "enhance": 1,
"numDevs": 2.0,
"window_type": 0, "use_simd": 0,
"hpLength_val": 40, "ssfLength": 10,
}
for sname, stype in scalar_specs:
# Get reasonable default
default = scalar_defaults.get(sname)
if default is None:
# Try to infer
if "period" in sname.lower() or "length" in sname.lower():
default = 14
elif "mult" in sname.lower() or "factor" in sname.lower():
default = 2.0
elif stype == "double":
default = 1.0
else:
default = 10
if stype == "double":
sig_params.append(f"{sname}: float = {default}")
else:
sig_params.append(f"{sname}: int = {int(default)}")
sig_params.append("offset: int = 0")
sig_params.append("**kwargs")
# Build function body
body = []
# Sanitize scalars
for sname, stype in scalar_specs:
if stype == "double":
body.append(f" {sname} = float({sname})")
else:
body.append(f" {sname} = int({sname})")
body.append(" offset = int(offset)")
# Convert inputs
if has_ohlcv:
body.append(" o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low)")
body.append(" c, _ = _arr(close); v, _ = _arr(volume)")
body.append(" n = len(o)")
elif has_ohlc:
body.append(" o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low); c, _ = _arr(close)")
body.append(" n = len(o)")
elif has_hlc:
body.append(" h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)")
body.append(" n = len(h)")
elif has_hl:
body.append(" h, idx = _arr(high); l, _ = _arr(low)")
body.append(" n = len(h)")
elif has_actual_predicted:
body.append(" a, idx = _arr(actual); p, _ = _arr(predicted)")
body.append(" n = len(a)")
elif has_xy:
body.append(" xarr, idx = _arr(x); yarr, _ = _arr(y)")
body.append(" n = len(xarr)")
elif has_price_vol:
body.append(" pr, idx = _arr(price); v, _ = _arr(volume)")
body.append(" n = len(pr)")
elif has_src_vol:
body.append(" src, idx = _arr(close); v, _ = _arr(volume)")
body.append(" n = len(src)")
elif single_src:
py_input_name = "close" if inputs[0]["name"] in ("source", "src", "prices", "price") else inputs[0]["name"]
body.append(f" src, idx = _arr({py_input_name})")
body.append(" n = len(src)")
elif len(inputs) == 2:
body.append(f" xarr, idx = _arr(x); yarr, _ = _arr(y)")
body.append(" n = len(xarr)")
# Allocate outputs
for p in outputs:
body.append(f" {p['name']} = _out(n)")
# Build native call arguments in original order
call_args = []
for p in params:
pname = p["name"]
ptype = p["type"]
if pname == "n":
call_args.append("n")
elif ptype == "double*":
if p in outputs:
call_args.append(f"_ptr({pname})")
else:
# Map to our local var names
if has_ohlcv:
vmap = {"sourceOpen": "o", "sourceHigh": "h", "sourceLow": "l", "sourceClose": "c", "sourceVolume": "v"}
call_args.append(f"_ptr({vmap.get(pname, pname)})")
elif has_ohlc:
vmap = {"open": "o", "high": "h", "low": "l", "close": "c"}
call_args.append(f"_ptr({vmap.get(pname, pname)})")
elif has_hlc:
vmap = {"high": "h", "low": "l", "close": "c"}
call_args.append(f"_ptr({vmap.get(pname, pname)})")
elif has_hl:
vmap = {"high": "h", "low": "l"}
call_args.append(f"_ptr({vmap.get(pname, pname)})")
elif has_actual_predicted:
vmap = {"actual": "a", "predicted": "p"}
call_args.append(f"_ptr({vmap.get(pname, pname)})")
elif has_xy:
vmap = {"seriesX": "xarr", "seriesY": "yarr", "x": "xarr", "y": "yarr"}
call_args.append(f"_ptr({vmap.get(pname, pname)})")
elif has_price_vol:
vmap = {"price": "pr", "volume": "v"}
call_args.append(f"_ptr({vmap.get(pname, pname)})")
elif has_src_vol:
if pname == "volume":
call_args.append("_ptr(v)")
else:
call_args.append("_ptr(src)")
elif single_src:
call_args.append("_ptr(src)")
elif len(inputs) == 2:
vmap = {}
for ip in inputs:
if ip["name"].startswith("source") or ip["name"].startswith("base"):
vmap[ip["name"]] = "xarr"
else:
vmap[ip["name"]] = "yarr"
call_args.append(f"_ptr({vmap.get(pname, pname)})")
else:
call_args.append(f"_ptr({pname})")
else:
call_args.append(pname)
call_str = ", ".join(call_args)
body.append(f' _check(_lib.qtl_{name}({call_str}))')
# Wrap output
if len(outputs) == 1:
out_name = outputs[0]["name"]
# Decide label
has_period_scalar = any("period" in s[0].lower() or "length" in s[0].lower() for s in scalar_specs)
if has_period_scalar:
# Use first period-like scalar for label
period_var = next(s[0] for s in scalar_specs if "period" in s[0].lower() or "length" in s[0].lower())
body.append(f' return _wrap({out_name}, idx, f"{label}_{{{period_var}}}", "{cat}", offset)')
else:
body.append(f' return _wrap({out_name}, idx, "{label}", "{cat}", offset)')
elif len(outputs) > 1:
# Multi-output
out_dict_parts = []
for p in outputs:
out_dict_parts.append(f'"{p["name"]}": {p["name"]}')
out_dict = ", ".join(out_dict_parts)
body.append(f' return _wrap_multi({{{out_dict}}}, idx, "{cat}", offset)')
else:
body.append(" return None # no output detected")
# Assemble
sig = ", ".join(sig_params)
func = f'def {py_name}({sig}) -> object:\n'
func += f' """{desc}."""\n'
func += "\n".join(body) + "\n"
return func
def generate_category_file(category: str, exports: list[dict]) -> str:
"""Generate a full category module."""
# Map category to Python module name
mod_name = category.replace("-", "_")
header = f'"""quantalib {category} indicators.\n\nAuto-generated — DO NOT EDIT.\n"""\n'
header += "from __future__ import annotations\n\n"
header += "from ._helpers import _arr, _ptr, _out, _wrap, _wrap_multi, _check, _lib\n\n\n"
functions = []
all_names = []
for exp in sorted(exports, key=lambda e: e["name"]):
func = gen_wrapper(exp)
if func:
py_name = PY_NAME.get(exp["name"], exp["name"])
all_names.append(py_name)
functions.append(func)
# __all__
all_str = "__all__ = [\n"
for n in all_names:
all_str += f' "{n}",\n'
all_str += "]\n"
return header + all_str + "\n\n" + "\n\n".join(functions)
def main():
exports = parse_exports()
# Group by category
by_cat: dict[str, list[dict]] = {}
for exp in exports:
cat = exp["category"]
by_cat.setdefault(cat, []).append(exp)
print(f"Parsed {len(exports)} exports in {len(by_cat)} categories:")
for cat, exps in sorted(by_cat.items()):
print(f" {cat}: {len(exps)} indicators")
# Generate files
for cat, exps in sorted(by_cat.items()):
if cat == "uncategorized":
continue
mod_name = cat.replace("-", "_")
# Map category dirs to Python module names
py_mod = {
"trends_FIR": "trends_fir",
"trends_IIR": "trends_iir",
}.get(mod_name, mod_name)
outpath = OUT_DIR / f"{py_mod}.py"
content = generate_category_file(cat, exps)
outpath.write_text(content, encoding="utf-8")
print(f" Generated {outpath.name} ({len(exps)} indicators)")
# List uncategorized
if "uncategorized" in by_cat:
print(f"\n UNCATEGORIZED: {[e['name'] for e in by_cat['uncategorized']]}")
if __name__ == "__main__":
main()