Full Code of kand-ta/kand for AI

main acd4954ab197 cached
365 files
1.1 MB
348.8k tokens
612 symbols
1 requests
Download .txt
Showing preview only (1,256K chars total). Download the full file or copy to clipboard to get everything.
Repository: kand-ta/kand
Branch: main
Commit: acd4954ab197
Files: 365
Total size: 1.1 MB

Directory structure:
gitextract_86qxh_to/

├── .gitattributes
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── CI.yml
│       ├── publish-doc.yml
│       ├── publish-docker.yml
│       ├── publish-rust.yml
│       ├── release.yml
│       ├── rust.yml
│       └── stale.yml
├── .gitignore
├── .python-version
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Cargo.toml
├── Dockerfile
├── LICENSE-APACHE
├── LICENSE-MIT
├── Makefile
├── README.md
├── cliff.toml
├── clippy.toml
├── docs/
│   ├── about.md
│   ├── advance.md
│   ├── api.md
│   ├── install.md
│   └── performance.md
├── kand/
│   ├── Cargo.toml
│   ├── benches/
│   │   ├── bench_main.rs
│   │   ├── benchmarks/
│   │   │   ├── helper.rs
│   │   │   ├── mod.rs
│   │   │   ├── ohlcv/
│   │   │   │   ├── ad_bench.rs
│   │   │   │   ├── adosc_bench.rs
│   │   │   │   ├── adr_bench.rs
│   │   │   │   ├── adx_bench.rs
│   │   │   │   ├── adxr_bench.rs
│   │   │   │   ├── aroon_bench.rs
│   │   │   │   ├── aroonosc_bench.rs
│   │   │   │   ├── atr_bench.rs
│   │   │   │   ├── bbands_bench.rs
│   │   │   │   ├── bop_bench.rs
│   │   │   │   ├── cci_bench.rs
│   │   │   │   ├── cdl_doji_bench.rs
│   │   │   │   ├── cdl_dragonfly_doji_bench.rs
│   │   │   │   ├── cdl_gravestone_doji_bench.rs
│   │   │   │   ├── cdl_hammer_bench.rs
│   │   │   │   ├── cdl_inverted_hammer_bench.rs
│   │   │   │   ├── cdl_long_shadow_bench.rs
│   │   │   │   ├── cdl_marubozu_bench.rs
│   │   │   │   ├── dema_bench.rs
│   │   │   │   ├── dx_bench.rs
│   │   │   │   ├── ecl_bench.rs
│   │   │   │   ├── ema_bench.rs
│   │   │   │   ├── macd_bench.rs
│   │   │   │   ├── medprice_bench.rs
│   │   │   │   ├── mfi_bench.rs
│   │   │   │   ├── midpoint_bench.rs
│   │   │   │   ├── midprice_bench.rs
│   │   │   │   ├── minus_di_bench.rs
│   │   │   │   ├── minus_dm_bench.rs
│   │   │   │   ├── mod.rs
│   │   │   │   ├── mom_bench.rs
│   │   │   │   ├── natr_bench.rs
│   │   │   │   ├── obv_bench.rs
│   │   │   │   ├── plus_di_bench.rs
│   │   │   │   ├── plus_dm_bench.rs
│   │   │   │   ├── rma_bench.rs
│   │   │   │   ├── roc_bench.rs
│   │   │   │   ├── rocp_bench.rs
│   │   │   │   ├── rocr100_bench.rs
│   │   │   │   ├── rocr_bench.rs
│   │   │   │   ├── rsi_bench.rs
│   │   │   │   ├── sar_bench.rs
│   │   │   │   ├── sma_bench.rs
│   │   │   │   ├── stoch_bench.rs
│   │   │   │   ├── supertrend_bench.rs
│   │   │   │   ├── t3_bench.rs
│   │   │   │   ├── tema_bench.rs
│   │   │   │   ├── trange_bench.rs
│   │   │   │   ├── trima_bench.rs
│   │   │   │   ├── trix_bench.rs
│   │   │   │   ├── typprice_bench.rs
│   │   │   │   ├── vegas_bench.rs
│   │   │   │   ├── vwap_bench.rs
│   │   │   │   ├── wclprice_bench.rs
│   │   │   │   ├── willr_bench.rs
│   │   │   │   └── wma_bench.rs
│   │   │   ├── other/
│   │   │   │   └── mod.rs
│   │   │   └── stats/
│   │   │       ├── beta_bench.rs
│   │   │       ├── correl_bench.rs
│   │   │       ├── max_bench.rs
│   │   │       ├── min_bench.rs
│   │   │       ├── mod.rs
│   │   │       ├── stddev_bench.rs
│   │   │       ├── sum_bench.rs
│   │   │       └── var_bench.rs
│   │   └── helper.rs
│   └── src/
│       ├── error.rs
│       ├── helper.rs
│       ├── lib.rs
│       └── ta/
│           ├── mod.rs
│           ├── ohlcv/
│           │   ├── ad.rs
│           │   ├── adosc.rs
│           │   ├── adr.rs
│           │   ├── adx.rs
│           │   ├── adxr.rs
│           │   ├── aroon.rs
│           │   ├── aroonosc.rs
│           │   ├── atr.rs
│           │   ├── bbands.rs
│           │   ├── bop.rs
│           │   ├── cci.rs
│           │   ├── cdl_doji.rs
│           │   ├── cdl_dragonfly_doji.rs
│           │   ├── cdl_gravestone_doji.rs
│           │   ├── cdl_hammer.rs
│           │   ├── cdl_inverted_hammer.rs
│           │   ├── cdl_long_shadow.rs
│           │   ├── cdl_marubozu.rs
│           │   ├── dema.rs
│           │   ├── dx.rs
│           │   ├── ecl.rs
│           │   ├── ema.rs
│           │   ├── ha.rs
│           │   ├── macd.rs
│           │   ├── medprice.rs
│           │   ├── mfi.rs
│           │   ├── midpoint.rs
│           │   ├── midprice.rs
│           │   ├── minus_di.rs
│           │   ├── minus_dm.rs
│           │   ├── mod.rs
│           │   ├── mom.rs
│           │   ├── natr.rs
│           │   ├── obv.rs
│           │   ├── plus_di.rs
│           │   ├── plus_dm.rs
│           │   ├── rma.rs
│           │   ├── roc.rs
│           │   ├── rocp.rs
│           │   ├── rocr.rs
│           │   ├── rocr100.rs
│           │   ├── rsi.rs
│           │   ├── sar.rs
│           │   ├── sma.rs
│           │   ├── stoch.rs
│           │   ├── supertrend.rs
│           │   ├── t3.rs
│           │   ├── tema.rs
│           │   ├── trange.rs
│           │   ├── trima.rs
│           │   ├── trix.rs
│           │   ├── typprice.rs
│           │   ├── vegas.rs
│           │   ├── vwap.rs
│           │   ├── wclprice.rs
│           │   ├── willr.rs
│           │   └── wma.rs
│           ├── other/
│           │   └── mod.rs
│           ├── stats/
│           │   ├── alpha.rs
│           │   ├── beta.rs
│           │   ├── calmar.rs
│           │   ├── correl.rs
│           │   ├── drawdown.rs
│           │   ├── fv.rs
│           │   ├── kelly.rs
│           │   ├── max.rs
│           │   ├── min.rs
│           │   ├── mod.rs
│           │   ├── nper.rs
│           │   ├── ret.rs
│           │   ├── sharpe.rs
│           │   ├── sortino.rs
│           │   ├── stddev.rs
│           │   ├── sum.rs
│           │   ├── var.rs
│           │   └── winrate.rs
│           └── types.rs
├── kand-py/
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── python/
│   │   ├── benches/
│   │   │   ├── .gitkeep
│   │   │   ├── bench_ema.py
│   │   │   ├── bench_ema_incremental.py
│   │   │   ├── bench_ema_incremental_mt.py
│   │   │   ├── bench_ema_mt.py
│   │   │   └── ema.py
│   │   ├── examples/
│   │   │   ├── sma.py
│   │   │   └── sma_thread.py
│   │   └── kand/
│   │       ├── __init__.py
│   │       ├── _kand.pyi
│   │       └── py.typed
│   └── src/
│       ├── helper.rs
│       ├── lib.rs
│       └── ta/
│           ├── mod.rs
│           ├── ohlcv/
│           │   ├── ad.rs
│           │   ├── adosc.rs
│           │   ├── adr.rs
│           │   ├── adx.rs
│           │   ├── adxr.rs
│           │   ├── aroon.rs
│           │   ├── aroonosc.rs
│           │   ├── atr.rs
│           │   ├── bbands.rs
│           │   ├── bop.rs
│           │   ├── cci.rs
│           │   ├── cdl_doji.rs
│           │   ├── cdl_dragonfly_doji.rs
│           │   ├── cdl_gravestone_doji.rs
│           │   ├── cdl_hammer.rs
│           │   ├── cdl_inverted_hammer.rs
│           │   ├── cdl_long_shadow.rs
│           │   ├── cdl_marubozu.rs
│           │   ├── dema.rs
│           │   ├── dx.rs
│           │   ├── ecl.rs
│           │   ├── ema.rs
│           │   ├── macd.rs
│           │   ├── medprice.rs
│           │   ├── mfi.rs
│           │   ├── midpoint.rs
│           │   ├── midprice.rs
│           │   ├── minus_di.rs
│           │   ├── minus_dm.rs
│           │   ├── mod.rs
│           │   ├── mom.rs
│           │   ├── natr.rs
│           │   ├── obv.rs
│           │   ├── plus_di.rs
│           │   ├── plus_dm.rs
│           │   ├── rma.rs
│           │   ├── roc.rs
│           │   ├── rocp.rs
│           │   ├── rocr.rs
│           │   ├── rocr100.rs
│           │   ├── rsi.rs
│           │   ├── sar.rs
│           │   ├── sma.rs
│           │   ├── stoch.rs
│           │   ├── supertrend.rs
│           │   ├── t3.rs
│           │   ├── tema.rs
│           │   ├── trange.rs
│           │   ├── trima.rs
│           │   ├── trix.rs
│           │   ├── typprice.rs
│           │   ├── vegas.rs
│           │   ├── vwap.rs
│           │   ├── wclprice.rs
│           │   ├── willr.rs
│           │   └── wma.rs
│           ├── other/
│           │   └── mod.rs
│           └── stats/
│               ├── beta.rs
│               ├── correl.rs
│               ├── fv.rs
│               ├── max.rs
│               ├── min.rs
│               ├── mod.rs
│               ├── stddev.rs
│               ├── sum.rs
│               └── var.rs
├── kand-wasm/
│   ├── Cargo.toml
│   └── src/
│       ├── lib.rs
│       └── ta/
│           ├── mod.rs
│           ├── ohlcv/
│           │   ├── ad.rs
│           │   ├── adosc.rs
│           │   ├── adr.rs
│           │   ├── adx.rs
│           │   ├── adxr.rs
│           │   ├── apo.rs
│           │   ├── aroon.rs
│           │   ├── aroonosc.rs
│           │   ├── atr.rs
│           │   ├── bbands.rs
│           │   ├── bop.rs
│           │   ├── cci.rs
│           │   ├── cdl_doji.rs
│           │   ├── cdl_dragonfly_doji.rs
│           │   ├── cdl_gravestone_doji.rs
│           │   ├── cdl_hammer.rs
│           │   ├── cdl_inverted_hammer.rs
│           │   ├── cdl_long_shadow.rs
│           │   ├── cdl_marubozu.rs
│           │   ├── cmo.rs
│           │   ├── dema.rs
│           │   ├── dx.rs
│           │   ├── ecl.rs
│           │   ├── ema.rs
│           │   ├── ha.rs
│           │   ├── ht_dcperiod.rs
│           │   ├── ht_dcphase.rs
│           │   ├── ht_phasor.rs
│           │   ├── ht_sine.rs
│           │   ├── ht_trendline.rs
│           │   ├── ht_trendmode.rs
│           │   ├── kama.rs
│           │   ├── linearreg.rs
│           │   ├── linearreg_angle.rs
│           │   ├── linearreg_intercept.rs
│           │   ├── linearreg_slope.rs
│           │   ├── macd.rs
│           │   ├── macdext.rs
│           │   ├── mama.rs
│           │   ├── medprice.rs
│           │   ├── mfi.rs
│           │   ├── midpoint.rs
│           │   ├── midprice.rs
│           │   ├── minus_di.rs
│           │   ├── minus_dm.rs
│           │   ├── mod.rs
│           │   ├── mom.rs
│           │   ├── natr.rs
│           │   ├── obv.rs
│           │   ├── plus_di.rs
│           │   ├── plus_dm.rs
│           │   ├── ppo.rs
│           │   ├── renko.rs
│           │   ├── rma.rs
│           │   ├── roc.rs
│           │   ├── rocp.rs
│           │   ├── rocr.rs
│           │   ├── rocr100.rs
│           │   ├── rsi.rs
│           │   ├── sar.rs
│           │   ├── sarext.rs
│           │   ├── sma.rs
│           │   ├── stoch.rs
│           │   ├── stochf.rs
│           │   ├── stochrsi.rs
│           │   ├── supertrend.rs
│           │   ├── t3.rs
│           │   ├── tema.rs
│           │   ├── trange.rs
│           │   ├── trima.rs
│           │   ├── trix.rs
│           │   ├── tsf.rs
│           │   ├── typprice.rs
│           │   ├── ultosc.rs
│           │   ├── vegas.rs
│           │   ├── vwap.rs
│           │   ├── wclprice.rs
│           │   ├── willr.rs
│           │   └── wma.rs
│           ├── other/
│           │   └── mod.rs
│           ├── stats/
│           │   ├── alpha.rs
│           │   ├── beta.rs
│           │   ├── calmar.rs
│           │   ├── correl.rs
│           │   ├── drawdown.rs
│           │   ├── fv.rs
│           │   ├── kelly.rs
│           │   ├── max.rs
│           │   ├── min.rs
│           │   ├── mod.rs
│           │   ├── nper.rs
│           │   ├── ret.rs
│           │   ├── sharpe.rs
│           │   ├── sortino.rs
│           │   ├── stddev.rs
│           │   ├── sum.rs
│           │   ├── var.rs
│           │   └── winrate.rs
│           └── types.rs
├── mkdocs.yml
├── pyproject.toml
├── rust-toolchain.toml
└── scripts/
    └── gen_stub.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
# Basic settings
* text=auto eol=lf

# Source code files
*.rs    text diff=rust
*.toml  text diff=toml

# Scripts and configuration files
*.sh    text eol=lf
*.bat   text eol=crlf
*.cmd   text eol=crlf
*.json  text
*.yaml  text
*.xml   text
*.md    text
*.txt   text

# Visual Studio files
*.sln        text eol=crlf
*.vcxproj    text eol=crlf
*.vcxproj.filters text eol=crlf

# Binary files
*.png   binary
*.jpg   binary
*.gif   binary
*.ico   binary
*.zip   binary
*.dll   binary
*.exe   binary
*.lib   binary
*.pdf   binary

# Special handling
*.json  merge=union
*.yaml  merge=union
*.xml   merge=union


================================================
FILE: .github/dependabot.yml
================================================
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file

version: 2
updates:
  - package-ecosystem: "cargo"
    directory: "/"
    schedule:
      interval: "weekly"


================================================
FILE: .github/workflows/CI.yml
================================================
# This file is autogenerated by maturin v1.9.3
# To update, run
#
#    maturin generate-ci github
#
name: CI

on:
  push:
    branches:
      - main
      - master
    tags:
      - '*'
  pull_request:
  workflow_dispatch:

permissions:
  contents: read

jobs:
  linux:
    runs-on: ${{ matrix.platform.runner }}
    strategy:
      matrix:
        platform:
          - runner: ubuntu-22.04
            target: x86_64
          - runner: ubuntu-22.04
            target: x86
          - runner: ubuntu-22.04
            target: aarch64
          - runner: ubuntu-22.04
            target: armv7
          - runner: ubuntu-22.04
            target: s390x
          - runner: ubuntu-22.04
            target: ppc64le
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: 3.x
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist --find-interpreter
          sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
          manylinux: auto
      - name: Upload wheels
        uses: actions/upload-artifact@v4
        with:
          name: wheels-linux-${{ matrix.platform.target }}
          path: dist

  musllinux:
    runs-on: ${{ matrix.platform.runner }}
    strategy:
      matrix:
        platform:
          - runner: ubuntu-22.04
            target: x86_64
          - runner: ubuntu-22.04
            target: x86
          - runner: ubuntu-22.04
            target: aarch64
          - runner: ubuntu-22.04
            target: armv7
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: 3.x
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist --find-interpreter
          sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
          manylinux: musllinux_1_2
      - name: Upload wheels
        uses: actions/upload-artifact@v4
        with:
          name: wheels-musllinux-${{ matrix.platform.target }}
          path: dist

  windows:
    runs-on: ${{ matrix.platform.runner }}
    strategy:
      matrix:
        platform:
          - runner: windows-latest
            target: x64
          - runner: windows-latest
            target: x86
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: 3.x
          architecture: ${{ matrix.platform.target }}
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist --find-interpreter
          sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
      - name: Upload wheels
        uses: actions/upload-artifact@v4
        with:
          name: wheels-windows-${{ matrix.platform.target }}
          path: dist

  macos:
    runs-on: ${{ matrix.platform.runner }}
    strategy:
      matrix:
        platform:
          - runner: macos-13
            target: x86_64
          - runner: macos-14
            target: aarch64
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: 3.x
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist --find-interpreter
          sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
      - name: Upload wheels
        uses: actions/upload-artifact@v4
        with:
          name: wheels-macos-${{ matrix.platform.target }}
          path: dist

  sdist:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build sdist
        uses: PyO3/maturin-action@v1
        with:
          command: sdist
          args: --out dist
      - name: Upload sdist
        uses: actions/upload-artifact@v4
        with:
          name: wheels-sdist
          path: dist

  release:
    name: Release
    runs-on: ubuntu-latest
    if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
    needs: [linux, musllinux, windows, macos, sdist]
    permissions:
      # Use to sign the release artifacts
      id-token: write
      # Used to upload release artifacts
      contents: write
      # Used to generate artifact attestation
      attestations: write
    steps:
      - uses: actions/download-artifact@v4
      - name: Generate artifact attestation
        uses: actions/attest-build-provenance@v2
        with:
          subject-path: 'wheels-*/*'
      - name: Publish to PyPI
        if: ${{ startsWith(github.ref, 'refs/tags/') }}
        uses: PyO3/maturin-action@v1
        env:
          MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
        with:
          command: upload
          args: --non-interactive --skip-existing wheels-*/*


================================================
FILE: .github/workflows/publish-doc.yml
================================================
name: Deploy Documentation
on:
  push:
    branches:
      - master
      - main
permissions:
  contents: write
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Configure Git Credentials
        run: |
          git config user.name github-actions[bot]
          git config user.email 41898282+github-actions[bot]@users.noreply.github.com
      - uses: actions/setup-python@v5
        with:
          python-version: 3.x
      - uses: dtolnay/rust-toolchain@stable
      - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
      - uses: actions/cache@v4
        with:
          key: mkdocs-material-${{ env.cache_id }}
          path: .cache
          restore-keys: |
            mkdocs-material-
      - name: Install dependencies
        run: |
          pip install mkdocs-material mkdocstrings mkdocstrings-python mkdocs-minify-plugin
          pip install .
      - name: Copy and process README.md
        run: |
          cp CHANGELOG.md docs/changelog.md
          cp README.md docs/index.md
          sed -i 's|docs/assets/logo.png|assets/logo.png|g' docs/index.md
          sed -i 's|docs/assets/bench_ema.png|assets/bench_ema.png|g' docs/index.md
      - run: mkdocs gh-deploy --force


================================================
FILE: .github/workflows/publish-docker.yml
================================================
name: Docker Package

on:
  push:
    tags: [ 'v*.*.*' ]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log into registry ${{ env.REGISTRY }}
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract Docker metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}

      - name: Build and push Docker image
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max


================================================
FILE: .github/workflows/publish-rust.yml
================================================
name: Publish to crates.io

on:
  push:
    tags:
      - 'v*.*.*'

env:
  CARGO_TERM_COLOR: always

jobs:
  publish:
    name: Build, Test & Publish
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build
        run: cargo build --release --verbose
      - name: Test
        run: cargo test --verbose
      - name: Publish to crates.io
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: cargo publish -p kand


================================================
FILE: .github/workflows/release.yml
================================================
name: Automatic Release

on:
  push:
    tags:
      - 'v*.*.*'

permissions:
  contents: write  # Grants permission to create releases

jobs:
  generate-changelog:
    name: Generate Changelog
    runs-on: ubuntu-latest
    outputs:
      release_body: ${{ steps.git-cliff.outputs.content }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Generate changelog
        id: git-cliff
        uses: orhun/git-cliff-action@v2
        with:
          config: cliff.toml
          args: -vv --latest --strip all

  create-release:
    name: Create GitHub Release
    needs: generate-changelog
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set release version
        shell: bash
        run: echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV

      - name: Create Release
        uses: softprops/action-gh-release@v1
        with:
          name: Release v${{ env.RELEASE_VERSION }}
          body: ${{ needs.generate-changelog.outputs.release_body }}
          draft: false
          prerelease: ${{ contains(github.ref, '-') }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .github/workflows/rust.yml
================================================
name: Rust

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

env:
  CARGO_TERM_COLOR: always

jobs:
  call-ci:
    uses: qntx/workflows/.github/workflows/rust.yml@main


================================================
FILE: .github/workflows/stale.yml
================================================
name: Close Stale Issues and PRs

on:
  schedule:
    - cron: "30 1 * * *"
  workflow_dispatch:

jobs:
  close-stale:
    uses: qntx/workflows/.github/workflows/stale.yml@main


================================================
FILE: .gitignore
================================================
# Generated by Cargo
# will have compiled files and executables
debug/
target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
# Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb

# RustRover
#  JetBrains specific template is maintained in a separate JetBrains.gitignore that can
#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
#  and can be added to the global gitignore or merged into this file.  For a more nuclear
#  option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# Added by cargo

/target


# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
#   For a library or package, you might want to ignore these files since the code is
#   intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# poetry
#   Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
#   This is especially recommended for binary packages to ensure reproducibility, and is more
#   commonly ignored for libraries.
#   https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
#   Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
#   pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
#   in version control.
#   https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
#  JetBrains specific template is maintained in a separate JetBrains.gitignore that can
#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
#  and can be added to the global gitignore or merged into this file.  For a more nuclear
#  option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/


================================================
FILE: .python-version
================================================
3.11


================================================
FILE: CHANGELOG.md
================================================
# Changelog

This document records all significant updates and changes to the Kand project.

## [unreleased]

### 🚀 Features

- Update readme
- Update readme
- Update readme
- Add CONTRIBUTING
- Update Readme add Disclaimer
- Add CORREL (Pearson's Correlation Coefficient) indicator (#27)

### 🐛 Bug Fixes

- *(ci)* Fix publish-rust
- *(.editorconfig)* Fix path
- Update mkdocs.yml

### 💼 Other

- *(deps)* Bump serde_json from 1.0.140 to 1.0.141 (#28)
- *(deps)* Bump rand from 0.9.0 to 0.9.2 (#29)

## [0.2.2] - 2025-03-04

### 🚀 Features

- *(precision)* Add f32 floating-point precision support (#10)

### 🐛 Bug Fixes

- *(tema)* Resolve ambiguous numeric type errors in TEMA calculation
- *(tema)* Resolve ambiguous numeric type errors in TEMA calculation
- *(willr)* Resolve Clippy warnings for strict float comparisons
- *(stats)* Resolve Clippy warnings for strict float comparisons in max/min
- *(ci)* Fix test-rust

### 🚜 Refactor

- Use _inc instead of _incremental

## [0.2.1] - 2025-03-02

### 🚀 Features

- *(precision)* Add f32 floating-point precision support

## [0.2.0] - 2025-03-02

### 🚀 Features

- [**breaking**] Release v0.2.0 with major type system refactoring

### 🐛 Bug Fixes

- *(ci:publish-doc)* Update publish-doc
- *(makefile)* Fix uv-sync, add params for gen_stub.py

### 💼 Other

- Update the types and lib type

## [0.1.3] - 2025-02-27

### 🚜 Refactor

- *(ci:release)* Refactor release ci

## [0.1.2] - 2025-02-27

### 🐛 Bug Fixes

- *(makefile)* Update makefile
- *(bench)* Added #[allow(clippy::expect_used)] to suppress clippy warnings
- *(cdl_gravestone_doji)* Optimize T::from(100).unwrap() to T::from(100).ok_or(KandError::ConversionError)?
- *(var)* Replace unwrap with safe conversion using ok_or(KandError::ConversionError)?

### 🚜 Refactor

- *(ci)* Simplify release workflow and customize changelog footer
- *(tpo)* Replace as f64 with f64::from(u8::try_from(i).unwrap()) for type conversion

### 📚 Documentation

- Update rust doc
- *(helper)* Add missing error documentation for lowest_bars and highest_bars functions

## [0.1.1] - 2025-02-27

### 🚀 Features

- *(ci)* Add changelog ci.

### 🐛 Bug Fixes

- *(aroonosc)* Optimize precision conversion by replacing 'as' with 'T::from' for safety

## [0.0.4] - 2025-02-23

---

> "Quantitative trading begins with data, thrives on strategy, and succeeds through execution. Kand, making trading simpler."


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Kand

First off, thank you for considering contributing to Kand! It's people like you that make Kand such a great tool.

Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue or assessing patches and features.

## Development Setup

Before you start developing, you need to install several required tools:

### Required Tools

1. **Install Rust development tools**:

   ```bash
   cargo install cargo-udeps git-cliff wasm-pack
   ```

   - `cargo-udeps`: Finds unused dependencies
   - `git-cliff`: Generates changelogs
   - `wasm-pack`: WebAssembly package builder

2. **Install uv** (Python package manager):
   Follow the installation guide at: <https://github.com/astral-sh/uv>

3. **Install maturin** (Python-Rust bindings):

   ```bash
   uv tool install maturin
   ```

4. **Install pre-commit** (Git hooks framework):

   ```bash
   pip install pre-commit
   ```

5. **Install make** (Build automation tool):
   - **Linux/macOS**: Usually pre-installed, or install via package manager
   - **Windows**: Install via one of the following options:
     - Install [Git for Windows](https://git-scm.com/download/win) (includes make)
     - Install [Chocolatey](https://chocolatey.org/) and run `choco install make`
     - Install [MSYS2](https://www.msys2.org/) and run `pacman -S make`

Make sure all these tools are properly installed before proceeding with development.

## Development Workflow

Our project is structured into three main parts:

1. `kand`: The core library written in Rust, containing all the technical indicator implementations.
2. `kand-py`: The Python bindings for the core library, allowing Kand to be used in Python.
3. `kand-wasm`: The WebAssembly bindings for the core library, enabling its use in JavaScript/TypeScript environments (web and Node.js).

When making changes, please follow this general workflow:

1. **Modify the Rust code**: All logic for technical indicators resides in the `kand/` directory. Make your changes or additions here first.
2. **Ensure tests pass**: Run the Rust test suite to make sure your changes haven't broken anything.
3. **Update bindings**: If you've added a new indicator or changed a function signature, update the corresponding bindings in the `kand-py/` and/or `kand-wasm/` directories.
4. **Run all checks**: Use the provided `Makefile` to run a full suite of checks, including building, testing, linting, and formatting.

### Using the Makefile

We have a `Makefile` that simplifies the development process. The most important command is:

```bash
make
```

Running `make` by default executes the `pre-commit` target, which will:

- Build the project (`build`)
- Run tests (`test`)
- Run the linter (`clippy`)
- Format the code (`fmt`)
- Generate the changelog (`cliff`)
- Check for unused dependencies (`udeps-check`)
- Build the Wasm package (`wasm-build`)
- Sync the Python environment and generate stubs (`uv-sync`)

Please ensure all checks pass before submitting a pull request.

## Coding Guidelines

To maintain consistency and readability across the codebase, adhere to the following coding guidelines when implementing or modifying technical indicators:

### Parameter Naming and Order

- **Parameter Order**: Function parameters for technical indicators should follow the `(input data, optimization parameters, output data)` pattern:
  - **Input Data**: Includes raw input data (e.g., `input: &[TAFloat]` for a price series, `input: TAFloat` for a new price, `prev_input: TAFloat` for an old price) and computation state (e.g., `prev_sma: TAFloat` for the previous SMA value). Raw input data should precede state data.
  - **Optimization Parameters**: Configuration parameters like `opt_period: TAPeriod` that control the indicator's behavior.
  - **Output Data**: Typically a mutable output parameter (e.g., `output: &mut [TAFloat]`) for full calculations or the function's return value (e.g., `TAFloat`) for incremental calculations.
  - **Examples**:
    - For full SMA calculation: Use `(input, opt_period, output)` as seen in `sma(input: &[TAFloat], opt_period: TAPeriod, output: &mut [TAFloat])`.
    - For incremental SMA calculation: Use `(input, prev_input, prev_sma, opt_period)` as seen in `sma_inc(input: TAFloat, prev_input: TAFloat, prev_sma: TAFloat, opt_period: TAPeriod)`.
- **Naming Conventions**:
  - Use descriptive names for input data, such as `input` (price series or new price), `prev_input` (old price), or `prev_sma` (previous SMA value).
  - Use domain-specific terms with the `opt_` prefix for optimization parameters, such as `opt_period`, `opt_weight`, or `opt_smoothing`, to clearly indicate their role as configuration parameters.
  - For output data, use clear names like `output` or `sma_values` to indicate the result's purpose.
- **Consistency**: Apply this parameter order and naming style to all technical indicator functions, including full calculation functions (e.g., `sma`) and incremental calculation functions (e.g., `sma_inc`), to ensure a cohesive codebase.

## Modifying Existing Indicators

1. Locate the indicator's code in the `kand/src/` directory and apply your changes.
2. Run the tests to ensure correctness: `make test`.
3. If you have changed any function signatures, update the corresponding code in `kand-py` and/or `kand-wasm`.
4. Run `make` to perform all pre-commit checks.

## Adding New Indicators

Adding a new indicator is exciting! To ensure quality and consistency, please follow these steps:

1. Implement the new indicator in the `kand/` directory.
2. Add a new test module for your indicator.
3. **Provide accurate test data**: This is a critical step.
    - **If the indicator exists in TA-Lib**, your test data **must** align with the output of TA-Lib. This ensures compatibility and correctness.
    - **If the indicator is not in TA-Lib**, you must provide a reference to verify the accuracy of your implementation and test data. This can be:
        - A Python implementation of the indicator.
        - A link to a trading website, academic paper, or another reliable source that defines the indicator and provides example calculations.
4. Add the Python bindings for your new indicator in the `kand-py/` directory.
5. Run `make` to ensure everything is in order.

## Pull Request Process

1. Fork the repository and create your branch from `main`.
2. Make your changes, adhering to the workflow described above.
3. Ensure the test suite passes and that all `make` checks are green.
4. Issue that pull request! We'll review it as soon as we can.

Thank you for your contribution!


================================================
FILE: Cargo.toml
================================================
[workspace]
members = ["kand", "kand-py", "kand-wasm"]
# Only check / build main crates by default (check all with `--workspace`)
default-members = ["kand"]

resolver = "3"

[workspace.dependencies]
kand = { path = "./kand", default-features = false, features = ["f64", "i64", "check"] }

approx = "^0.5.1"
criterion = "0.7.0"
csv = "^1.3.1"
ndarray = "^0.16.1"
num_enum = "^0.7.3"
num-traits = "^0.2.19"
numpy = "0.25.0"
pyo3 = "0.25.1"
rand = "^0.9.2"
rayon = "^1.10.0"
rust_decimal = "^1.36.0"
serde = { version = "^1.0.219", features = ["derive"] }
serde_json = "^1.0.141"
thiserror = "^2.0.12"
wasm-bindgen = "^0.2.100"

[profile.release]
lto = true           # Enable Link Time Optimization to remove unused code
codegen-units = 1    # Maximize optimization at the cost of slower compilation
panic = 'abort'      # Remove panic handling to reduce binary size
strip = true         # Fully strip debug symbols; debugging in production will be difficult


================================================
FILE: Dockerfile
================================================
FROM --platform=$BUILDPLATFORM python:3.12-slim-bullseye AS build
ENV HOME="/root"
WORKDIR $HOME

# Install build dependencies and set up Python environment
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
    build-essential \
    curl \
    cmake \
    gcc-aarch64-linux-gnu \
    g++-aarch64-linux-gnu \
    patchelf && \
    rm -rf /var/lib/apt/lists/* && \
    python -m venv $HOME/.venv && \
    .venv/bin/pip install --no-cache-dir "maturin>=1.7,<2.0"
ENV PATH="$HOME/.venv/bin:$PATH"

# Set Rust target based on the target platform
ARG TARGETPLATFORM
RUN case "$TARGETPLATFORM" in \
  "linux/arm64") echo "aarch64-unknown-linux-gnu" > rust_target.txt ;; \
  "linux/amd64") echo "x86_64-unknown-linux-gnu" > rust_target.txt ;; \
  *) exit 1 ;; \
  esac

# Install Rust toolchain
COPY rust-toolchain.toml rust-toolchain.toml
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --target $(cat rust_target.txt) --profile minimal --default-toolchain none && \
    . $HOME/.cargo/env && \
    rustup target add $(cat rust_target.txt)

# Copy project files and build
COPY kand kand
COPY kand-py kand-py
COPY Cargo.toml Cargo.lock pyproject.toml README.md LICENSE-MIT LICENSE-APACHE ./
COPY python python

# Build Python extension
RUN case "${TARGETPLATFORM}" in \
  "linux/arm64") \
    export JEMALLOC_SYS_WITH_LG_PAGE=16; \
    export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc; \
    export CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc; \
    export CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++; \
    ;; \
  *) \
    ;; \
  esac && \
  . $HOME/.cargo/env && \
  maturin build --release --target $(cat rust_target.txt) -i python3.12 && \
  mkdir -p /wheels && \
  cp target/wheels/*.whl /wheels/ && \
  rm -rf target $HOME/.cargo/registry $HOME/.cargo/git

# Final image: Provide Python runtime
FROM python:3.12-slim-bullseye
WORKDIR /app

# Copy and install the wheel file
COPY --from=build /wheels/ /wheels/
RUN pip install --no-cache-dir /wheels/*.whl && rm -rf \
    /wheels \
    /root/.cache \
    /usr/share/doc \
    /usr/share/man \
    /usr/share/locale \
    /var/lib/apt/lists/* \
    /var/cache/apt/archives/*

# Set Python path
ENV PYTHONPATH=/app


================================================
FILE: LICENSE-APACHE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: LICENSE-MIT
================================================
MIT License

Copyright (c) 2025 Kand TA

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: Makefile
================================================
# Makefile for Rust project using Cargo

.PHONY: all
all: pre-commit

# Build the project with all features enabled in release mode
.PHONY: build
build:
	cargo build --release --all-features

# Update dependencies to their latest compatible versions
.PHONY: update
update:
	cargo update

# Run the project with all features enabled in release mode
.PHONY: run
run:
	cargo run --release --all-features

# Run all tests with all features enabled
.PHONY: test
test:
	cargo test --all-features

# Run benchmarks with all features enabled
.PHONY: bench
bench:
	cargo bench --all-features

# Run Clippy linter with nightly toolchain, fixing issues automatically
# and applying strict linting rules
.PHONY: clippy
clippy:
	cargo +nightly clippy --fix \
		--all-targets \
		--all-features \
		--allow-dirty \
		--allow-staged \
		-- -D warnings \
		-W clippy::pedantic \
		-W clippy::nursery \
		-W clippy::unwrap_used \
		-W clippy::expect_used

# Format the code using rustfmt with nightly toolchain
.PHONY: fmt
fmt:
	cargo +nightly fmt

# Generate documentation for all crates and open it in the browser
.PHONY: doc
doc:
	cargo +nightly doc --all-features --no-deps --open

# Generate CHANGELOG.md using git-cliff
.PHONY: cliff
cliff:
	git-cliff
	git cliff --output CHANGELOG.md

# Sync Python environment using uv
.PHONY: uv-sync
uv-sync:
	uv venv
	uv lock --upgrade
	uv sync
	uv run "./scripts/gen_stub.py" kand kand-py/python/kand/_kand.pyi

# Check for unused dependencies using cargo-udeps with nightly toolchain
.PHONY: udeps
udeps:
	cargo +nightly udeps --all-features

# Update and run udeps to check for unused dependencies
.PHONY: udeps-check
udeps-check:
	cargo update
	cargo +nightly udeps --all-features


# Build the wasm package
.PHONY: wasm-build
wasm-build:
	@echo "Building WASM package..."
	(cd kand-wasm && wasm-pack build --target web && wasm-pack pack pkg)

# Publish the wasm package to npm
# Note: You must be logged in to npm for this to work (`npm login`)
.PHONY: wasm-publish
wasm-publish: wasm-build
	@echo "Publishing WASM package to npm..."
	(cd kand-wasm/pkg && npm pkg fix && npm pkg set name="kand" && npm publish --access public)

# Convenience target to build and publish wasm
.PHONY: wasm
wasm: wasm-publish

# Run pre-commit hooks on all files
.PHONY: pre-commit
pre-commit:
	$(MAKE) build
	$(MAKE) test
	$(MAKE) clippy
	$(MAKE) fmt
	$(MAKE) cliff
	$(MAKE) udeps-check
	$(MAKE) wasm-build
	$(MAKE) uv-sync


================================================
FILE: README.md
================================================
<h1 align="center">
  <img src="docs/assets/logo.png" alt="Kand Logo" width="250">
</h1>
<div align="center">
  <a href="https://crates.io/crates/kand">
    <img src="https://img.shields.io/crates/v/kand.svg" alt="Crates.io"/>
  </a>
  <a href="https://pypi.python.org/pypi/kand">
    <img src="https://img.shields.io/pypi/v/kand.svg" alt="PyPI Version"/>
  </a>
  <a href="https://www.npmjs.com/package/kand">
    <img src="https://img.shields.io/npm/v/kand.svg" alt="NPM Version"/>
  </a>
  <a href="https://pypi.python.org/pypi/kand">
    <img src="https://img.shields.io/pypi/pyversions/kand.svg" alt="Python Versions"/>
  </a>
  <a href="https://github.com/kand-ta/kand/actions/workflows/CI.yml">
    <img src="https://github.com/kand-ta/kand/actions/workflows/CI.yml/badge.svg" alt="CI Status"/>
  </a>
  <a href="https://docs.rs/kand">
    <img src="https://docs.rs/kand/badge.svg" alt="Docs.rs"/>
  </a>
  <a href="https://pypi.python.org/pypi/kand">
    <img src="https://img.shields.io/pypi/l/kand.svg" alt="License"/>
  </a>
</div>
<p align="center">
  <b>Documentation</b>:
  <a href="https://docs.rs/kand">Rust</a>
  -
  <a href="https://kand-ta.github.io/kand/">Python</a>
  |
  <b>Repository</b>:
  <a href="https://github.com/kand-ta/kand">GitHub</a>
</p>
<h2 align="center">
  <b>Kand: A Modern, High-Performance Technical Analysis Library</b>
</h2>

> [!WARNING]
> This project is under active development. APIs may change, and some features might not be fully implemented or tested yet. Contributions and feedback are welcome!

<p align="center">
  <picture align="center">
    <img alt="EMA Performance Comparison" src="docs/assets/bench_ema.png" width="600">
  </picture>
</p>

<p align="center">
  <i>EMA calculation performance comparison across different implementations.</i>
</p>

## Why Kand?

`Kand` is engineered as a modern replacement for `TA-Lib`, addressing its core limitations—such as single-threaded execution, Python GIL constraints, memory overhead, and inefficient real-time processing—while preserving its strengths in comprehensive indicator support and ease of integration. Built in Rust, `Kand` delivers superior performance, safety, and flexibility for quantitative trading, data science, and financial analysis.

- **⚡ Superior Performance with Memory Safety**
  Leveraging Rust's efficiency, `Kand` achieves speeds rivaling or exceeding `TA-Lib`'s peak performance, but with built-in memory safety that eliminates common vulnerabilities and reduces overhead in `TA-Lib`'s C-based implementation.

- **🔓 True Multithreading Capabilities**
  Unlike `TA-Lib`, which is hindered by Python's GIL and single-threaded design, `Kand` enables seamless parallel processing across multiple cores, unlocking significant gains in multi-threaded environments for large-scale computations.

- **⚙️ Efficient Real-Time Incremental Updates**
  `Kand` introduces O(1) complexity for incremental calculations, ideal for streaming data and real-time applications—overcoming `TA-Lib`'s reliance on batch processing, which introduces latency and inefficiency in dynamic scenarios.

- **🚀 Zero-Copy NumPy Integration**
  With native, zero-copy data sharing via Rust-NumPy bindings, `Kand` ensures lossless, high-speed data flow between Python and Rust, addressing `TA-Lib`'s memory copying overhead and enabling ultra-low latency (~7ns) operations.

- **📊 Expanded Indicator Suite**
  Kand supports a wide array of standard indicators (e.g., EMA, RSI, MACD) like ``TA-Lib``, while pioneering advanced ones such as Vegas, VWAP, and Supertrend, extending analytical capabilities beyond `TA-Lib`'s traditional scope.

- **📦 Streamlined Installation and Lightweight Design**
  Install with a single `pip install kand` command, featuring precompiled wheels and no complex C dependencies—solving `TA-Lib`'s notoriously cumbersome setup and reducing package bloat for effortless deployment.

- **💻 Broad Cross-Platform Compatibility**
  Seamlessly runs on macOS, Linux, and Windows, with additional support for JavaScript/TypeScript via `WebAssembly`, providing greater universality than `TA-Lib`'s platform-specific challenges.

> *If you truly understand `TA-Lib`'s limitations, you'll appreciate Kand's innovations.* `Kand` isn't just about fixing what's broken—it's about enabling what's possible. Dive deeper at [**why `kand`**](https://kand-ta.github.io/kand/about).

### Python API

The Python interface of `kand` leverages PyO3 for ultra-low latency bindings to the Rust core, seamlessly integrating with NumPy for zero-copy operations and true thread-safe calculations. Below are examples for batch and incremental usage.

```python
import numpy as np
from kand import ema

# Batch EMA computation with zero-copy NumPy integration
prices = np.array([10.0, 11.0, 12.0, 13.0, 14.0], dtype=np.float64)
ema_values = ema(prices, period=3)

# Incremental EMA update for streaming data
prev_ema = 13.5
new_price = 15.0
new_ema = ema_inc(new_price, prev_ema, period=3)
```

**Key Features:**

- **Zero-Copy**: Operates directly on NumPy arrays, avoiding memory duplication.
- **GIL-Free**: Rust backend releases the Python GIL, enabling parallel execution.
- **Incremental Updates**: O(1) complexity for real-time applications.

---

### Rust API

The Rust interface in `kand` provides a high-performance, type-safe implementation of EMA with flexible parameter control. It supports both Vec and ndarray inputs for batch and incremental calculations, as shown below.

```rust
use kand::ohlcv::ema;
use ndarray::Array1;

// Batch EMA calculation over a price series
let prices = vec![10.0, 11.0, 12.0, 13.0, 14.0];
let mut ema_values = vec![0.0; prices.len()];
ema::ema(&prices, 3, None, &mut ema_values)?;

// Batch EMA with ndarray for scientific workflows
let prices = Array1::from_vec(vec![10.0, 11.0, 12.0, 13.0, 14.0]);
let mut ema_values = Array1::zeros(prices.len());
ema::ema(&prices, 3, None, &mut ema_values)?;

// Constant-time incremental EMA update
let prev_ema = 13.5;
let new_price = 15.0;
let new_ema = ema::ema_inc(new_price, prev_ema, 3, None)?;
```

**Key Features:**

- **Memory Efficiency**: Leverages mutable buffers (`&mut Vec<f64>` or `&mut Array1<f64>`) to store results, slashing memory allocations.
- **Error Handling**: Returns `Result<(), KandError>` or `Result<f64, KandError>` for reliable failure detection (e.g., invalid period, NaN inputs).
- **Incremental Design**: O(1) updates tailored for real-time systems.

---

### JavaScript/TypeScript API

The JavaScript/TypeScript interface provides WebAssembly bindings for high-performance technical analysis in web applications and Node.js projects. It delivers near-native performance with a clean, synchronous API.

```typescript
import { ema, emaInc } from 'kand';

// Batch EMA computation for price series
const prices = new Float64Array([10.0, 11.0, 12.0, 13.0, 14.0]);
const emaValues = ema(prices, 3, null);
console.log(emaValues);

// Incremental EMA update for streaming data
const prevEma = 13.5;
const newPrice = 15.0;
const newEma = emaInc(newPrice, prevEma, 3, null);
console.log(newEma);

// Custom smoothing factor
const customK = 0.5;
const customEma = emaInc(newPrice, prevEma, 3, customK);
```

**Key Features:**

- **WebAssembly Performance**: Near-native speed through optimized WASM bindings.
- **Type Safety**: Full TypeScript definitions with comprehensive JSDoc documentation.
- **ES Module Standard**: Adheres to the ES module standard for native integration with modern JavaScript environments.

---

## Setup

### Python

Get started with Kand in one command - no extra configuration needed:

```bash
pip install kand
```

### Rust

You can take latest release from [`crates.io`](https://crates.io/crates/kand), or if you want to use the latest features / performance improvements point to the `main` branch of this repo.

```bash
cargo add kand
```

Recommend Rust version `>=1.80`.

### JavaScript/TypeScript

For web applications and Node.js projects, install Kand via npm:

```bash
npm i kand
```

The package provides WebAssembly bindings for high-performance technical analysis in JavaScript and TypeScript environments.

## Functions List

### OHLCV Based

- [x] **AD** - Chaikin A/D Line
- [x] **ADOSC** - Chaikin A/D Oscillator
- [x] **ADR** - Average Daily Range
- [x] **ADX** - Average Directional Movement Index
- [x] **ADXR** - Average Directional Movement Index Rating
- [x] **AROON** - Aroon
- [x] **AROONOSC** - Aroon Oscillator
- [x] **ATR** - Average True Range
- [x] **BBANDS** - Bollinger Bands
- [x] **BOP** - Balance Of Power
- [x] **CCI** - Commodity Channel Index
- [x] **CDL_DOJI** - Doji
- [x] **CDL_DRAGONFLY_DOJI** - Dragonfly Doji
- [x] **CDL_GRAVESTONE_DOJI** - Gravestone Doji
- [x] **CDL_HAMMER** - Hammer
- [x] **CDL_INVERTED_HAMMER** - Inverted Hammer
- [x] **CDL_LONG_LOWER_SHADOW** - Long Lower Shadow
- [x] **CDL_LONG_UPPER_SHADOW** - Long Upper Shadow
- [x] **CDL_MARUBOZU** - Marubozu
- [x] **DEMA** - Double Exponential Moving Average
- [x] **DX** - Directional Movement Index
- [x] **EMA** - Exponential Moving Average
- [x] **ECL** - Expanded Camarilla Levels **[Untested]**
- [x] **HA** - Heikin Ashi Chart
- [x] **MACD** - Moving Average Convergence/Divergence **[Unstable]**
- [x] **MEDPRICE** - Median Price
- [x] **MFI** - Money Flow Index **[No Incremental]**
- [x] **MIDPOINT** - MidPoint over period
- [x] **MIDPRICE** - Midpoint Price over period
- [x] **MINUS_DI** - Minus Directional Indicator
- [x] **MINUS_DM** - Minus Directional Movement
- [x] **MOM** - Momentum
- [x] **NATR** - Normalized Average True Range
- [x] **OBV** - On Balance Volume
- [x] **PLUS_DI** - Plus Directional Indicator
- [x] **PLUS_DM** - Plus Directional Movement
- [x] **RMA** - Rolling Moving Average
- [x] **ROC** - Rate of change : ((price/prevPrice)-1)*100
- [x] **ROCP** - Rate of change Percentage: (price-prevPrice)/prevPrice
- [x] **ROCR** - Rate of change ratio: (price/prevPrice)
- [x] **ROCR100** - Rate of change ratio 100 scale: (price/prevPrice)*100
- [x] **RSI** - Relative Strength Index
- [x] **SAR** - Parabolic SAR
- [x] **SMA** - Simple Moving Average
- [x] **STOCH** - Stochastic **[No Incremental]**
- [x] **SUPERTREND** - Super Trend Indicator
- [x] **T3** - Triple Exponential Moving Average (T3)
- [x] **TEMA** - Triple Exponential Moving Average
- [x] **TRANGE** - True Range
- [x] **TRIMA** - Triangular Moving Average
- [x] **TRIX** - 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA
- [x] **TYPPRICE** - Typical Price
- [x] **VEGAS** - VEGAS Channel and Trend Boundary EMAs **[Untested]**
- [x] **VWAP** - Volume Weighted Average Price
- [x] **WCLPRICE** - Weighted Close Price
- [x] **WILLR** - Williams' %R
- [x] **WMA** - Weighted Moving Average

### Statistical Analysis

- [ ] **ALPHA** - Alpha: Measures excess returns over market
- [ ] **BETA** - Beta: Measures sensitivity to market volatility
- [ ] **CALMAR** - Calmar Ratio: Annual return to maximum drawdown ratio
- [x] **CORREL** - Pearson's Correlation Coefficient
- [ ] **DRAWDOWN** - Maximum Drawdown: Maximum potential loss
- [ ] **KELLY** - Kelly Criterion: Optimal position sizing
- [x] **MAX** - Highest value over a specified period
- [x] **MIN** - Lowest value over a specified period
- [ ] **SHARPE** - Sharpe Ratio: Risk-adjusted return measure
- [ ] **SORTINO** - Sortino Ratio: Downside risk-adjusted returns
- [x] **STDDEV** - Standard Deviation
- [x] **SUM** - Summation
- [x] **VAR** - Variance
- [ ] **WINRATE** - Win Rate: Strategy success probability

## Contributing

We are passionate about supporting contributors of all levels of experience and would love to see
you get involved in the project. See the
[contributing guide](https://github.com/rust-ta/kand/blob/main/CONTRIBUTING.md) to get started.

## License

This project is licensed under either of the following licenses, at your option:

- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0))
- MIT license ([LICENSE-MIT](LICENSE-MIT) or [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT))

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in kand by you, as defined in the Apache-2.0 license, shall be dually licensed as above, without any additional terms or conditions.

## Disclaimer

This project is provided "as is" without any warranties or guarantees of any kind, express or implied, including but not limited to warranties of merchantability, fitness for a particular purpose, accuracy, or non-infringement. The authors and contributors of this project are not liable for any damages, losses, or liabilities resulting from the use of this project, including but not limited to financial losses, investment decisions, or trading outcomes.

Trading or investing in financial instruments involves high risks, including the potential loss of some or all of your investment amount, and may not be suitable for all users. Before using this project for any financial purposes, you should carefully consider your investment objectives, level of experience, and risk tolerance, and seek independent professional advice if needed.

The information, data, and calculations provided by this project are for informational purposes only and do not constitute financial, investment, or trading advice, recommendations, or solicitations to buy or sell any securities or assets. We do not guarantee the accuracy, completeness, or timeliness of any output, and users assume all risks and liabilities associated with its use.


================================================
FILE: cliff.toml
================================================
# git-cliff ~ default configuration file
# https://git-cliff.org/docs/configuration
#
# Lines starting with "#" are comments.
# Configuration options are organized into tables and keys.
# See documentation for more information on available options.

[changelog]
# template for the changelog header
header = """
# Changelog\n
This document records all significant updates and changes to the Kand project. \n
"""
# template for the changelog body
# https://keats.github.io/tera/docs/#introduction
body = """
{% if version %}\
    ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
    ## [unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
    ### {{ group | striptags | trim | upper_first }}
    {% for commit in commits %}
        - {% if commit.scope %}*({{ commit.scope }})* {% endif %}\
            {% if commit.breaking %}[**breaking**] {% endif %}\
            {{ commit.message | upper_first }}\
    {% endfor %}
{% endfor %}\n
"""
# template for the changelog footer
footer = """
---

> "Quantitative trading begins with data, thrives on strategy, and succeeds through execution. Kand, making trading simpler."
"""
# remove the leading and trailing s
trim = true
# postprocessors
postprocessors = [
  # { pattern = '<REPO>', replace = "https://github.com/orhun/git-cliff" }, # replace repository URL
]
# render body even when there are no releases to process
# render_always = true
# output file path
# output = "test.md"

[git]
# parse the commits based on https://www.conventionalcommits.org
conventional_commits = true
# filter out the commits that are not conventional
filter_unconventional = true
# process each line of a commit as an individual commit
split_commits = false
# regex for preprocessing the commit messages
commit_preprocessors = [
  # Replace issue numbers
  #{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](<REPO>/issues/${2}))"},
  # Check spelling of the commit with https://github.com/crate-ci/typos
  # If the spelling is incorrect, it will be automatically fixed.
  #{ pattern = '.*', replace_command = 'typos --write-changes -' },
]
# regex for parsing and grouping commits
commit_parsers = [
  { message = "^feat", group = "<!-- 0 -->🚀 Features" },
  { message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
  { message = "^doc", group = "<!-- 3 -->📚 Documentation" },
  { message = "^perf", group = "<!-- 4 -->⚡ Performance" },
  { message = "^refactor", group = "<!-- 2 -->🚜 Refactor" },
  { message = "^style", group = "<!-- 5 -->🎨 Styling" },
  { message = "^test", group = "<!-- 6 -->🧪 Testing" },
  { message = "^chore\\(release\\): prepare for", skip = true },
  { message = "^chore\\(deps.*\\)", skip = true },
  { message = "^chore\\(pr\\)", skip = true },
  { message = "^chore\\(pull\\)", skip = true },
  { message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" },
  { body = ".*security", group = "<!-- 8 -->🛡️ Security" },
  { message = "^revert", group = "<!-- 9 -->◀️ Revert" },
  { message = ".*", group = "<!-- 10 -->💼 Other" },
]
# filter out the commits that are not matched by commit parsers
filter_commits = false
# sort the tags topologically
topo_order = false
# sort the commits inside sections by oldest/newest order
sort_commits = "oldest"


================================================
FILE: clippy.toml
================================================
too-many-arguments-threshold = 20
type-complexity-threshold = 500
allow-expect-in-tests = true
allow-unwrap-in-tests = true


================================================
FILE: docs/about.md
================================================
# About Kand

## The Motivation

TALib has long been a cornerstone for financial indicator calculations, valued for its comprehensive feature set. However, as modern workflows demand higher performance and flexibility, its limitations have become apparent:

- **Performance Bottlenecks**: TALib’s C-based core, while fast, is constrained by Python’s Global Interpreter Lock (GIL), limiting multi-threaded potential in today’s multi-core world. This issue has been a persistent challenge, as noted in discussions around the [Python bindings](https://github.com/TA-Lib/ta-lib-python/issues/675).
- **Complex Setup**: Installing TALib often involves wrangling C library dependencies, a hurdle for users seeking quick deployment. The fact that installation issues dominate their [GitHub issues](https://github.com/TA-Lib/ta-lib-python/issues) speaks volumes about this challenge.
- **Batch-Only Design**: TALib focuses on full-batch computations, lacking efficient incremental updates needed for real-time systems. While its Python bindings offer a stream feature for incremental calculations, it still relies on batch processing underneath, resulting in slower performance. Even attempts to address parallelism in the [native C library](https://github.com/TA-Lib/ta-lib/issues/49) highlight its multi-threading constraints.

These pain points inspired us to rethink how financial tools should work in a modern, high-performance context.

## Why We Built Kand

`kand` was created to address TALib’s shortcomings and deliver a next-generation solution for financial developers. Leveraging Rust’s speed and safety, we set out to build a library that’s not just an alternative, but a leap forward:

- **Elite Performance**: Written in Rust, `kand` matches or exceeds TALib’s speed while adding GIL-free multi-threading for true parallelism.
- **Seamless Integration**: Powered by `rust-numpy`, `kand` shares array memory addresses directly between Python and Rust, enabling true zero-copy data access without any overhead in cross-language operations.
- **Real-Time Ready**: True O(1) complexity with near-zero overhead—each update is just a pure variable computation without loops or batching, making it ideal for real-time streaming data processing.
- **Frictionless Setup**: A single `pip install` command replaces TALib’s cumbersome C setup, with precompiled wheels for all major platforms.
- **Cross-Platform Power**: Runs effortlessly on Linux, macOS, and Windows—musl Linux included.

## Our Vision

`kand` isn’t just about fixing what’s broken—it’s about enabling what’s possible. Whether you’re a quant trader, data scientist, or developer, we aim to provide a tool that’s fast, reliable, and effortless to use, so you can focus on building, not battling your tools.

To see `kand` in action, check out our [Installation Guide](install.md) or dive into the [API Documentation](api.md).


================================================
FILE: docs/advance.md
================================================
# Advanced Configuration Guide

This guide explains how to customize `kand` for numerical precision, optimization, and cross-platform use. Custom configurations require building from source with `maturin`, as the default `pip install kand` provides a pre-built package with fixed settings (`f64`, `i64`, `check`).

## Customization Options

### Numerical Precision

Choose the floating-point precision for your needs:

- **`f32` (32-bit)**: Lower memory usage, great for large datasets or constrained systems.
- **`f64` (64-bit)**: Default, higher precision for complex calculations.

| Precision | Memory Usage | Precision | Use Case                  |
|-----------|--------------|-----------|---------------------------|
| `f32`     | Low          | Lower     | Embedded systems, big data |
| `f64`     | Medium       | Higher    | Scientific computing      |

### Integer Types

Select the integer type for indexing:

- **`i32` (32-bit)**: Memory-efficient, suits smaller applications.
- **`i64` (64-bit)**: Default, handles larger datasets.

| Type  | Description     | Best For                  |
|-------|-----------------|---------------------------|
| `i32` | 32-bit integers | Small-scale applications  |
| `i64` | 64-bit integers | Large datasets            |

### Validation Levels

Adjust validation for safety vs. performance:

- **`check`**: Basic validation, ideal for production.
- **`check-nan`**: Detailed checks, best for debugging.
- **None**: No validation, fastest but risky.

| Level        | Safety | Performance | Use Case            |
|--------------|--------|-------------|---------------------|
| `check`      | High   | Medium      | Production          |
| `check-nan` | Highest| Slowest     | Debugging           |
| None         | Low    | Fastest     | Tested environments |

!!! warning "Performance vs. Safety"
    Skipping validation boosts speed but may cause issues with invalid inputs. Use cautiously.

---

## Building from Source

Customizing `kand` requires a local build with `maturin`.

### Prerequisites

- **Python**: 3.8+
- **Rust**: 1.80+
- **maturin**: `pip install maturin`

### Build Steps

1. **Clone the Repository**:

   ```bash
   git clone https://github.com/kand-ta/kand.git
   cd kand
   ```

2. **Build with Custom Features**:
    For development (editable install):

    ```bash
    maturin develop --features f32,i64,check
    ```

!!! tip "High-Performance Build Example"
    Use `--release` for an optimized build:
    ```bash
    maturin build --release --features f64,i64,check
    ```

---

## Troubleshooting

- **Feature Not Working**: Ensure `--features` matches your desired configuration (e.g., `f32,i64,check`).
- **Build Fails**: Check Rust/Python versions or run `cargo build` to debug.
- **Help**: Visit [GitHub Discussions](https://github.com/kand-ta/kand/discussions).

---

## Performance Trade-offs

| Configuration         | Memory | Speed  | Precision |
|-----------------------|--------|--------|-----------|
| `f32, i32, no checks` | Lowest | Fastest| Lowest    |
| `f32, i64, check`     | Low    | Fast   | Low       |
| `f64, i64, check`     | Medium | Medium | High      |
| `f64, i64, check-nan` | High   | Slowest| Highest   |

See the [Performance Guide](performance.md) for benchmarks.


================================================
FILE: docs/api.md
================================================

::: kand


================================================
FILE: docs/install.md
================================================
# Installation Guide

Get started with `kand` through Python or Docker. This guide covers all installation methods and system compatibility details.

## Python Installation

### Requirements
- Python 3.8+
- `pip` (Python package installer)

### Install from PyPI
Install `kand` with one command—precompiled wheels available for instant setup:

```bash
pip install kand
```

!!! tip "Supported Platforms & Python Versions"
    We provide precompiled packages on PyPI for major systems and Python versions:

    | Platform     | Supported Python Versions         |
    |--------------|-----------------------------------|
    | **Linux**    | 3.8, 3.9, 3.10, 3.11, 3.12       |
    | **musl Linux** | 3.8, 3.9, 3.10, 3.11, 3.12     |
    | **Windows**  | 3.8, 3.9, 3.10, 3.11, 3.12, 3.13 |
    | **macOS**    | 3.8, 3.9, 3.10, 3.11, 3.12, 3.13 |

    No compilation needed—just `pip install` and go!

## Docker Usage

### Pull the Official Image
Grab the latest `kand` container:

```bash
docker pull ghcr.io/rust-ta/kand:latest
```

### Run with Docker
Launch it interactively:

```bash
docker run -it --rm ghcr.io/rust-ta/kand:latest
```

Or build your own:

```bash
docker build -t my-kand-app .
docker run -it --rm my-kand-app
```

## Troubleshooting

Encounter issues? Try these steps:

1. Update `pip` or `cargo` to the latest version.
2. Verify Python (3.8+) or Rust (1.80+) compatibility.
3. Ensure the Docker daemon is running.
4. Check [GitHub Issues](https://github.com/rust-ta/kand/issues) for solutions.

!!! note
    Still stuck? Join our community or file an issue on GitHub!

## Next Steps

- Explore the [API Documentation](api.md) to dive into `kand`.
- Join our community for help and updates.
- Report bugs or suggestions on [GitHub](https://github.com/rust-ta/kand/issues).


================================================
FILE: docs/performance.md
================================================
# Performance Testing

## Introduction

This document showcases the performance testing results for Exponential Moving Average (EMA) computations, comparing single-threaded and multi-threaded approaches. Tests were conducted on two platforms: a Windows laptop featuring an Intel Core i7-13700 processor and a Mac Mini powered by an Apple M4 chip. The analysis highlights how thread count impacts computational efficiency across diverse dataset sizes, with a special focus on the superior scalability of `kand` over `talib`.

!!! info
    **`kand` vs. `talib`**: While `talib` is constrained to single-threaded execution, `kand` leverages multi-threading to unlock significant performance gains, especially on modern multi-core hardware.

---

## Test Environment

!!! abstract "Hardware Specifications"
    === "Windows Platform"
        - **Device**: Laptop
        - **CPU**: Intel Core i7-13700
            * 6 Performance cores
        - **OS**: Windows 11 Pro

    === "Mac Platform"
        - **Device**: Mac Mini
        - **CPU**: Apple M4
            * 4 Performance cores
        - **OS**: macOS Sonoma

!!! info "Software Stack"
    | Component     | Version | Description |
    |--------------|---------|-------------|
    | :snake: Python | 3.11    | Core runtime environment |
    | :chart_with_upwards_trend: TA-Lib | 0.6.3   | Technical analysis baseline |
    | :zap: Kand    | 0.0.11  | High-performance implementation |

!!! tip "Version Compatibility"
    All tests were conducted using the latest stable releases of each component. Performance characteristics may vary with different versions.

---

## Test Methodology

!!! note "Test Code Location"
    All benchmark code is available in the `python/benches` directory:
    - `bench_ema.py`: Single-thread performance testing
    - `bench_ema_mt.py`: Multi-thread performance testing

!!! warning "System Variability"
    Performance results may vary significantly across different systems due to:
    - CPU architecture and clock speeds
    - Memory configuration and speed
    - Operating system scheduling
    - System load and background processes
    - Thermal conditions

    We strongly recommend running the benchmarks on your specific system for the most accurate performance assessment.

- **Single-threaded tests**: Executed using 1 thread with `talib.EMA`.
- **Multi-threaded tests**: Conducted with `kand.ema`:
  - Windows i7-13700: 2, 4, and 6 threads.
  - Mac Mini M4: 2 and 4 threads.
- **Dataset sizes**: 50K, 100K, 250K, 500K, 1M, 2.5M, 5M, 10M data points.
- **EMA period**: 30.
- **Runs per test**: 1000 iterations to calculate average execution time.
- **Tools**: Python scripts leveraging `talib.EMA` (single-threaded) and `kand.ema` (multi-threaded).

---

## Results

### Windows i7-13700 Mobile

=== "Single-threaded"
    ![Windows Single-threaded](assets/batch_ema_performance_win_i713700.png)
    *Figure 1: EMA computation performance on Windows with 1 thread using `talib`.*

=== "2 Threads"
    ![Windows 2 Threads](assets/batch_ema_performance_mt_2_win_i713700.png)
    *Figure 2: Performance with 2 threads using `kand`.*

=== "4 Threads"
    ![Windows 4 Threads](assets/batch_ema_performance_mt_4_win_i713700.png)
    *Figure 3: Performance with 4 threads using `kand`.*

=== "6 Threads"
    ![Windows 6 Threads](assets/batch_ema_performance_mt_6_win_i713700.png)
    *Figure 4: Performance with 6 threads using `kand`.*

### Mac Mini M4

=== "Single-threaded"
    ![Mac Single-threaded](assets/batch_ema_performance_mac_m4.png)
    *Figure 5: EMA computation performance on Mac Mini with 1 thread using `talib`.*

=== "2 Threads"
    ![Mac 2 Threads](assets/batch_ema_performance_mt_2_mac_m4.png)
    *Figure 6: Performance with 2 threads using `kand`.*

=== "4 Threads"
    ![Mac 4 Threads](assets/batch_ema_performance_mt_4_mac_m4.png)
    *Figure 7: Performance with 4 threads using `kand`.*

---

## Analysis

The results reveal compelling insights into performance trends:

- **Multi-threading Advantage with `kand`**: Unlike `talib`, which is bottlenecked by single-threaded execution, `kand` harnesses multiple threads to drastically reduce EMA computation times. This advantage becomes increasingly evident with larger datasets (e.g., 5M and 10M points).

- **Scalability**:

  - On the Windows i7-13700, performance peaks at 6 threads, fully utilizing its 6 P-cores.
  - On the Mac Mini M4, efficiency maxes out at 4 threads, aligned with its 4 P-cores.

!!! tip "Why `kand` Outshines `talib`"
    The single-threaded nature of `talib` limits its ability to exploit modern multi-core CPUs. In contrast, `kand`’s multi-threaded design scales seamlessly with core count, delivering superior performance on datasets of any size.

!!! success "Key Takeaway"
    By embracing multi-threading, `kand` unlocks the full potential of modern processors, leaving `talib`’s single-threaded approach in the dust—especially for high-performance financial computations.

!!! note "Key Takeaway"
    📌 Thread counts are capped by the number of performance cores (P-cores). The i7-13700 supports up to 6 threads with its 6 P-cores, while the M4 is limited to 4 threads due to its 4 P-cores.

---

## Conclusion

Multi-threading capabilities in `kand` deliver exceptional performance gains across various technical analysis computations, consistently outperforming the single-threaded limitations of traditional libraries like `talib`. Our benchmarks on the Windows i7-13700 (6 P-cores) and Mac Mini M4 (4 P-cores) demonstrate impressive scalability, with the i7-13700 achieving superior throughput at higher thread counts. For applications dealing with large-scale financial data processing, `kand`'s sophisticated multi-core utilization architecture provides a significant competitive advantage. This foundation sets the stage for future optimizations across different hardware configurations and computational scenarios, making `kand` an ideal choice for high-performance financial analysis systems.


================================================
FILE: kand/Cargo.toml
================================================
[package]
name = "kand"
version = "0.2.2"
edition = "2024"
authors = ["CtrlX <gitctrlx@gmail.com>"]
readme = "../README.md"
description = "Kand: A Modern, High-Performance Technical Analysis Library."
license = "Apache-2.0 OR MIT"
repository = "https://github.com/rust-ta/kand"
documentation = "https://docs.rs/kand"
keywords = ["technical-analysis", "finance", "rust", "talib", "indicators"]
categories = ["finance", "algorithms", "data-structures", "science", "mathematics"]

[dependencies]
num_enum = { workspace = true }
thiserror = { workspace = true }

[dev-dependencies]
approx = { workspace = true }
criterion = { workspace = true }
csv = { workspace = true }
ndarray = { workspace = true }
rand = { workspace = true }
rayon = { workspace = true }

[[bench]]
name = "bench_main"
harness = false

[features]
default = ["f64", "i64", "check"]     # Default: extended precision with basic checks
f32 = []                              # 32-bit floating point
f64 = []                              # 64-bit floating point
i32 = []                              # 32-bit integer
i64 = []                              # 64-bit integer
check = []                            # Basic validation checks
check-nan = []                        # Check for NaN values in input data
allow-nan = []                        # Allow NaN values in output data


================================================
FILE: kand/benches/bench_main.rs
================================================
use criterion::criterion_main;

mod benchmarks;
mod helper;

criterion_main! {
    // OHLCV benchmarks
    benchmarks::ohlcv::ad_bench::ohlcv,
    benchmarks::ohlcv::adosc_bench::ohlcv,
    benchmarks::ohlcv::adr_bench::ohlcv,
    benchmarks::ohlcv::adx_bench::ohlcv,
    benchmarks::ohlcv::adxr_bench::ohlcv,
    benchmarks::ohlcv::aroon_bench::ohlcv,
    benchmarks::ohlcv::aroonosc_bench::ohlcv,
    benchmarks::ohlcv::atr_bench::ohlcv,
    benchmarks::ohlcv::bbands_bench::ohlcv,
    benchmarks::ohlcv::bop_bench::ohlcv,
    benchmarks::ohlcv::cci_bench::ohlcv,
    benchmarks::ohlcv::cdl_doji_bench::ohlcv,
    benchmarks::ohlcv::cdl_dragonfly_doji_bench::ohlcv,
    benchmarks::ohlcv::cdl_gravestone_doji_bench::ohlcv,
    benchmarks::ohlcv::cdl_hammer_bench::ohlcv,
    benchmarks::ohlcv::cdl_inverted_hammer_bench::ohlcv,
    benchmarks::ohlcv::cdl_long_shadow_bench::ohlcv,
    benchmarks::ohlcv::cdl_marubozu_bench::ohlcv,
    benchmarks::ohlcv::dema_bench::ohlcv,
    benchmarks::ohlcv::dx_bench::ohlcv,
    benchmarks::ohlcv::ecl_bench::ohlcv,
    benchmarks::ohlcv::ema_bench::ohlcv,
    benchmarks::ohlcv::macd_bench::ohlcv,
    benchmarks::ohlcv::medprice_bench::ohlcv,
    benchmarks::ohlcv::mfi_bench::ohlcv,
    benchmarks::ohlcv::midpoint_bench::ohlcv,
    benchmarks::ohlcv::midprice_bench::ohlcv,
    benchmarks::ohlcv::minus_di_bench::ohlcv,
    benchmarks::ohlcv::minus_dm_bench::ohlcv,
    benchmarks::ohlcv::mom_bench::ohlcv,
    benchmarks::ohlcv::natr_bench::ohlcv,
    benchmarks::ohlcv::obv_bench::ohlcv,
    benchmarks::ohlcv::plus_di_bench::ohlcv,
    benchmarks::ohlcv::plus_dm_bench::ohlcv,
    benchmarks::ohlcv::rma_bench::ohlcv,
    benchmarks::ohlcv::roc_bench::ohlcv,
    benchmarks::ohlcv::rocp_bench::ohlcv,
    benchmarks::ohlcv::rocr_bench::ohlcv,
    benchmarks::ohlcv::rocr100_bench::ohlcv,
    benchmarks::ohlcv::rsi_bench::ohlcv,
    benchmarks::ohlcv::sar_bench::ohlcv,
    benchmarks::ohlcv::sma_bench::ohlcv,
    benchmarks::ohlcv::stoch_bench::ohlcv,
    benchmarks::ohlcv::supertrend_bench::ohlcv,
    benchmarks::ohlcv::t3_bench::ohlcv,
    benchmarks::ohlcv::tema_bench::ohlcv,
    benchmarks::ohlcv::trix_bench::ohlcv,
    benchmarks::ohlcv::trange_bench::ohlcv,
    benchmarks::ohlcv::trima_bench::ohlcv,
    benchmarks::ohlcv::trix_bench::ohlcv,
    benchmarks::ohlcv::typprice_bench::ohlcv,
    benchmarks::ohlcv::vegas_bench::ohlcv,
    benchmarks::ohlcv::wclprice_bench::ohlcv,
    benchmarks::ohlcv::willr_bench::ohlcv,
    benchmarks::ohlcv::wma_bench::ohlcv,
    benchmarks::ohlcv::vwap_bench::ohlcv,

    // Stats benchmarks
    benchmarks::stats::max_bench::stats,
    benchmarks::stats::min_bench::stats,
    benchmarks::stats::stddev_bench::stats,
    benchmarks::stats::sum_bench::stats,
    benchmarks::stats::var_bench::stats,

    // Helper benchmarks
    // benchmarks::helper::helper,
}


================================================
FILE: kand/benches/benchmarks/helper.rs
================================================


================================================
FILE: kand/benches/benchmarks/mod.rs
================================================
pub mod ohlcv;
pub mod stats;

// pub mod helper;


================================================
FILE: kand/benches/benchmarks/ohlcv/ad_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::ad::ad;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_ad(c: &mut Criterion) {
    let mut group = c.benchmark_group("AD");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];

    for size in sizes {
        let high = generate_test_data(size);
        let low = generate_test_data(size);
        let close = generate_test_data(size);
        let volume = generate_test_data(size);
        let mut output = vec![0.0; size];

        group.bench_with_input(BenchmarkId::new("size", size), &size, |b, _| {
            b.iter(|| {
                // Use black_box on the result to prevent LLVM from optimizing away the computation
                let _ = ad(
                    black_box(&high),
                    black_box(&low),
                    black_box(&close),
                    black_box(&volume),
                    black_box(&mut output),
                );
            });
        });
    }

    group.finish();
}

criterion_group!(ohlcv, bench_ad);


================================================
FILE: kand/benches/benchmarks/ohlcv/adosc_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::adosc::adosc;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_adosc(c: &mut Criterion) {
    let mut group = c.benchmark_group("adosc");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let fast_periods = [3, 5, 10];
    let slow_periods = [10, 20, 30];

    for size in sizes {
        let high = generate_test_data(size);
        let low = generate_test_data(size);
        let close = generate_test_data(size);
        let volume = generate_test_data(size);
        let mut output_adosc = vec![0.0; size];
        let mut output_ad = vec![0.0; size];
        let mut output_fast_ema = vec![0.0; size];
        let mut output_slow_ema = vec![0.0; size];

        for (fast_period, slow_period) in fast_periods.iter().zip(slow_periods.iter()) {
            group.bench_with_input(
                BenchmarkId::new(
                    format!("size_{size}_fast_{fast_period}_slow_{slow_period}"),
                    format!("{fast_period}-{slow_period}"),
                ),
                &(fast_period, slow_period),
                |b, &(fast_period, slow_period)| {
                    b.iter(|| {
                        let _ = adosc(
                            black_box(&high),
                            black_box(&low),
                            black_box(&close),
                            black_box(&volume),
                            black_box(*fast_period),
                            black_box(*slow_period),
                            black_box(&mut output_adosc),
                            black_box(&mut output_ad),
                            black_box(&mut output_fast_ema),
                            black_box(&mut output_slow_ema),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_adosc);


================================================
FILE: kand/benches/benchmarks/ohlcv/adr_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::adr::adr;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_adr(c: &mut Criterion) {
    let mut group = c.benchmark_group("adr");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = adr(
                            black_box(&input_high),
                            black_box(&input_low),
                            black_box(period),
                            black_box(&mut output),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_adr);


================================================
FILE: kand/benches/benchmarks/ohlcv/adx_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::adx::adx;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_adx(c: &mut Criterion) {
    let mut group = c.benchmark_group("adx");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output_adx = vec![0.0; size];
        let mut output_smoothed_plus_dm = vec![0.0; size];
        let mut output_smoothed_minus_dm = vec![0.0; size];
        let mut output_smoothed_tr = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = adx(
                            black_box(&input_high),
                            black_box(&input_low),
                            black_box(&input_close),
                            black_box(period),
                            black_box(&mut output_adx),
                            black_box(&mut output_smoothed_plus_dm),
                            black_box(&mut output_smoothed_minus_dm),
                            black_box(&mut output_smoothed_tr),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_adx);


================================================
FILE: kand/benches/benchmarks/ohlcv/adxr_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::adxr::adxr;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_adxr(c: &mut Criterion) {
    let mut group = c.benchmark_group("adxr");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output_adxr = vec![0.0; size];
        let mut output_adx = vec![0.0; size];
        let mut output_smoothed_plus_dm = vec![0.0; size];
        let mut output_smoothed_minus_dm = vec![0.0; size];
        let mut output_smoothed_tr = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = adxr(
                            black_box(&input_high),
                            black_box(&input_low),
                            black_box(&input_close),
                            black_box(period),
                            black_box(&mut output_adxr),
                            black_box(&mut output_adx),
                            black_box(&mut output_smoothed_plus_dm),
                            black_box(&mut output_smoothed_minus_dm),
                            black_box(&mut output_smoothed_tr),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_adxr);


================================================
FILE: kand/benches/benchmarks/ohlcv/aroon_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ta::ohlcv::aroon::aroon;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_aroon(c: &mut Criterion) {
    let mut group = c.benchmark_group("aroon");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let mut output_aroon_up = vec![0.0; size];
        let mut output_aroon_down = vec![0.0; size];
        let mut output_prev_high = vec![0.0; size];
        let mut output_prev_low = vec![0.0; size];
        let mut output_days_since_high = vec![0; size];
        let mut output_days_since_low = vec![0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = aroon(
                            black_box(&input_high),
                            black_box(&input_low),
                            black_box(period),
                            black_box(&mut output_aroon_up),
                            black_box(&mut output_aroon_down),
                            black_box(&mut output_prev_high),
                            black_box(&mut output_prev_low),
                            black_box(&mut output_days_since_high),
                            black_box(&mut output_days_since_low),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_aroon);


================================================
FILE: kand/benches/benchmarks/ohlcv/aroonosc_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::aroonosc::aroonosc;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_aroonosc(c: &mut Criterion) {
    let mut group = c.benchmark_group("aroonosc");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let mut output_aroonosc = vec![0.0; size];
        let mut output_prev_high = vec![0.0; size];
        let mut output_prev_low = vec![0.0; size];
        let mut output_days_since_high = vec![0; size];
        let mut output_days_since_low = vec![0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = aroonosc(
                            black_box(&input_high),
                            black_box(&input_low),
                            black_box(period),
                            black_box(&mut output_aroonosc),
                            black_box(&mut output_prev_high),
                            black_box(&mut output_prev_low),
                            black_box(&mut output_days_since_high),
                            black_box(&mut output_days_since_low),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_aroonosc);


================================================
FILE: kand/benches/benchmarks/ohlcv/atr_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::atr::atr;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_atr(c: &mut Criterion) {
    let mut group = c.benchmark_group("atr");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let high = generate_test_data(size);
        let low = generate_test_data(size);
        let close = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = atr(
                            black_box(&high),
                            black_box(&low),
                            black_box(&close),
                            black_box(period),
                            black_box(&mut output),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_atr);


================================================
FILE: kand/benches/benchmarks/ohlcv/bbands_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::bbands::bbands;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_bbands(c: &mut Criterion) {
    let mut group = c.benchmark_group("bbands");

    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_price = generate_test_data(size);
        let mut output_upper = vec![0.0; size];
        let mut output_middle = vec![0.0; size];
        let mut output_lower = vec![0.0; size];
        let mut output_sma = vec![0.0; size];
        let mut output_var = vec![0.0; size];
        let mut output_sum = vec![0.0; size];
        let mut output_sum_sq = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = bbands(
                            black_box(&input_price),
                            black_box(period),
                            black_box(2.0),
                            black_box(2.0),
                            black_box(&mut output_upper),
                            black_box(&mut output_middle),
                            black_box(&mut output_lower),
                            black_box(&mut output_sma),
                            black_box(&mut output_var),
                            black_box(&mut output_sum),
                            black_box(&mut output_sum_sq),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_bbands);


================================================
FILE: kand/benches/benchmarks/ohlcv/bop_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::bop::bop;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_bop(c: &mut Criterion) {
    let mut group = c.benchmark_group("bop");

    let sizes = vec![100_000, 1_000_000, 10_000_000];

    for size in sizes {
        let input_open = generate_test_data(size);
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output_bop = vec![0.0; size];

        group.bench_with_input(BenchmarkId::new("size", size), &size, |b, &_size| {
            b.iter(|| {
                let _ = bop(
                    black_box(&input_open),
                    black_box(&input_high),
                    black_box(&input_low),
                    black_box(&input_close),
                    black_box(&mut output_bop),
                );
            });
        });
    }

    group.finish();
}

criterion_group!(ohlcv, bench_bop);


================================================
FILE: kand/benches/benchmarks/ohlcv/cci_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::cci::cci;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_cci(c: &mut Criterion) {
    let mut group = c.benchmark_group("cci");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output_cci = vec![0.0; size];
        let mut output_tp = vec![0.0; size];
        let mut output_sma_tp = vec![0.0; size];
        let mut output_mean_dev = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = cci(
                            black_box(&input_high),
                            black_box(&input_low),
                            black_box(&input_close),
                            black_box(period),
                            black_box(&mut output_cci),
                            black_box(&mut output_tp),
                            black_box(&mut output_sma_tp),
                            black_box(&mut output_mean_dev),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_cci);


================================================
FILE: kand/benches/benchmarks/ohlcv/cdl_doji_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::cdl_doji::cdl_doji;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_cdl_doji(c: &mut Criterion) {
    let mut group = c.benchmark_group("cdl_doji");

    let sizes = vec![100_000, 1_000_000, 10_000_000];

    for size in sizes {
        let input_open = generate_test_data(size);
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output_signals = vec![0; size];

        group.bench_with_input(BenchmarkId::new("size", size), &size, |b, &_size| {
            b.iter(|| {
                let _ = cdl_doji(
                    black_box(&input_open),
                    black_box(&input_high),
                    black_box(&input_low),
                    black_box(&input_close),
                    black_box(0.1),
                    black_box(0.1),
                    black_box(&mut output_signals),
                );
            });
        });
    }

    group.finish();
}

criterion_group!(ohlcv, bench_cdl_doji);


================================================
FILE: kand/benches/benchmarks/ohlcv/cdl_dragonfly_doji_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::cdl_dragonfly_doji::cdl_dragonfly_doji;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_cdl_dragonfly_doji(c: &mut Criterion) {
    let mut group = c.benchmark_group("cdl_dragonfly_doji");

    let sizes = vec![100_000, 1_000_000, 10_000_000];

    for size in sizes {
        let input_open = generate_test_data(size);
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output_signals = vec![0; size];

        group.bench_with_input(BenchmarkId::new("size", size), &size, |b, &_size| {
            b.iter(|| {
                let _ = cdl_dragonfly_doji(
                    black_box(&input_open),
                    black_box(&input_high),
                    black_box(&input_low),
                    black_box(&input_close),
                    black_box(0.1),
                    black_box(&mut output_signals),
                );
            });
        });
    }

    group.finish();
}

criterion_group!(ohlcv, bench_cdl_dragonfly_doji);


================================================
FILE: kand/benches/benchmarks/ohlcv/cdl_gravestone_doji_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::cdl_gravestone_doji::cdl_gravestone_doji;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_cdl_gravestone_doji(c: &mut Criterion) {
    let mut group = c.benchmark_group("cdl_gravestone_doji");

    let sizes = vec![100_000, 1_000_000, 10_000_000];

    for size in sizes {
        let input_open = generate_test_data(size);
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output_signals = vec![0; size];

        group.bench_with_input(BenchmarkId::new("size", size), &size, |b, &_size| {
            b.iter(|| {
                let _ = cdl_gravestone_doji(
                    black_box(&input_open),
                    black_box(&input_high),
                    black_box(&input_low),
                    black_box(&input_close),
                    black_box(0.1),
                    black_box(&mut output_signals),
                );
            });
        });
    }

    group.finish();
}

criterion_group!(ohlcv, bench_cdl_gravestone_doji);


================================================
FILE: kand/benches/benchmarks/ohlcv/cdl_hammer_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::cdl_hammer::cdl_hammer;
use std::hint::black_box;

use crate::helper::generate_test_data;
#[allow(dead_code)]
fn bench_cdl_hammer(c: &mut Criterion) {
    let mut group = c.benchmark_group("cdl_hammer");

    let sizes = vec![100_000, 1_000_000, 10_000_000];

    for size in sizes {
        let input_open = generate_test_data(size);
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output_signals = vec![0; size];
        let mut output_body_avg = vec![0.0; size];

        group.bench_with_input(BenchmarkId::new("size", size), &size, |b, &_size| {
            b.iter(|| {
                let _ = cdl_hammer(
                    black_box(&input_open),
                    black_box(&input_high),
                    black_box(&input_low),
                    black_box(&input_close),
                    black_box(5),
                    black_box(0.1),
                    black_box(&mut output_signals),
                    black_box(&mut output_body_avg),
                );
            });
        });
    }

    group.finish();
}

criterion_group!(ohlcv, bench_cdl_hammer);


================================================
FILE: kand/benches/benchmarks/ohlcv/cdl_inverted_hammer_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::cdl_inverted_hammer::cdl_inverted_hammer;
use std::hint::black_box;

use crate::helper::generate_test_data;
#[allow(dead_code)]
fn bench_cdl_inverted_hammer(c: &mut Criterion) {
    let mut group = c.benchmark_group("cdl_inverted_hammer");

    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_open = generate_test_data(size);
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output_signals = vec![0; size];
        let mut output_body_avg = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = cdl_inverted_hammer(
                            black_box(&input_open),
                            black_box(&input_high),
                            black_box(&input_low),
                            black_box(&input_close),
                            black_box(period),
                            black_box(0.1),
                            black_box(&mut output_signals),
                            black_box(&mut output_body_avg),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_cdl_inverted_hammer);


================================================
FILE: kand/benches/benchmarks/ohlcv/cdl_long_shadow_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::cdl_long_shadow::cdl_long_shadow;
use std::hint::black_box;

use crate::helper::generate_test_data;
#[allow(dead_code)]
fn bench_cdl_long_shadow(c: &mut Criterion) {
    let mut group = c.benchmark_group("cdl_long_shadow");

    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_open = generate_test_data(size);
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output_signals = vec![0; size];
        let mut output_body_avg = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = cdl_long_shadow(
                            black_box(&input_open),
                            black_box(&input_high),
                            black_box(&input_low),
                            black_box(&input_close),
                            black_box(period),
                            black_box(0.5),
                            black_box(&mut output_signals),
                            black_box(&mut output_body_avg),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_cdl_long_shadow);


================================================
FILE: kand/benches/benchmarks/ohlcv/cdl_marubozu_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::cdl_marubozu::cdl_marubozu;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_cdl_marubozu(c: &mut Criterion) {
    let mut group = c.benchmark_group("cdl_marubozu");

    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_open = generate_test_data(size);
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output_signals = vec![0; size];
        let mut output_body_avg = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = cdl_marubozu(
                            black_box(&input_open),
                            black_box(&input_high),
                            black_box(&input_low),
                            black_box(&input_close),
                            black_box(period),
                            black_box(0.1),
                            black_box(&mut output_signals),
                            black_box(&mut output_body_avg),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_cdl_marubozu);


================================================
FILE: kand/benches/benchmarks/ohlcv/dema_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::dema::dema;
use std::hint::black_box;

use crate::helper::generate_test_data;
#[allow(dead_code)]
fn bench_dema(c: &mut Criterion) {
    let mut group = c.benchmark_group("dema");

    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output_dema = vec![0.0; size];
        let mut output_ema1 = vec![0.0; size];
        let mut output_ema2 = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = dema(
                            black_box(&input),
                            black_box(period),
                            black_box(&mut output_dema),
                            black_box(&mut output_ema1),
                            black_box(&mut output_ema2),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_dema);


================================================
FILE: kand/benches/benchmarks/ohlcv/dx_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::dx::dx;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_dx(c: &mut Criterion) {
    let mut group = c.benchmark_group("dx");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output_dx = vec![0.0; size];
        let mut output_smoothed_plus_dm = vec![0.0; size];
        let mut output_smoothed_minus_dm = vec![0.0; size];
        let mut output_smoothed_tr = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = dx(
                            black_box(&input_high),
                            black_box(&input_low),
                            black_box(&input_close),
                            black_box(period),
                            black_box(&mut output_dx),
                            black_box(&mut output_smoothed_plus_dm),
                            black_box(&mut output_smoothed_minus_dm),
                            black_box(&mut output_smoothed_tr),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_dx);


================================================
FILE: kand/benches/benchmarks/ohlcv/ecl_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::ecl::ecl;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
#[allow(clippy::similar_names)]
fn bench_ecl(c: &mut Criterion) {
    let mut group = c.benchmark_group("ecl");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output_h5 = vec![0.0; size];
        let mut output_h4 = vec![0.0; size];
        let mut output_h3 = vec![0.0; size];
        let mut output_h2 = vec![0.0; size];
        let mut output_h1 = vec![0.0; size];
        let mut output_l1 = vec![0.0; size];
        let mut output_l2 = vec![0.0; size];
        let mut output_l3 = vec![0.0; size];
        let mut output_l4 = vec![0.0; size];
        let mut output_l5 = vec![0.0; size];

        group.bench_with_input(BenchmarkId::new("size", size), &size, |b, &_size| {
            b.iter(|| {
                let _ = ecl(
                    black_box(&input_high),
                    black_box(&input_low),
                    black_box(&input_close),
                    black_box(&mut output_h5),
                    black_box(&mut output_h4),
                    black_box(&mut output_h3),
                    black_box(&mut output_h2),
                    black_box(&mut output_h1),
                    black_box(&mut output_l1),
                    black_box(&mut output_l2),
                    black_box(&mut output_l3),
                    black_box(&mut output_l4),
                    black_box(&mut output_l5),
                );
            });
        });
    }

    group.finish();
}

criterion_group!(ohlcv, bench_ecl);


================================================
FILE: kand/benches/benchmarks/ohlcv/ema_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::ema::ema;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_ema(c: &mut Criterion) {
    let mut group = c.benchmark_group("ema");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = ema(
                            black_box(&input),
                            black_box(period),
                            black_box(None),
                            black_box(&mut output),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_ema);


================================================
FILE: kand/benches/benchmarks/ohlcv/macd_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::macd::macd;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_macd(c: &mut Criterion) {
    let mut group = c.benchmark_group("macd");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let fast_periods = [12, 26, 9]; // Standard MACD periods
    let slow_periods = vec![26, 52, 18];
    let signal_periods = vec![9, 18, 6];

    for size in sizes {
        let input = generate_test_data(size);
        let mut macd_line = vec![0.0; size];
        let mut signal_line = vec![0.0; size];
        let mut histogram = vec![0.0; size];
        let mut fast_ema = vec![0.0; size];
        let mut slow_ema = vec![0.0; size];

        for ((fast_period, slow_period), signal_period) in
            fast_periods.iter().zip(&slow_periods).zip(&signal_periods)
        {
            group.bench_with_input(
                BenchmarkId::new(
                    format!(
                        "size_{size}_fast_{fast_period}_slow_{slow_period}_signal_{signal_period}"
                    ),
                    format!("{fast_period}-{slow_period}-{signal_period}"),
                ),
                &(*fast_period, *slow_period, *signal_period),
                |b, &(fast_period, slow_period, signal_period)| {
                    b.iter(|| {
                        let _ = macd(
                            black_box(&input),
                            black_box(fast_period),
                            black_box(slow_period),
                            black_box(signal_period),
                            black_box(&mut macd_line),
                            black_box(&mut signal_line),
                            black_box(&mut histogram),
                            black_box(&mut fast_ema),
                            black_box(&mut slow_ema),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_macd);


================================================
FILE: kand/benches/benchmarks/ohlcv/medprice_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::medprice::medprice;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_medprice(c: &mut Criterion) {
    let mut group = c.benchmark_group("medprice");

    let sizes = vec![100_000, 1_000_000, 10_000_000];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let mut output_medprice = vec![0.0; size];

        group.bench_with_input(BenchmarkId::new("size", size), &size, |b, &_size| {
            b.iter(|| {
                let _ = medprice(
                    black_box(&input_high),
                    black_box(&input_low),
                    black_box(&mut output_medprice),
                );
            });
        });
    }

    group.finish();
}

criterion_group!(ohlcv, bench_medprice);


================================================
FILE: kand/benches/benchmarks/ohlcv/mfi_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::mfi::mfi;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_mfi(c: &mut Criterion) {
    let mut group = c.benchmark_group("mfi");

    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let input_volume = generate_test_data(size);
        let mut output_mfi = vec![0.0; size];
        let mut output_typ_prices = vec![0.0; size];
        let mut output_money_flows = vec![0.0; size];
        let mut output_pos_flows = vec![0.0; size];
        let mut output_neg_flows = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = mfi(
                            black_box(&input_high),
                            black_box(&input_low),
                            black_box(&input_close),
                            black_box(&input_volume),
                            black_box(period),
                            black_box(&mut output_mfi),
                            black_box(&mut output_typ_prices),
                            black_box(&mut output_money_flows),
                            black_box(&mut output_pos_flows),
                            black_box(&mut output_neg_flows),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_mfi);


================================================
FILE: kand/benches/benchmarks/ohlcv/midpoint_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::midpoint::midpoint;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_midpoint(c: &mut Criterion) {
    let mut group = c.benchmark_group("midpoint");

    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_price = generate_test_data(size);
        let mut output_midpoint = vec![0.0; size];
        let mut output_highest = vec![0.0; size];
        let mut output_lowest = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = midpoint(
                            black_box(&input_price),
                            black_box(period),
                            black_box(&mut output_midpoint),
                            black_box(&mut output_highest),
                            black_box(&mut output_lowest),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_midpoint);


================================================
FILE: kand/benches/benchmarks/ohlcv/midprice_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::midprice::midprice;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_midprice(c: &mut Criterion) {
    let mut group = c.benchmark_group("midprice");

    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let mut output_midprice = vec![0.0; size];
        let mut output_highest_high = vec![0.0; size];
        let mut output_lowest_low = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = midprice(
                            black_box(&input_high),
                            black_box(&input_low),
                            black_box(period),
                            black_box(&mut output_midprice),
                            black_box(&mut output_highest_high),
                            black_box(&mut output_lowest_low),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_midprice);


================================================
FILE: kand/benches/benchmarks/ohlcv/minus_di_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::minus_di::minus_di;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_minus_di(c: &mut Criterion) {
    let mut group = c.benchmark_group("minus_di");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let high = generate_test_data(size);
        let low = generate_test_data(size);
        let close = generate_test_data(size);
        let mut output_minus_di = vec![0.0; size];
        let mut output_smoothed_minus_dm = vec![0.0; size];
        let mut output_smoothed_tr = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = minus_di(
                            black_box(&high),
                            black_box(&low),
                            black_box(&close),
                            black_box(period),
                            black_box(&mut output_minus_di),
                            black_box(&mut output_smoothed_minus_dm),
                            black_box(&mut output_smoothed_tr),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_minus_di);


================================================
FILE: kand/benches/benchmarks/ohlcv/minus_dm_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::minus_dm::minus_dm;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_minus_dm(c: &mut Criterion) {
    let mut group = c.benchmark_group("minus_dm");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = minus_dm(
                            black_box(&input_high),
                            black_box(&input_low),
                            black_box(period),
                            black_box(&mut output),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_minus_dm);


================================================
FILE: kand/benches/benchmarks/ohlcv/mod.rs
================================================
pub mod ad_bench;
pub mod adosc_bench;
pub mod adr_bench;
pub mod adx_bench;
pub mod adxr_bench;
pub mod aroon_bench;
pub mod aroonosc_bench;
pub mod atr_bench;
pub mod bbands_bench;
pub mod bop_bench;
pub mod cci_bench;
pub mod cdl_doji_bench;
pub mod cdl_dragonfly_doji_bench;
pub mod cdl_gravestone_doji_bench;
pub mod cdl_hammer_bench;
pub mod cdl_inverted_hammer_bench;
pub mod cdl_long_shadow_bench;
pub mod cdl_marubozu_bench;
pub mod dema_bench;
pub mod dx_bench;
pub mod ecl_bench;
pub mod ema_bench;
pub mod macd_bench;
pub mod medprice_bench;
pub mod mfi_bench;
pub mod midpoint_bench;
pub mod midprice_bench;
pub mod minus_di_bench;
pub mod minus_dm_bench;
pub mod mom_bench;
pub mod natr_bench;
pub mod obv_bench;
pub mod plus_di_bench;
pub mod plus_dm_bench;
pub mod rma_bench;
pub mod roc_bench;
pub mod rocp_bench;
pub mod rocr100_bench;
pub mod rocr_bench;
pub mod rsi_bench;
pub mod sar_bench;
pub mod sma_bench;
pub mod stoch_bench;
pub mod supertrend_bench;
pub mod t3_bench;
pub mod tema_bench;
pub mod trange_bench;
pub mod trima_bench;
pub mod trix_bench;
pub mod typprice_bench;
pub mod vegas_bench;
pub mod vwap_bench;
pub mod wclprice_bench;
pub mod willr_bench;
pub mod wma_bench;


================================================
FILE: kand/benches/benchmarks/ohlcv/mom_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::mom::mom;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_mom(c: &mut Criterion) {
    let mut group = c.benchmark_group("mom");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = mom(black_box(&input), black_box(period), black_box(&mut output));
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_mom);


================================================
FILE: kand/benches/benchmarks/ohlcv/natr_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::natr::natr;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_natr(c: &mut Criterion) {
    let mut group = c.benchmark_group("natr");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let high = generate_test_data(size);
        let low = generate_test_data(size);
        let close = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = natr(
                            black_box(&high),
                            black_box(&low),
                            black_box(&close),
                            black_box(period),
                            black_box(&mut output),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_natr);


================================================
FILE: kand/benches/benchmarks/ohlcv/obv_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::obv::obv;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_obv(c: &mut Criterion) {
    let mut group = c.benchmark_group("obv");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];

    for size in sizes {
        let close = generate_test_data(size);
        let volume = generate_test_data(size);
        let mut output = vec![0.0; size];

        group.bench_with_input(BenchmarkId::new("size", size), &size, |b, &_size| {
            b.iter(|| {
                let _ = obv(
                    black_box(&close),
                    black_box(&volume),
                    black_box(&mut output),
                );
            });
        });
    }

    group.finish();
}

criterion_group!(ohlcv, bench_obv);


================================================
FILE: kand/benches/benchmarks/ohlcv/plus_di_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::plus_di::plus_di;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_plus_di(c: &mut Criterion) {
    let mut group = c.benchmark_group("plus_di");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let high = generate_test_data(size);
        let low = generate_test_data(size);
        let close = generate_test_data(size);
        let mut output_plus_di = vec![0.0; size];
        let mut output_smoothed_plus_dm = vec![0.0; size];
        let mut output_smoothed_tr = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = plus_di(
                            black_box(&high),
                            black_box(&low),
                            black_box(&close),
                            black_box(period),
                            black_box(&mut output_plus_di),
                            black_box(&mut output_smoothed_plus_dm),
                            black_box(&mut output_smoothed_tr),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_plus_di);


================================================
FILE: kand/benches/benchmarks/ohlcv/plus_dm_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::plus_dm::plus_dm;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_plus_dm(c: &mut Criterion) {
    let mut group = c.benchmark_group("plus_dm");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = plus_dm(
                            black_box(&input_high),
                            black_box(&input_low),
                            black_box(period),
                            black_box(&mut output),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_plus_dm);


================================================
FILE: kand/benches/benchmarks/ohlcv/rma_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::rma::rma;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_rma(c: &mut Criterion) {
    let mut group = c.benchmark_group("rma");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = rma(black_box(&input), black_box(period), black_box(&mut output));
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_rma);


================================================
FILE: kand/benches/benchmarks/ohlcv/roc_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::roc::roc;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_roc(c: &mut Criterion) {
    let mut group = c.benchmark_group("roc");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = roc(black_box(&input), black_box(period), black_box(&mut output));
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_roc);


================================================
FILE: kand/benches/benchmarks/ohlcv/rocp_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::rocp::rocp;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_rocp(c: &mut Criterion) {
    let mut group = c.benchmark_group("rocp");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = rocp(black_box(&input), black_box(period), black_box(&mut output));
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_rocp);


================================================
FILE: kand/benches/benchmarks/ohlcv/rocr100_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::rocr100::rocr100;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_rocr100(c: &mut Criterion) {
    let mut group = c.benchmark_group("rocr100");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ =
                            rocr100(black_box(&input), black_box(period), black_box(&mut output));
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_rocr100);


================================================
FILE: kand/benches/benchmarks/ohlcv/rocr_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::rocr::rocr;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_rocr(c: &mut Criterion) {
    let mut group = c.benchmark_group("rocr");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = rocr(black_box(&input), black_box(period), black_box(&mut output));
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_rocr);


================================================
FILE: kand/benches/benchmarks/ohlcv/rsi_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::rsi::rsi;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_rsi(c: &mut Criterion) {
    let mut group = c.benchmark_group("rsi");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];
        let mut output_avg_gain = vec![0.0; size];
        let mut output_avg_loss = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = rsi(
                            black_box(&input),
                            black_box(period),
                            black_box(&mut output),
                            black_box(&mut output_avg_gain),
                            black_box(&mut output_avg_loss),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_rsi);


================================================
FILE: kand/benches/benchmarks/ohlcv/sar_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::sar::sar;
use std::hint::black_box;

use crate::helper::generate_test_data;
#[allow(dead_code)]
fn bench_sar(c: &mut Criterion) {
    let mut group = c.benchmark_group("sar");

    let sizes = vec![100_000, 1_000_000, 10_000_000];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let mut output_sar = vec![0.0; size];
        let mut output_is_long = vec![false; size];
        let mut output_af = vec![0.0; size];
        let mut output_ep = vec![0.0; size];

        group.bench_with_input(BenchmarkId::new("size", size), &size, |b, &_size| {
            b.iter(|| {
                let _ = sar(
                    black_box(&input_high),
                    black_box(&input_low),
                    black_box(0.02),
                    black_box(0.2),
                    black_box(&mut output_sar),
                    black_box(&mut output_is_long),
                    black_box(&mut output_af),
                    black_box(&mut output_ep),
                );
            });
        });
    }

    group.finish();
}

criterion_group!(ohlcv, bench_sar);


================================================
FILE: kand/benches/benchmarks/ohlcv/sma_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::sma::sma;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_sma(c: &mut Criterion) {
    let mut group = c.benchmark_group("SMA");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = sma(black_box(&input), black_box(period), black_box(&mut output));
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_sma);


================================================
FILE: kand/benches/benchmarks/ohlcv/stoch_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::stoch::stoch;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_stoch(c: &mut Criterion) {
    let mut group = c.benchmark_group("stoch");

    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let k_periods = [5, 14, 30];
    let k_slow_periods = vec![3, 5, 9];
    let d_periods = vec![3, 5, 9];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output_fast_k = vec![0.0; size];
        let mut output_k = vec![0.0; size];
        let mut output_d = vec![0.0; size];

        for (&k_period, &k_slow_period, &d_period) in k_periods
            .iter()
            .zip(&k_slow_periods)
            .zip(&d_periods)
            .map(|((a, b), c)| (a, b, c))
        {
            group.bench_with_input(
                BenchmarkId::new(
                    format!("size_{size}_k{k_period}_ks{k_slow_period}_d{d_period}"),
                    format!("{k_period}-{k_slow_period}-{d_period}"),
                ),
                &(k_period, k_slow_period, d_period),
                |b, &(k_period, k_slow_period, d_period)| {
                    b.iter(|| {
                        let _ = stoch(
                            black_box(&input_high),
                            black_box(&input_low),
                            black_box(&input_close),
                            black_box(k_period),
                            black_box(k_slow_period),
                            black_box(d_period),
                            black_box(&mut output_fast_k),
                            black_box(&mut output_k),
                            black_box(&mut output_d),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_stoch);


================================================
FILE: kand/benches/benchmarks/ohlcv/supertrend_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::supertrend::supertrend;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_supertrend(c: &mut Criterion) {
    let mut group = c.benchmark_group("supertrend");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];
    let multiplier = 3.0;

    for size in sizes {
        let input = generate_test_data(size);
        let mut trend = vec![0; size];
        let mut supertrend_output = vec![0.0; size];
        let mut atr = vec![0.0; size];
        let mut upper = vec![0.0; size];
        let mut lower = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = supertrend(
                            black_box(&input), // high
                            black_box(&input), // low
                            black_box(&input), // close
                            black_box(period),
                            black_box(multiplier),
                            black_box(&mut trend),
                            black_box(&mut supertrend_output),
                            black_box(&mut atr),
                            black_box(&mut upper),
                            black_box(&mut lower),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_supertrend);


================================================
FILE: kand/benches/benchmarks/ohlcv/t3_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::t3::t3;
use std::hint::black_box;

use crate::helper::generate_test_data;
#[allow(dead_code)]
fn bench_t3(c: &mut Criterion) {
    let mut group = c.benchmark_group("t3");

    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];
    let vfactors = vec![0.5, 0.7, 0.9];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];
        let mut ema1 = vec![0.0; size];
        let mut ema2 = vec![0.0; size];
        let mut ema3 = vec![0.0; size];
        let mut ema4 = vec![0.0; size];
        let mut ema5 = vec![0.0; size];
        let mut ema6 = vec![0.0; size];

        for period in &periods {
            for vfactor in &vfactors {
                group.bench_with_input(
                    BenchmarkId::new(format!("size_{size}_vfactor_{vfactor:.1}"), period),
                    &(*period, *vfactor),
                    |b, &(period, vfactor)| {
                        b.iter(|| {
                            let _ = t3(
                                black_box(&input),
                                black_box(period),
                                black_box(vfactor),
                                black_box(&mut output),
                                black_box(&mut ema1),
                                black_box(&mut ema2),
                                black_box(&mut ema3),
                                black_box(&mut ema4),
                                black_box(&mut ema5),
                                black_box(&mut ema6),
                            );
                        });
                    },
                );
            }
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_t3);


================================================
FILE: kand/benches/benchmarks/ohlcv/tema_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::tema::tema;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_tema(c: &mut Criterion) {
    let mut group = c.benchmark_group("tema");
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];
        let mut output_ema1 = vec![0.0; size];
        let mut output_ema2 = vec![0.0; size];
        let mut output_ema3 = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = tema(
                            black_box(&input),
                            black_box(period),
                            black_box(&mut output),
                            black_box(&mut output_ema1),
                            black_box(&mut output_ema2),
                            black_box(&mut output_ema3),
                        );
                    });
                },
            );
        }
    }
    group.finish();
}

criterion_group!(ohlcv, bench_tema);


================================================
FILE: kand/benches/benchmarks/ohlcv/trange_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::trange::trange;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_trange(c: &mut Criterion) {
    let mut group = c.benchmark_group("trange");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];

    for size in sizes {
        let high = generate_test_data(size);
        let low = generate_test_data(size);
        let close = generate_test_data(size);
        let mut output = vec![0.0; size];

        group.bench_with_input(BenchmarkId::new("size", size), &size, |b, &_size| {
            b.iter(|| {
                let _ = trange(
                    black_box(&high),
                    black_box(&low),
                    black_box(&close),
                    black_box(&mut output),
                );
            });
        });
    }

    group.finish();
}

criterion_group!(ohlcv, bench_trange);


================================================
FILE: kand/benches/benchmarks/ohlcv/trima_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::trima::trima;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_trima(c: &mut Criterion) {
    let mut group = c.benchmark_group("trima");

    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output_sma1 = vec![0.0; size];
        let mut output_sma2 = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = trima(
                            black_box(&input),
                            black_box(period),
                            black_box(&mut output_sma1),
                            black_box(&mut output_sma2),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_trima);


================================================
FILE: kand/benches/benchmarks/ohlcv/trix_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::trix::trix;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_trix(c: &mut Criterion) {
    let mut group = c.benchmark_group("trix");

    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];
        let mut ema1_output = vec![0.0; size];
        let mut ema2_output = vec![0.0; size];
        let mut ema3_output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = trix(
                            black_box(&input),
                            black_box(period),
                            black_box(&mut output),
                            black_box(&mut ema1_output),
                            black_box(&mut ema2_output),
                            black_box(&mut ema3_output),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_trix);


================================================
FILE: kand/benches/benchmarks/ohlcv/typprice_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::typprice::typprice;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_typprice(c: &mut Criterion) {
    let mut group = c.benchmark_group("typprice");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output = vec![0.0; size];

        group.bench_with_input(BenchmarkId::new("size", size), &size, |b, &_size| {
            b.iter(|| {
                let _ = typprice(
                    black_box(&input_high),
                    black_box(&input_low),
                    black_box(&input_close),
                    black_box(&mut output),
                );
            });
        });
    }

    group.finish();
}

criterion_group!(ohlcv, bench_typprice);


================================================
FILE: kand/benches/benchmarks/ohlcv/vegas_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::vegas::vegas;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_vegas(c: &mut Criterion) {
    let mut group = c.benchmark_group("vegas");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output_channel_upper = vec![0.0; size];
        let mut output_channel_lower = vec![0.0; size];
        let mut output_boundary_upper = vec![0.0; size];
        let mut output_boundary_lower = vec![0.0; size];

        group.bench_with_input(BenchmarkId::new("size", size), &size, |b, &_size| {
            b.iter(|| {
                let _ = vegas(
                    black_box(&input),
                    black_box(&mut output_channel_upper),
                    black_box(&mut output_channel_lower),
                    black_box(&mut output_boundary_upper),
                    black_box(&mut output_boundary_lower),
                );
            });
        });
    }

    group.finish();
}

criterion_group!(ohlcv, bench_vegas);


================================================
FILE: kand/benches/benchmarks/ohlcv/vwap_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::vwap::vwap;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_vwap(c: &mut Criterion) {
    let mut group = c.benchmark_group("vwap");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];

    for size in sizes {
        let high = generate_test_data(size);
        let low = generate_test_data(size);
        let close = generate_test_data(size);
        let volume = generate_test_data(size);
        let mut output_vwap = vec![0.0; size];
        let mut output_cum_pv = vec![0.0; size];
        let mut output_cum_vol = vec![0.0; size];

        group.bench_with_input(BenchmarkId::new("size", size), &size, |b, &_size| {
            b.iter(|| {
                let _ = vwap(
                    black_box(&high),
                    black_box(&low),
                    black_box(&close),
                    black_box(&volume),
                    black_box(&mut output_vwap),
                    black_box(&mut output_cum_pv),
                    black_box(&mut output_cum_vol),
                );
            });
        });
    }

    group.finish();
}

criterion_group!(ohlcv, bench_vwap);


================================================
FILE: kand/benches/benchmarks/ohlcv/wclprice_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::wclprice::wclprice;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_wclprice(c: &mut Criterion) {
    let mut group = c.benchmark_group("wclprice");

    let sizes = vec![100_000, 1_000_000, 10_000_000];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output = vec![0.0; size];

        group.bench_with_input(BenchmarkId::new("size", size), &size, |b, &_size| {
            b.iter(|| {
                let _ = wclprice(
                    black_box(&input_high),
                    black_box(&input_low),
                    black_box(&input_close),
                    black_box(&mut output),
                );
            });
        });
    }

    group.finish();
}

criterion_group!(ohlcv, bench_wclprice);


================================================
FILE: kand/benches/benchmarks/ohlcv/willr_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::willr::willr;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_willr(c: &mut Criterion) {
    let mut group = c.benchmark_group("willr");

    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input_high = generate_test_data(size);
        let input_low = generate_test_data(size);
        let input_close = generate_test_data(size);
        let mut output = vec![0.0; size];
        let mut output_highest_high = vec![0.0; size];
        let mut output_lowest_low = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = willr(
                            black_box(&input_high),
                            black_box(&input_low),
                            black_box(&input_close),
                            black_box(period),
                            black_box(&mut output),
                            black_box(&mut output_highest_high),
                            black_box(&mut output_lowest_low),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_willr);


================================================
FILE: kand/benches/benchmarks/ohlcv/wma_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::ohlcv::wma::wma;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_wma(c: &mut Criterion) {
    let mut group = c.benchmark_group("wma");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = wma(black_box(&input), black_box(period), black_box(&mut output));
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_wma);


================================================
FILE: kand/benches/benchmarks/other/mod.rs
================================================


================================================
FILE: kand/benches/benchmarks/stats/beta_bench.rs
================================================
use criterion::{black_box, criterion_group, BenchmarkId, Criterion};
use kand::ohlcv::beta::beta;

use crate::helpers::generate_test_data;

#[allow(dead_code)]
fn bench_beta(c: &mut Criterion) {
    let mut group = c.benchmark_group("beta");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{}", size), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = beta(black_box(&input), black_box(period), black_box(&mut output));
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_beta);


================================================
FILE: kand/benches/benchmarks/stats/correl_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use std::hint::black_box;
use kand::stats::correl::correl;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_correl(c: &mut Criterion) {
    let mut group = c.benchmark_group("correl");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{}", size), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = correl(black_box(&input), black_box(period), black_box(&mut output));
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(ohlcv, bench_correl);


================================================
FILE: kand/benches/benchmarks/stats/max_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::stats::max::max;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_max(c: &mut Criterion) {
    let mut group = c.benchmark_group("max");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = max(black_box(&input), black_box(period), black_box(&mut output));
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(stats, bench_max);


================================================
FILE: kand/benches/benchmarks/stats/min_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::stats::min::min;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_min(c: &mut Criterion) {
    let mut group = c.benchmark_group("min");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = min(black_box(&input), black_box(period), black_box(&mut output));
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(stats, bench_min);


================================================
FILE: kand/benches/benchmarks/stats/mod.rs
================================================
pub mod max_bench;
pub mod min_bench;
pub mod stddev_bench;
pub mod sum_bench;
pub mod var_bench;


================================================
FILE: kand/benches/benchmarks/stats/stddev_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::stats::stddev::stddev;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_stddev(c: &mut Criterion) {
    let mut group = c.benchmark_group("stddev");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];
        let mut output_sum = vec![0.0; size];
        let mut output_sum_sq = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = stddev(
                            black_box(&input),
                            black_box(period),
                            black_box(&mut output),
                            black_box(&mut output_sum),
                            black_box(&mut output_sum_sq),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(stats, bench_stddev);


================================================
FILE: kand/benches/benchmarks/stats/sum_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::stats::sum::sum;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_sum(c: &mut Criterion) {
    let mut group = c.benchmark_group("sum");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = sum(black_box(&input), black_box(period), black_box(&mut output));
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(stats, bench_sum);


================================================
FILE: kand/benches/benchmarks/stats/var_bench.rs
================================================
use criterion::{BenchmarkId, Criterion, criterion_group};
use kand::stats::var::var;
use std::hint::black_box;

use crate::helper::generate_test_data;

#[allow(dead_code)]
fn bench_var(c: &mut Criterion) {
    let mut group = c.benchmark_group("var");

    // Test different data sizes
    let sizes = vec![100_000, 1_000_000, 10_000_000];
    let periods = vec![5, 50, 200];

    for size in sizes {
        let input = generate_test_data(size);
        let mut output = vec![0.0; size];
        let mut output_sum = vec![0.0; size];
        let mut output_sum_sq = vec![0.0; size];

        for period in &periods {
            group.bench_with_input(
                BenchmarkId::new(format!("size_{size}"), period),
                period,
                |b, &period| {
                    b.iter(|| {
                        let _ = var(
                            black_box(&input),
                            black_box(period),
                            black_box(&mut output),
                            black_box(&mut output_sum),
                            black_box(&mut output_sum_sq),
                        );
                    });
                },
            );
        }
    }

    group.finish();
}

criterion_group!(stats, bench_var);


================================================
FILE: kand/benches/helper.rs
================================================
use kand::TAFloat;
use rand::Rng;

/// Generate a vector of floating point values simulating price movements
///
/// # Panics
///
/// This function will panic if:
/// - Type conversion from `usize` to `TAFloat` fails
#[must_use]
#[allow(clippy::expect_used)]
pub fn generate_test_data(size: usize) -> Vec<TAFloat> {
    let mut rng = rand::rng();
    let mut data = Vec::with_capacity(size);

    // These constants are used frequently
    let price_init: TAFloat = 100.0;
    let increment: TAFloat = 0.001;
    let half: TAFloat = 0.5;
    let two: TAFloat = 2.0;

    let mut price = price_init;

    for i in 0..size {
        // Simulate small random price movements
        let random_factor: TAFloat = rng.random_range(0.0..1.0);
        price = (random_factor - half).mul_add(two, price);
        let idx = i as TAFloat;
        data.push(idx.mul_add(increment, price));
    }
    data
}


================================================
FILE: kand/src/error.rs
================================================
#[derive(thiserror::Error, Debug)]
pub enum KandError {
    #[error("Invalid parameter value provided to the function")]
    InvalidParameter,

    #[error("Insufficient data points for the requested calculation")]
    InsufficientData,

    #[error("Input data contains NaN (Not a Number) values")]
    NaNDetected,

    #[error("Input arrays have mismatched lengths")]
    LengthMismatch,

    #[error("Input data is invalid (out of range or empty)")]
    InvalidData,

    #[error("File operation error occurred")]
    FileError,

    #[error("Failed to convert between numeric types")]
    ConversionError,

    #[error("Invalid input: {0}")]
    InvalidInput(String),

    #[error("Calculation error: {0}")]
    CalculationError(String),
}

pub type Result<T> = std::result::Result<T, KandError>;


================================================
FILE: kand/src/helper.rs
================================================
use crate::{KandError, TAFloat};

/// Find the number of bars back to the lowest value in a lookback period
///
/// # Arguments
/// * `array` - Array of values to analyze
/// * `start_idx` - Starting index for analysis
/// * `lookback` - Number of bars to look back
///
/// # Visual Example
/// ```text
/// Given array: [5, 2, 4, 1, 3], start_idx = 4, lookback = 3
///
/// Lookback window:        [4, 1, 3]
///                          ^  ^  ^
/// Indices:                 2  3  4
/// Values:                  4  1  3
/// i values:                2  1  0
///                             ↑
///                      Lowest value (1)
///
/// Returns: 1 (number of bars back from start_idx to lowest value)
/// ```
///
/// # Returns
/// * `Result<usize, KandError>` - Number of bars back to lowest value if successful, error otherwise
///
/// # Errors
/// * Returns `KandError::InvalidParameter` if:
///   - The input array is empty
///   - `start_idx` is out of bounds
///   - `lookback` is 0
///   - `start_idx` is less than `lookback - 1`
pub fn lowest_bars(
    array: &[TAFloat],
    start_idx: usize,
    lookback: usize,
) -> Result<usize, KandError> {
    if array.is_empty() || start_idx >= array.len() || lookback == 0 || start_idx < lookback - 1 {
        return Err(KandError::InvalidParameter);
    }

    let mut lowest = array[start_idx];
    let mut lowest_idx = 0;

    for i in 1..lookback {
        if array[start_idx - i] < lowest {
            lowest = array[start_idx - i];
            lowest_idx = i;
        }
    }
    Ok(lowest_idx)
}

/// Find the number of bars back to the highest value in a lookback period
///
/// # Arguments
/// * `array` - Array of values to analyze
/// * `start_idx` - Starting index for analysis
/// * `lookback` - Number of bars to look back
///
/// # Visual Example
/// ```text
/// Given array: [1, 4, 2, 5, 3], start_idx = 4, lookback = 3
///
/// Lookback window:        [2, 5, 3]
///                          ^  ^  ^
/// Indices:                 2  3  4
/// Values:                  2  5  3
/// i values:                2  1  0
///                             ↑
///                      Highest value (5)
///
/// Returns: 1 (number of bars back from start_idx to highest value)
/// ```
///
/// # Returns
/// * `Result<usize, KandError>` - Number of bars back to highest value if successful, error otherwise
///
/// # Errors
/// * Returns `KandError::InvalidParameter` if:
///   - The input array is empty
///   - `start_idx` is out of bounds
///   - `lookback` is 0
///   - `start_idx` is less than `lookback - 1`
pub fn highest_bars(
    array: &[TAFloat],
    start_idx: usize,
    lookback: usize,
) -> Result<usize, KandError> {
    if array.is_empty() || start_idx >= array.len() || lookback == 0 || start_idx < lookback - 1 {
        return Err(KandError::InvalidParameter);
    }

    let mut highest = array[start_idx];
    let mut highest_idx = 0;

    for i in 1..lookback {
        if array[start_idx - i] > highest {
            highest = array[start_idx - i];
            highest_idx = i;
        }
    }
    Ok(highest_idx)
}

/// Calculate k factor from period value (k = 2 / (period + 1))
///
/// # Arguments
/// * `period` - The period value to convert
///
/// # Returns
/// * `Result<TAFloat, KandError>` - The calculated k factor if successful, error otherwise
///
/// # Errors
/// * Returns `KandError::InvalidParameter` if `period` is 0
pub fn period_to_k(period: usize) -> Result<TAFloat, KandError> {
    if period == 0 {
        return Err(KandError::InvalidParameter);
    }
    Ok(2.0 / ((period + 1) as TAFloat))
}

/// Calculate candlestick real body length
///
/// # Arguments
/// * `open` - Opening price
/// * `close` - Closing price
///
/// # Returns
/// * `TAFloat` - Absolute difference between open and close prices
#[must_use]
pub fn real_body_length(open: TAFloat, close: TAFloat) -> TAFloat {
    (close - open).abs()
}

/// Calculate candlestick upper shadow length
///
/// # Arguments
/// * `high` - High price
/// * `open` - Opening price
/// * `close` - Closing price
///
/// # Returns
/// * `TAFloat` - Length of upper shadow
#[must_use]
pub fn upper_shadow_length(high: TAFloat, open: TAFloat, close: TAFloat) -> TAFloat {
    high - if close >= open { close } else { open }
}

/// Calculate candlestick lower shadow length
///
/// # Arguments
/// * `low` - Low price
/// * `open` - Opening price
/// * `close` - Closing price
///
/// # Returns
/// * `TAFloat` - Length of lower shadow
#[must_use]
pub fn lower_shadow_length(low: TAFloat, open: TAFloat, close: TAFloat) -> TAFloat {
    if close >= open {
        open - low
    } else {
        close - low
    }
}

/// Check if there is a gap up between real bodies of two candlesticks
///
/// # Arguments
/// * `open2` - Opening price of second candle
/// * `close2` - Closing price of second candle
/// * `open1` - Opening price of first candle
/// * `close1` - Closing price of first candle
///
/// # Returns
/// * `bool` - True if gap up exists, false otherwise
#[must_use]
pub fn has_real_body_gap_up(
    open2: TAFloat,
    close2: TAFloat,
    open1: TAFloat,
    close1: TAFloat,
) -> bool {
    open2.min(close2) > open1.max(close1)
}

/// Check if there is a gap down between real bodies of two candlesticks
///
/// # Arguments
/// * `open2` - Opening price of second candle
/// * `close2` - Closing price of second candle
/// * `open1` - Opening price of first candle
/// * `close1` - Closing price of first candle
///
/// # Returns
/// * `bool` - True if gap down exists, false otherwise
#[must_use]
pub fn has_real_body_gap_down(
    open2: TAFloat,
    close2: TAFloat,
    open1: TAFloat,
    close1: TAFloat,
) -> bool {
    open2.max(close2) < open1.min(close1)
}


================================================
FILE: kand/src/lib.rs
================================================
//! # Kand
//!
//! A high-performance technical analysis library for Rust, inspired by TA-Lib.
//!
//! ## Overview
//!
//! Kand provides a comprehensive suite of technical analysis tools for financial market data analysis.
//! Built with Rust's safety and performance in mind, it offers a modern alternative to traditional
//! technical analysis libraries.
//!
//! ## Features
//!
//! - **High Performance**: Written in pure Rust with zero dependencies on external C libraries
//! - **Type Safety**: Leverages Rust's type system to prevent common errors at compile time
//! - **Flexible Types**: Supports both standard (32-bit) and extended (64-bit) precision modes
//! - **Comprehensive Indicators**: Implements popular technical indicators including:
//!   - Moving Averages (SMA, EMA, WMA)
//!   - Momentum Indicators (RSI, MACD)
//!   - Volume Indicators (OBV)
//!   - And more...
//!
//! ## Quick Start
//!
//! ```rust
//! use kand::ohlcv::sma;
//!
//! // Input price data
//! let prices = vec![2.0, 4.0, 6.0, 8.0, 10.0];
//! let period = 3;
//! let mut sma_values = vec![0.0; prices.len()];
//!
//! // Calculate SMA
//! sma::sma(&prices, period, &mut sma_values).unwrap();
//! // First (period-1) values will be NaN, then: [NaN, NaN, 4.0, 6.0, 8.0]
//!
//! // Calculate next SMA value incrementally
//! let prev_sma = 8.0; // Last SMA value
//! let new_price = 12.0; // New price to include
//! let old_price = 6.0; // Oldest price to remove
//!
//! let next_sma = sma::sma_inc(prev_sma, new_price, old_price, period).unwrap();
//! // next_sma = 10.0 ((8.0 + 10.0 + 12.0) / 3)
//! ```
//!
//! ## Feature Flags
//!
//! Kand can be configured through feature flags:
//!
//! ### Precision Modes
//! - `default = ["extended", "check"]`: 64-bit precision with basic validation checks
//! - `standard = ["f32", "i32"]`: Standard precision mode using 32-bit types
//! - `extended = ["f64", "i64"]`: Extended precision mode using 64-bit types
//!
//! ### Type Selection
//! - `f32`: Use 32-bit floating point numbers
//! - `f64`: Use 64-bit floating point numbers
//! - `i32`: Use 32-bit integers
//! - `i64`: Use 64-bit integers
//!
//! ### Validation
//! - `check`: Enable basic validation checks
//! - `check-nan = ["check"]`: Enable extended validation (includes basic checks)
//!
//! ## Safety and Error Handling
//!
//! All functions in Kand return a `Result` type, properly handling edge cases and
//! invalid inputs. Common error cases include:
//!
//! - `InvalidParameter`: Invalid input parameters (e.g., period < 2)
//! - `InvalidData`: Empty or invalid input data
//! - `LengthMismatch`: Input and output slice lengths don't match
//! - `InsufficientData`: Not enough data points for calculation
//! - `NaNDetected`: NaN values in input data (with `check-nan` feature)
//!
//! ## Performance Considerations
//!
//! The library is optimized for both speed and memory usage:
//!
//! - Incremental calculation support for real-time updates
//! - Configurable precision modes (standard/extended)
//! - In-place calculations to minimize memory allocations
//! - Optional validation checks that can be disabled for maximum performance
#![allow(clippy::similar_names, clippy::too_many_lines)]

pub mod ta;
pub use ta::*;

pub mod helper;

pub mod error;
pub use error::{KandError, Result};

/// Default floating-point precision type used across the library.
///
/// This type is determined by the enabled features:
/// - With feature "f64": Uses f64 (recommended for most cases)
/// - With feature "f32": Uses f32 (for memory-constrained environments)
/// - With no features enabled: Defaults to f64
///
/// The default configuration (feature "extended") provides f64 for:
/// - Higher precision calculations (15-17 decimal digits)
/// - Better handling of large price values
/// - More accurate technical indicator results
#[cfg(all(feature = "f32", not(feature = "f64")))]
pub type TAFloat = f32;

#[cfg(not(all(feature = "f32", not(feature = "f64"))))]
pub type TAFloat = f64; // Default to f64 when no features are enabled

/// Default integer type used for indicator outputs.
///
/// This type is determined by the enabled features:
/// - With feature "i64": Uses i64 (recommended for most cases)
/// - With feature "i32": Uses i32 (for memory-constrained environments)
/// - With no features enabled: Defaults to i32
///
/// The default configuration (feature "extended") provides i64 for:
/// - Larger value range (-2^63 to 2^63-1)
/// - Better precision in accumulation operations
/// - Future-proof for high-frequency data analysis
#[cfg(all(feature = "i32", not(feature = "i64")))]
pub type TAInt = i32;

#[cfg(not(all(feature = "i32", not(feature = "i64"))))]
pub type TAInt = i64; // Default to i64 when no features are enabled

/// Default type for indicator periods.
///
/// This is consistently `usize` across the library to represent time periods,
/// lookback windows, and other count-based parameters.
pub type TAPeriod = usize;

/// Global EPSILON value used for floating-point comparisons
/// to account for rounding errors in calculations.
///
/// This value is automatically set based on the floating-point type:
/// - f32: Uses f32::EPSILON (≈ 1.19e-7)
/// - f64: Uses f64::EPSILON (≈ 2.22e-16)
#[cfg(all(feature = "f32", not(feature = "f64")))]
pub const EPSILON: TAFloat = f32::EPSILON;

#[cfg(not(all(feature = "f32", not(feature = "f64"))))]
pub const EPSILON: TAFloat = f64::EPSILON;


================================================
FILE: kand/src/ta/mod.rs
================================================
pub mod ohlcv;
pub mod stats;

pub mod types;


================================================
FILE: kand/src/ta/ohlcv/ad.rs
================================================
use crate::{KandError, TAFloat, TAPeriod};

/// Returns the lookback period required for A/D calculation.
///
/// The A/D indicator requires no lookback period, as it can be calculated starting from the first data point.
///
/// # Errors
///
/// This function always returns `Ok(0)`.
///
/// # Examples
///
/// ```
/// use kand::ohlcv::ad;
/// let lookback = ad::lookback().unwrap();
/// assert_eq!(lookback, 0);
/// ```
#[must_use]
pub const fn lookback() -> Result<TAPeriod, KandError> {
    Ok(0)
}

/// Core calculation for Accumulation/Distribution (A/D) without error checking.
///
/// This is a high-performance version for advanced users, assuming valid inputs.
/// It computes the A/D by accumulating money flow volume.
///
/// # Parameters
///
/// - `input_high`: Slice of high prices.
/// - `input_low`: Slice of low prices.
/// - `input_close`: Slice of close prices.
/// - `input_volume`: Slice of volumes.
/// - `output_ad`: Mutable slice to store the A/D values.
/// - `lookback`: The lookback period (0 for A/D).
///
/// # Notes
///
/// - No error checking is performed; ensure inputs are valid.
/// - All values in `output_ad` are set since lookback is 0.
/// - Assumes all input slices have the same length.
pub fn ad_raw(
    input_high: &[TAFloat],
    input_low: &[TAFloat],
    input_close: &[TAFloat],
    input_volume: &[TAFloat],
    output_ad: &mut [TAFloat],
    lookback: TAPeriod,
) {
    let len = input_high.len();
    let mut ad = 0.0;
    for i in lookback..len {
        let high_low_diff = input_high[i] - input_low[i];
        let mfm = if high_low_diff == 0.0 {
            0.0
        } else {
            ((input_close[i] - input_low[i]) - (input_high[i] - input_close[i])) / high_low_diff
        };
        ad = mfm.mul_add(input_volume[i], ad);
        output_ad[i] = ad;
    }
}

/// Calculates the Accumulation/Distribution (A/D) indicator for the entire price series.
///
/// The A/D indicator measures the cumulative flow of money into and out of a security by analyzing
/// price and volume data. It starts from 0 and accumulates the money flow volume over time.
///
/// # Formula
///
/// ```text
/// Money Flow Multiplier (MFM) = ((Close - Low) - (High - Close)) / (High - Low)
/// Money Flow Volume (MFV) = MFM * Volume
/// A/D = Previous A/D + MFV
/// ```
///
/// # Calculation
///
/// 1. Compute the Money Flow Multiplier (MFM), ranging from -1 to +1:
///    - Positive values indicate buying pressure (close near high).
///    - Negative values indicate selling pressure (close near low).
/// 2. Multiply MFM by volume to get Money Flow Volume (MFV).
/// 3. Accumulate MFV to form the A/D line, starting from 0.
///
/// If High - Low is zero, MFM is set to 0 to avoid division by zero.
///
/// # Errors
///
/// - [`KandError::InvalidData`] if input arrays are empty (enabled by "check" feature).
/// - [`KandError::LengthMismatch`] if input arrays have different lengths (enabled by "check" feature).
/// - [`KandError::NaNDetected`] if any input contains NaN values (enabled by "check-nan" feature).
///
/// # Examples
///
/// ```
/// use kand::ohlcv::ad;
/// let input_high = vec![10.0, 12.0, 15.0];
/// let input_low = vec![8.0, 9.0, 11.0];
/// let input_close = vec![9.0, 11.0, 13.0];
/// let input_volume = vec![100.0, 150.0, 200.0];
/// let mut output_ad = vec![0.0; 3];
///
/// ad::ad(
///     &input_high,
///     &input_low,
///     &input_close,
///     &input_volume,
///     &mut output_ad,
/// )
/// .unwrap();
/// ```
pub fn ad(
    input_high: &[TAFloat],
    input_low: &[TAFloat],
    input_close: &[TAFloat],
    input_volume: &[TAFloat],
    output_ad: &mut [TAFloat],
) -> Result<(), KandError> {
    let len = input_high.len();
    let lookback = lookback()?;

    #[cfg(feature = "check")]
    {
        if len == 0 {
            return Err(KandError::InvalidData);
        }

        if len != input_low.len()
            || len != input_close.len()
            || len != input_volume.len()
            || len != output_ad.len()
        {
            return Err(KandError::LengthMismatch);
        }
    }

    #[cfg(feature = "check-nan")]
    {
        for i in lookback..len {
            if input_high[i].is_nan()
                || input_low[i].is_nan()
                || input_close[i].is_nan()
                || input_volume[i].is_nan()
            {
                return Err(KandError::NaNDetected);
            }
        }
    }

    ad_raw(
        input_high,
        input_low,
        input_close,
        input_volume,
        output_ad,
        lookback,
    );

    Ok(())
}

/// Core calculation for incremental A/D without error checking.
///
/// This is a high-performance version for advanced users, assuming valid inputs.
/// It computes the next A/D value using the previous A/D and new data.
///
/// # Formula
///
/// ```text
/// Money Flow Multiplier (MFM) = ((Close - Low) - (High - Close)) / (High - Low)
/// Money Flow Volume (MFV) = MFM * Volume
/// Latest A/D = Previous A/D + MFV
/// ```
///
/// # Parameters
///
/// - `input_high`: High price.
/// - `input_low`: Low price.
/// - `input_close`: Close price.
/// - `input_volume`: Volume.
/// - `prev_ad`: The previous A/D value.
///
/// # Returns
///
/// The next A/D value as a `TAFloat`.
///
/// # Notes
///
/// - No error checking is performed; ensure inputs are valid.
/// - If High - Low is zero, MFM is set to 0.
pub fn ad_inc_raw(
    input_high: TAFloat,
    input_low: TAFloat,
    input_close: TAFloat,
    input_volume: TAFloat,
    prev_ad: TAFloat,
) -> TAFloat {
    let high_low_diff = input_high - input_low;
    let mfm = if high_low_diff == 0.0 {
        0.0
    } else {
        ((input_close - input_low) - (input_high - input_close)) / high_low_diff
    };
    mfm.mul_add(input_volume, prev_ad)
}

/// Calculates the latest A/D value incrementally using the previous A/D value.
///
/// This is an optimized version that computes only the latest A/D value, avoiding recalculation of the entire series.
///
/// # Formula
///
/// ```text
/// Money Flow Multiplier (MFM) = ((Close - Low) - (High - Close)) / (High - Low)
/// Money Flow Volume (MFV) = MFM * Volume
/// Latest A/D = Previous A/D + MFV
/// ```
///
/// If High - Low is zero, MFM is set to 0 to avoid division by zero.
///
/// # Errors
///
/// - [`KandError::NaNDetected`] if any input contains NaN values (enabled by "check-nan" feature).
///
/// # Examples
///
/// ```
/// use kand::ohlcv::ad;
/// let input_high = 15.0;
/// let input_low = 11.0;
/// let input_close = 13.0;
/// let input_volume = 200.0;
/// let prev_ad = 25.0;
///
/// let output_ad = ad::ad_inc(input_high, input_low, input_close, input_volume, prev_ad).unwrap();
/// ```
#[must_use]
pub fn ad_inc(
    input_high: TAFloat,
    input_low: TAFloat,
    input_close: TAFloat,
    input_volume: TAFloat,
    prev_ad: TAFloat,
) -> Result<TAFloat, KandError> {
    #[cfg(feature = "check-nan")]
    {
        if input_high.is_nan()
            || input_low.is_nan()
            || input_close.is_nan()
            || input_volume.is_nan()
            || prev_ad.is_nan()
        {
            return Err(KandError::NaNDetected);
        }
    }

    Ok(ad_inc_raw(
        input_high,
        input_low,
        input_close,
        input_volume,
        prev_ad,
    ))
}

#[cfg(test)]
mod tests {
    use approx::assert_relative_eq;

    use super::*;
    use crate::EPSILON;

    const INPUT_HIGH: [f64; 25] = [
        35266.0, 35247.5, 35235.7, 35190.8, 35182.0, 35258.0, 35262.9, 35281.5, 35256.0, 35210.0,
        35185.4, 35230.0, 35241.0, 35218.1, 35212.6, 35128.9, 35047.7, 35019.5, 35078.8, 35085.0,
        35034.1, 34984.4, 35010.8, 35047.1, 35091.4,
    ];

    const INPUT_LOW: [f64; 25] = [
        35216.1, 35206.5, 35180.0, 35130.7, 35153.6, 35174.7, 35202.6, 35203.5, 35175.0, 35166.0,
        35170.9, 35154.1, 35186.0, 35143.9, 35080.1, 35021.1, 34950.1, 34966.0, 35012.3, 35022.2,
        34931.6, 34911.0, 34952.5, 34977.9, 35039.0,
    ];

    const INPUT_CLOSE: [f64; 25] = [
        35216.1, 35221.4, 35190.7, 35170.0, 35181.5, 35254.6, 35202.8, 35251.9, 35197.6, 35184.7,
        35175.1, 35229.9, 35212.5, 35160.7, 35090.3, 35041.2, 34999.3, 35013.4, 35069.0, 35024.6,
        34939.5, 34952.6, 35000.0, 35041.8, 35080.0,
    ];

    const INPUT_VOLUME: [f64; 25] = [
        1055.365, 756.488, 682.152, 1197.747, 425.97, 859.638, 741.925, 888.477, 1043.333, 467.901,
        387.47, 566.099, 672.296, 834.915, 1854.024, 3670.795, 3761.198, 1605.442, 1726.574,
        934.713, 2199.061, 2349.823, 837.218, 1000.638, 1218.202,
    ];

    const EXPECTED_VALUES: [f64; 25] = [
        -1_055.365,
        -1_262.015_380_487_751_1,
        -1_682.083_847_274_164,
        -1_313.393_007_007_976_8,
        -902.421_950_669_947_9,
        -112.958_481_282_220_36,
        -849.961_922_409_807_9,
        -635.816_183_948_236_4,
        -1_096.943_608_639_632,
        -1_167.128_758_639_693_8,
        -1_330.133_379_329_504_6,
        -765.526_076_299_179_7,
        -789.973_203_571_907,
        -1_246.813_486_590_858_2,
        -2_815.387_753_760_547,
        -5_117.296_306_636_379,
        -5_086.466_814_832_707,
        -3_847.125_607_355_984_4,
        -2_629.436_575_777_188,
        -3_492.706_543_930_014,
        -5_352.790_336_125_074,
        -5_039.053_750_294_157,
        -4_512.022_865_217_038,
        -3_664.661_784_292_062_7,
        -2_976.517_143_070_741_4,
    ];

    /// Tests A/D calculation with `allow-nan` feature enabled.
    #[test]
    #[cfg(feature = "allow-nan")]
    fn test_ad_with_nan() {
        let mut output_ad = vec![f64::NAN; INPUT_HIGH.len()];
        ad(
            &INPUT_HIGH,
            &INPUT_LOW,
            &INPUT_CLOSE,
            &INPUT_VOLUME,
            &mut output_ad,
        )
        .unwrap();

        // Verify full series calculation
        for (i, &expected) in EXPECTED_VALUES.iter().enumerate() {
            assert_relative_eq!(output_ad[i], expected, epsilon = EPSILON);
        }

        // Verify incremental calculation matches full series
        let mut prev_ad = output_ad[0];
        for i in 1..INPUT_HIGH.len() {
            let result = ad_inc(
                INPUT_HIGH[i],
                INPUT_LOW[i],
                INPUT_CLOSE[i],
                INPUT_VOLUME[i],
                prev_ad,
            )
            .unwrap();
            if result.is_nan() {
                assert!(output_ad[i].is_nan());
            } else {
                assert_relative_eq!(result, output_ad[i], epsilon = EPSILON);
            }
            prev_ad = result;
        }
    }

    /// Tests A/D calculation without `allow-nan` feature.
    #[test]
    #[cfg(not(feature = "allow-nan"))]
    fn test_ad_without_nan() {
        let mut output_ad = vec![0.0; INPUT_HIGH.len()];
        ad(
            &INPUT_HIGH,
            &INPUT_LOW,
            &INPUT_CLOSE,
            &INPUT_VOLUME,
            &mut output_ad,
        )
        .unwrap();

        // Verify full series calculation
        for (i, &expected) in EXPECTED_VALUES.iter().enumerate() {
            assert_relative_eq!(output_ad[i], expected, epsilon = EPSILON);
        }

        // Verify incremental calculation matches full series
        let mut prev_ad = output_ad[0];
        for i in 1..INPUT_HIGH.len() {
            let result = ad_inc(
                INPUT_HIGH[i],
                INPUT_LOW[i],
                INPUT_CLOSE[i],
                INPUT_VOLUME[i],
                prev_ad,
            )
            .unwrap();
            assert_relative_eq!(result, output_ad[i], epsilon = EPSILON);
            prev_ad = result;
        }
    }
}


================================================
FILE: kand/src/ta/ohlcv/adosc.rs
================================================
use super::{ad, ema};
use crate::{KandError, TAFloat};

/// Returns the lookback period required for A/D Oscillator calculation.
///
/// The A/D Oscillator requires a lookback equal to the slow EMA period minus one.
///
/// # Errors
///
/// - [`KandError::InvalidParameter`] if fast or slow period is less than 2, or if fast period is not less than slow period (enabled by "check" feature).
///
/// # Examples
///
/// ```
/// use kand::ohlcv::adosc;
/// let lookback = adosc::lookback(3, 10).unwrap();
/// assert_eq!(lookback, 9);
/// ```
#[must_use]
pub const fn lookback(opt_fast_period: usize, opt_slow_period: usize) -> Result<usize, KandError> {
    #[cfg(feature = "check")]
    {
        if opt_fast_period < 2 || opt_slow_period < 2 || opt_fast_period >= opt_slow_period {
            return Err(KandError::InvalidParameter);
        }
    }

    ema::lookback(opt_slow_period)
}

/// Calculates the Accumulation/Distribution Oscillator (A/D Oscillator or ADOSC) for the entire price series.
///
/// The A/D Oscillator is the difference between fast and slow EMAs of the Accumulation/Distribution (A/D) line.
/// It helps identify trend strength and potential reversals by measuring momentum in money flow.
///
/// # Formula
///
/// ```text
/// Money Flow Multiplier (MFM) = ((Close - Low) - (High - Close
Download .txt
gitextract_86qxh_to/

├── .gitattributes
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── CI.yml
│       ├── publish-doc.yml
│       ├── publish-docker.yml
│       ├── publish-rust.yml
│       ├── release.yml
│       ├── rust.yml
│       └── stale.yml
├── .gitignore
├── .python-version
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Cargo.toml
├── Dockerfile
├── LICENSE-APACHE
├── LICENSE-MIT
├── Makefile
├── README.md
├── cliff.toml
├── clippy.toml
├── docs/
│   ├── about.md
│   ├── advance.md
│   ├── api.md
│   ├── install.md
│   └── performance.md
├── kand/
│   ├── Cargo.toml
│   ├── benches/
│   │   ├── bench_main.rs
│   │   ├── benchmarks/
│   │   │   ├── helper.rs
│   │   │   ├── mod.rs
│   │   │   ├── ohlcv/
│   │   │   │   ├── ad_bench.rs
│   │   │   │   ├── adosc_bench.rs
│   │   │   │   ├── adr_bench.rs
│   │   │   │   ├── adx_bench.rs
│   │   │   │   ├── adxr_bench.rs
│   │   │   │   ├── aroon_bench.rs
│   │   │   │   ├── aroonosc_bench.rs
│   │   │   │   ├── atr_bench.rs
│   │   │   │   ├── bbands_bench.rs
│   │   │   │   ├── bop_bench.rs
│   │   │   │   ├── cci_bench.rs
│   │   │   │   ├── cdl_doji_bench.rs
│   │   │   │   ├── cdl_dragonfly_doji_bench.rs
│   │   │   │   ├── cdl_gravestone_doji_bench.rs
│   │   │   │   ├── cdl_hammer_bench.rs
│   │   │   │   ├── cdl_inverted_hammer_bench.rs
│   │   │   │   ├── cdl_long_shadow_bench.rs
│   │   │   │   ├── cdl_marubozu_bench.rs
│   │   │   │   ├── dema_bench.rs
│   │   │   │   ├── dx_bench.rs
│   │   │   │   ├── ecl_bench.rs
│   │   │   │   ├── ema_bench.rs
│   │   │   │   ├── macd_bench.rs
│   │   │   │   ├── medprice_bench.rs
│   │   │   │   ├── mfi_bench.rs
│   │   │   │   ├── midpoint_bench.rs
│   │   │   │   ├── midprice_bench.rs
│   │   │   │   ├── minus_di_bench.rs
│   │   │   │   ├── minus_dm_bench.rs
│   │   │   │   ├── mod.rs
│   │   │   │   ├── mom_bench.rs
│   │   │   │   ├── natr_bench.rs
│   │   │   │   ├── obv_bench.rs
│   │   │   │   ├── plus_di_bench.rs
│   │   │   │   ├── plus_dm_bench.rs
│   │   │   │   ├── rma_bench.rs
│   │   │   │   ├── roc_bench.rs
│   │   │   │   ├── rocp_bench.rs
│   │   │   │   ├── rocr100_bench.rs
│   │   │   │   ├── rocr_bench.rs
│   │   │   │   ├── rsi_bench.rs
│   │   │   │   ├── sar_bench.rs
│   │   │   │   ├── sma_bench.rs
│   │   │   │   ├── stoch_bench.rs
│   │   │   │   ├── supertrend_bench.rs
│   │   │   │   ├── t3_bench.rs
│   │   │   │   ├── tema_bench.rs
│   │   │   │   ├── trange_bench.rs
│   │   │   │   ├── trima_bench.rs
│   │   │   │   ├── trix_bench.rs
│   │   │   │   ├── typprice_bench.rs
│   │   │   │   ├── vegas_bench.rs
│   │   │   │   ├── vwap_bench.rs
│   │   │   │   ├── wclprice_bench.rs
│   │   │   │   ├── willr_bench.rs
│   │   │   │   └── wma_bench.rs
│   │   │   ├── other/
│   │   │   │   └── mod.rs
│   │   │   └── stats/
│   │   │       ├── beta_bench.rs
│   │   │       ├── correl_bench.rs
│   │   │       ├── max_bench.rs
│   │   │       ├── min_bench.rs
│   │   │       ├── mod.rs
│   │   │       ├── stddev_bench.rs
│   │   │       ├── sum_bench.rs
│   │   │       └── var_bench.rs
│   │   └── helper.rs
│   └── src/
│       ├── error.rs
│       ├── helper.rs
│       ├── lib.rs
│       └── ta/
│           ├── mod.rs
│           ├── ohlcv/
│           │   ├── ad.rs
│           │   ├── adosc.rs
│           │   ├── adr.rs
│           │   ├── adx.rs
│           │   ├── adxr.rs
│           │   ├── aroon.rs
│           │   ├── aroonosc.rs
│           │   ├── atr.rs
│           │   ├── bbands.rs
│           │   ├── bop.rs
│           │   ├── cci.rs
│           │   ├── cdl_doji.rs
│           │   ├── cdl_dragonfly_doji.rs
│           │   ├── cdl_gravestone_doji.rs
│           │   ├── cdl_hammer.rs
│           │   ├── cdl_inverted_hammer.rs
│           │   ├── cdl_long_shadow.rs
│           │   ├── cdl_marubozu.rs
│           │   ├── dema.rs
│           │   ├── dx.rs
│           │   ├── ecl.rs
│           │   ├── ema.rs
│           │   ├── ha.rs
│           │   ├── macd.rs
│           │   ├── medprice.rs
│           │   ├── mfi.rs
│           │   ├── midpoint.rs
│           │   ├── midprice.rs
│           │   ├── minus_di.rs
│           │   ├── minus_dm.rs
│           │   ├── mod.rs
│           │   ├── mom.rs
│           │   ├── natr.rs
│           │   ├── obv.rs
│           │   ├── plus_di.rs
│           │   ├── plus_dm.rs
│           │   ├── rma.rs
│           │   ├── roc.rs
│           │   ├── rocp.rs
│           │   ├── rocr.rs
│           │   ├── rocr100.rs
│           │   ├── rsi.rs
│           │   ├── sar.rs
│           │   ├── sma.rs
│           │   ├── stoch.rs
│           │   ├── supertrend.rs
│           │   ├── t3.rs
│           │   ├── tema.rs
│           │   ├── trange.rs
│           │   ├── trima.rs
│           │   ├── trix.rs
│           │   ├── typprice.rs
│           │   ├── vegas.rs
│           │   ├── vwap.rs
│           │   ├── wclprice.rs
│           │   ├── willr.rs
│           │   └── wma.rs
│           ├── other/
│           │   └── mod.rs
│           ├── stats/
│           │   ├── alpha.rs
│           │   ├── beta.rs
│           │   ├── calmar.rs
│           │   ├── correl.rs
│           │   ├── drawdown.rs
│           │   ├── fv.rs
│           │   ├── kelly.rs
│           │   ├── max.rs
│           │   ├── min.rs
│           │   ├── mod.rs
│           │   ├── nper.rs
│           │   ├── ret.rs
│           │   ├── sharpe.rs
│           │   ├── sortino.rs
│           │   ├── stddev.rs
│           │   ├── sum.rs
│           │   ├── var.rs
│           │   └── winrate.rs
│           └── types.rs
├── kand-py/
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── python/
│   │   ├── benches/
│   │   │   ├── .gitkeep
│   │   │   ├── bench_ema.py
│   │   │   ├── bench_ema_incremental.py
│   │   │   ├── bench_ema_incremental_mt.py
│   │   │   ├── bench_ema_mt.py
│   │   │   └── ema.py
│   │   ├── examples/
│   │   │   ├── sma.py
│   │   │   └── sma_thread.py
│   │   └── kand/
│   │       ├── __init__.py
│   │       ├── _kand.pyi
│   │       └── py.typed
│   └── src/
│       ├── helper.rs
│       ├── lib.rs
│       └── ta/
│           ├── mod.rs
│           ├── ohlcv/
│           │   ├── ad.rs
│           │   ├── adosc.rs
│           │   ├── adr.rs
│           │   ├── adx.rs
│           │   ├── adxr.rs
│           │   ├── aroon.rs
│           │   ├── aroonosc.rs
│           │   ├── atr.rs
│           │   ├── bbands.rs
│           │   ├── bop.rs
│           │   ├── cci.rs
│           │   ├── cdl_doji.rs
│           │   ├── cdl_dragonfly_doji.rs
│           │   ├── cdl_gravestone_doji.rs
│           │   ├── cdl_hammer.rs
│           │   ├── cdl_inverted_hammer.rs
│           │   ├── cdl_long_shadow.rs
│           │   ├── cdl_marubozu.rs
│           │   ├── dema.rs
│           │   ├── dx.rs
│           │   ├── ecl.rs
│           │   ├── ema.rs
│           │   ├── macd.rs
│           │   ├── medprice.rs
│           │   ├── mfi.rs
│           │   ├── midpoint.rs
│           │   ├── midprice.rs
│           │   ├── minus_di.rs
│           │   ├── minus_dm.rs
│           │   ├── mod.rs
│           │   ├── mom.rs
│           │   ├── natr.rs
│           │   ├── obv.rs
│           │   ├── plus_di.rs
│           │   ├── plus_dm.rs
│           │   ├── rma.rs
│           │   ├── roc.rs
│           │   ├── rocp.rs
│           │   ├── rocr.rs
│           │   ├── rocr100.rs
│           │   ├── rsi.rs
│           │   ├── sar.rs
│           │   ├── sma.rs
│           │   ├── stoch.rs
│           │   ├── supertrend.rs
│           │   ├── t3.rs
│           │   ├── tema.rs
│           │   ├── trange.rs
│           │   ├── trima.rs
│           │   ├── trix.rs
│           │   ├── typprice.rs
│           │   ├── vegas.rs
│           │   ├── vwap.rs
│           │   ├── wclprice.rs
│           │   ├── willr.rs
│           │   └── wma.rs
│           ├── other/
│           │   └── mod.rs
│           └── stats/
│               ├── beta.rs
│               ├── correl.rs
│               ├── fv.rs
│               ├── max.rs
│               ├── min.rs
│               ├── mod.rs
│               ├── stddev.rs
│               ├── sum.rs
│               └── var.rs
├── kand-wasm/
│   ├── Cargo.toml
│   └── src/
│       ├── lib.rs
│       └── ta/
│           ├── mod.rs
│           ├── ohlcv/
│           │   ├── ad.rs
│           │   ├── adosc.rs
│           │   ├── adr.rs
│           │   ├── adx.rs
│           │   ├── adxr.rs
│           │   ├── apo.rs
│           │   ├── aroon.rs
│           │   ├── aroonosc.rs
│           │   ├── atr.rs
│           │   ├── bbands.rs
│           │   ├── bop.rs
│           │   ├── cci.rs
│           │   ├── cdl_doji.rs
│           │   ├── cdl_dragonfly_doji.rs
│           │   ├── cdl_gravestone_doji.rs
│           │   ├── cdl_hammer.rs
│           │   ├── cdl_inverted_hammer.rs
│           │   ├── cdl_long_shadow.rs
│           │   ├── cdl_marubozu.rs
│           │   ├── cmo.rs
│           │   ├── dema.rs
│           │   ├── dx.rs
│           │   ├── ecl.rs
│           │   ├── ema.rs
│           │   ├── ha.rs
│           │   ├── ht_dcperiod.rs
│           │   ├── ht_dcphase.rs
│           │   ├── ht_phasor.rs
│           │   ├── ht_sine.rs
│           │   ├── ht_trendline.rs
│           │   ├── ht_trendmode.rs
│           │   ├── kama.rs
│           │   ├── linearreg.rs
│           │   ├── linearreg_angle.rs
│           │   ├── linearreg_intercept.rs
│           │   ├── linearreg_slope.rs
│           │   ├── macd.rs
│           │   ├── macdext.rs
│           │   ├── mama.rs
│           │   ├── medprice.rs
│           │   ├── mfi.rs
│           │   ├── midpoint.rs
│           │   ├── midprice.rs
│           │   ├── minus_di.rs
│           │   ├── minus_dm.rs
│           │   ├── mod.rs
│           │   ├── mom.rs
│           │   ├── natr.rs
│           │   ├── obv.rs
│           │   ├── plus_di.rs
│           │   ├── plus_dm.rs
│           │   ├── ppo.rs
│           │   ├── renko.rs
│           │   ├── rma.rs
│           │   ├── roc.rs
│           │   ├── rocp.rs
│           │   ├── rocr.rs
│           │   ├── rocr100.rs
│           │   ├── rsi.rs
│           │   ├── sar.rs
│           │   ├── sarext.rs
│           │   ├── sma.rs
│           │   ├── stoch.rs
│           │   ├── stochf.rs
│           │   ├── stochrsi.rs
│           │   ├── supertrend.rs
│           │   ├── t3.rs
│           │   ├── tema.rs
│           │   ├── trange.rs
│           │   ├── trima.rs
│           │   ├── trix.rs
│           │   ├── tsf.rs
│           │   ├── typprice.rs
│           │   ├── ultosc.rs
│           │   ├── vegas.rs
│           │   ├── vwap.rs
│           │   ├── wclprice.rs
│           │   ├── willr.rs
│           │   └── wma.rs
│           ├── other/
│           │   └── mod.rs
│           ├── stats/
│           │   ├── alpha.rs
│           │   ├── beta.rs
│           │   ├── calmar.rs
│           │   ├── correl.rs
│           │   ├── drawdown.rs
│           │   ├── fv.rs
│           │   ├── kelly.rs
│           │   ├── max.rs
│           │   ├── min.rs
│           │   ├── mod.rs
│           │   ├── nper.rs
│           │   ├── ret.rs
│           │   ├── sharpe.rs
│           │   ├── sortino.rs
│           │   ├── stddev.rs
│           │   ├── sum.rs
│           │   ├── var.rs
│           │   └── winrate.rs
│           └── types.rs
├── mkdocs.yml
├── pyproject.toml
├── rust-toolchain.toml
└── scripts/
    └── gen_stub.py
Download .txt
SYMBOL INDEX (612 symbols across 199 files)

FILE: kand-py/python/benches/bench_ema.py
  function generate_test_data (line 15) | def generate_test_data(size):
  function test_batch_performance (line 19) | def test_batch_performance(data_sizes, period=3, runs=5):
  function plot_batch_results (line 41) | def plot_batch_results(data_sizes, talib_times, kand_times):
  function main (line 129) | def main():

FILE: kand-py/python/benches/bench_ema_mt.py
  function generate_test_data (line 17) | def generate_test_data(size):
  function run_ema (line 21) | def run_ema(data, period, runs_per_thread, func):
  function test_batch_performance (line 31) | def test_batch_performance(data_sizes, period=3, runs=5, num_threads=None):
  function plot_batch_results (line 67) | def plot_batch_results(data_sizes, talib_times, kand_times):
  function main (line 143) | def main():

FILE: kand-py/python/benches/ema.py
  function pure_python_ema (line 9) | def pure_python_ema(data: List[float], span: int) -> List[float]:
  function pandas_ema (line 25) | def pandas_ema(data: pd.Series, span: int) -> pd.Series:
  function plot_performance_comparison (line 37) | def plot_performance_comparison(results: Dict[str, float]) -> plt.Figure:
  function benchmark_ema (line 88) | def benchmark_ema(size: int = 10_000_000) -> Dict[str, float]:

FILE: kand-py/python/kand/_kand.pyi
  function ad (line 7) | def ad(high, low, close, volume):
  function ad_inc (line 38) | def ad_inc(high, low, close, volume, prev_ad):
  function adosc (line 70) | def adosc(high, low, close, volume, fast_period, slow_period):
  function adosc_inc (line 106) | def adosc_inc(high, low, close, volume, prev_ad, prev_fast_ema, prev_slo...
  function adx (line 145) | def adx(high, low, close, period):
  function adx_inc (line 178) | def adx_inc(high, low, prev_high, prev_low, prev_close, prev_adx, prev_s...
  function adxr (line 221) | def adxr(high, low, close, period):
  function adxr_inc (line 255) | def adxr_inc(high, low, prev_high, prev_low, prev_close, prev_adx, prev_...
  function aroon (line 301) | def aroon(high, low, period):
  function aroon_inc (line 334) | def aroon_inc(high, low, prev_high, prev_low, days_since_high, days_sinc...
  function aroonosc (line 373) | def aroonosc(high, low, period):
  function aroonosc_inc (line 405) | def aroonosc_inc(high, low, prev_high, prev_low, days_since_high, days_s...
  function atr (line 443) | def atr(high, low, close, period):
  function atr_inc (line 472) | def atr_inc(high, low, prev_close, prev_atr, period):
  function bbands (line 501) | def bbands(price, period, dev_up, dev_down):
  function bbands_inc (line 537) | def bbands_inc(price, prev_sma, prev_sum, prev_sum_sq, old_price, period...
  function bop (line 578) | def bop(open, high, low, close):
  function bop_inc (line 608) | def bop_inc(open, high, low, close):
  function cci (line 629) | def cci(high, low, close, period):
  function cci_inc (line 664) | def cci_inc(prev_sma_tp, new_high, new_low, new_close, old_high, old_low...
  function cdl_doji (line 701) | def cdl_doji(open, high, low, close, body_percent, shadow_equal_percent):
  function cdl_doji_inc (line 729) | def cdl_doji_inc(open, high, low, close, body_percent, shadow_equal_perc...
  function cdl_dragonfly_doji (line 753) | def cdl_dragonfly_doji(open, high, low, close, body_percent):
  function cdl_dragonfly_doji_inc (line 782) | def cdl_dragonfly_doji_inc(open, high, low, close, body_percent):
  function cdl_gravestone_doji (line 807) | def cdl_gravestone_doji(open, high, low, close, body_percent):
  function cdl_gravestone_doji_inc (line 836) | def cdl_gravestone_doji_inc(open, high, low, close, body_percent):
  function cdl_hammer (line 861) | def cdl_hammer(open, high, low, close, period, factor):
  function cdl_hammer_inc (line 893) | def cdl_hammer_inc(open, high, low, close, prev_body_avg, period, factor):
  function cdl_inverted_hammer (line 922) | def cdl_inverted_hammer(open, high, low, close, period, factor):
  function cdl_inverted_hammer_inc (line 954) | def cdl_inverted_hammer_inc(open, high, low, close, prev_body_avg, perio...
  function cdl_long_shadow (line 983) | def cdl_long_shadow(open, high, low, close, period, shadow_factor):
  function cdl_long_shadow_inc (line 1016) | def cdl_long_shadow_inc(open, high, low, close, prev_body_avg, period, s...
  function cdl_marubozu (line 1046) | def cdl_marubozu(open, high, low, close, period, shadow_percent):
  function cdl_marubozu_inc (line 1079) | def cdl_marubozu_inc(open, high, low, close, prev_body_avg, period, shad...
  function dema (line 1109) | def dema(input_price, period):
  function dema_inc (line 1134) | def dema_inc(price, prev_ema1, prev_ema2, period):
  function dx (line 1156) | def dx(high, low, close, period):
  function dx_inc (line 1188) | def dx_inc(input_high, input_low, prev_high, prev_low, prev_close, prev_...
  function ecl (line 1230) | def ecl(high, low, close):
  function ecl_inc (line 1258) | def ecl_inc(prev_high, prev_low, prev_close):
  function ema (line 1282) | def ema(data, period, k=None):
  function ema_inc (line 1312) | def ema_inc(price, prev_ema, period, k=None):
  function macd (line 1340) | def macd(data, fast_period, slow_period, signal_period):
  function macd_inc (line 1375) | def macd_inc(price, prev_fast_ema, prev_slow_ema, prev_signal, fast_peri...
  function max (line 1414) | def max(prices, period):
  function max_inc (line 1435) | def max_inc(price, prev_max, old_price, period):
  function medprice (line 1457) | def medprice(high, low):
  function medprice_inc (line 1484) | def medprice_inc(high, low):
  function mfi (line 1506) | def mfi(high, low, close, volume, period):
  function midpoint (line 1541) | def midpoint(data, period):
  function midpoint_inc (line 1569) | def midpoint_inc(price, prev_highest, prev_lowest, period):
  function midprice (line 1601) | def midprice(high, low, period):
  function midprice_inc (line 1631) | def midprice_inc(high, low, prev_highest, prev_lowest, period):
  function min (line 1666) | def min(prices, period):
  function min_inc (line 1689) | def min_inc(price, prev_min, prev_price, period):
  function minus_di (line 1711) | def minus_di(high, low, close, period):
  function minus_dm (line 1745) | def minus_dm(high, low, period):
  function mom (line 1772) | def mom(data, period):
  function mom_inc (line 1798) | def mom_inc(current_price, old_price):
  function natr (line 1823) | def natr(high, low, close, period):
  function natr_inc (line 1852) | def natr_inc(high, low, close, prev_close, prev_atr, period):
  function obv (line 1886) | def obv(close, volume):
  function obv_inc (line 1914) | def obv_inc(curr_close, prev_close, volume, prev_obv):
  function plus_di (line 1944) | def plus_di(high, low, close, period):
  function plus_di_inc (line 1976) | def plus_di_inc(high, low, prev_high, prev_low, prev_close, prev_smoothe...
  function plus_dm (line 2013) | def plus_dm(high, low, period):
  function plus_dm_inc (line 2040) | def plus_dm_inc(high, prev_high, low, prev_low, prev_plus_dm, period):
  function rma (line 2073) | def rma(data, period):
  function rma_inc (line 2101) | def rma_inc(current_price, prev_rma, period):
  function roc (line 2124) | def roc(data, period):
  function roc_inc (line 2151) | def roc_inc(current_price, prev_price):
  function rocp (line 2175) | def rocp(data, period):
  function rocp_inc (line 2202) | def rocp_inc(current_price, prev_price):
  function rocr (line 2226) | def rocr(data, period):
  function rocr100 (line 2253) | def rocr100(data, period):
  function rocr100_inc (line 2281) | def rocr100_inc(current_price, prev_price):
  function rocr_inc (line 2305) | def rocr_inc(current_price, prev_price):
  function rsi (line 2329) | def rsi(prices, period):
  function rsi_inc (line 2357) | def rsi_inc(current_price, prev_price, prev_avg_gain, prev_avg_loss, per...
  function sar (line 2382) | def sar(high, low, acceleration, maximum):
  function sar_inc (line 2411) | def sar_inc(high, low, prev_high, prev_low, prev_sar, is_long, af, ep, a...
  function sma (line 2440) | def sma(data, period):
  function sma_inc (line 2468) | def sma_inc(prev_sma, new_price, old_price, period):
  function stddev (line 2498) | def stddev(input, period):
  function stddev_inc (line 2526) | def stddev_inc(price, prev_sum, prev_sum_sq, old_price, period):
  function stoch (line 2558) | def stoch(high, low, close, k_period, k_slow_period, d_period):
  function sum (line 2593) | def sum(input, period):
  function sum_inc (line 2617) | def sum_inc(new_price, old_price, prev_sum):
  function supertrend (line 2642) | def supertrend(high, low, close, period, multiplier):
  function supertrend_inc (line 2677) | def supertrend_inc(high, low, close, prev_close, prev_atr, prev_trend, p...
  function t3 (line 2723) | def t3(data, period, vfactor):
  function t3_inc (line 2756) | def t3_inc(price, prev_ema1, prev_ema2, prev_ema3, prev_ema4, prev_ema5,...
  function tema (line 2802) | def tema(prices, period):
  function tema_inc (line 2831) | def tema_inc(new_price, prev_ema1, prev_ema2, prev_ema3, period):
  function trange (line 2863) | def trange(high, low, close):
  function trange_inc (line 2892) | def trange_inc(high, low, prev_close):
  function trima (line 2914) | def trima(prices, period):
  function trima_inc (line 2942) | def trima_inc(prev_sma1, prev_sma2, new_price, old_price, old_sma1, peri...
  function trix (line 2974) | def trix(prices, period):
  function trix_inc (line 3003) | def trix_inc(price, prev_ema1, prev_ema2, prev_ema3, period):
  function typprice (line 3035) | def typprice(high, low, close):
  function typprice_inc (line 3064) | def typprice_inc(high, low, close):
  function var (line 3086) | def var(prices, period):
  function var_inc (line 3113) | def var_inc(price, prev_sum, prev_sum_sq, old_price, period):
  function vegas (line 3145) | def vegas(prices):
  function vegas_inc (line 3172) | def vegas_inc(price, prev_channel_upper, prev_channel_lower, prev_bounda...
  function vwap (line 3206) | def vwap(high, low, close, volume):
  function vwap_inc (line 3235) | def vwap_inc(high, low, close, volume, prev_cum_pv, prev_cum_vol):
  function wclprice (line 3258) | def wclprice(high, low, close):
  function wclprice_inc (line 3286) | def wclprice_inc(high, low, close):
  function willr (line 3306) | def willr(high, low, close, period):
  function willr_inc (line 3339) | def willr_inc(prev_highest_high, prev_lowest_low, prev_high, prev_low, c...
  function wma (line 3369) | def wma(data, period):
  function wma_inc (line 3396) | def wma_inc(input_window, period):

FILE: kand-py/src/lib.rs
  function kand (line 9) | fn kand(m: &Bound<'_, PyModule>) -> PyResult<()> {

FILE: kand-py/src/ta/ohlcv/ad.rs
  function ad_py (line 33) | pub fn ad_py(
  function ad_inc_py (line 95) | pub fn ad_inc_py(

FILE: kand-py/src/ta/ohlcv/adosc.rs
  function adosc_py (line 38) | pub fn adosc_py(
  function adosc_inc_py (line 127) | pub fn adosc_inc_py(

FILE: kand-py/src/ta/ohlcv/adr.rs
  function adr_py (line 29) | pub fn adr_py(
  function adr_inc_py (line 80) | pub fn adr_inc_py(

FILE: kand-py/src/ta/ohlcv/adx.rs
  function adx_py (line 35) | pub fn adx_py(
  function adx_inc_py (line 123) | pub fn adx_inc_py(

FILE: kand-py/src/ta/ohlcv/adxr.rs
  function adxr_py (line 36) | pub fn adxr_py(
  function adxr_inc_py (line 139) | pub fn adxr_inc_py(

FILE: kand-py/src/ta/ohlcv/aroon.rs
  function aroon_py (line 35) | pub fn aroon_py(
  function aroon_inc_py (line 128) | pub fn aroon_inc_py(

FILE: kand-py/src/ta/ohlcv/aroonosc.rs
  function aroonosc_py (line 34) | pub fn aroonosc_py(
  function aroonosc_inc_py (line 122) | pub fn aroonosc_inc_py(

FILE: kand-py/src/ta/ohlcv/atr.rs
  function atr_py (line 31) | pub fn atr_py(
  function atr_inc_py (line 91) | pub fn atr_inc_py(

FILE: kand-py/src/ta/ohlcv/bbands.rs
  function bbands_py (line 38) | pub fn bbands_py(
  function bbands_inc_py (line 139) | pub fn bbands_inc_py(

FILE: kand-py/src/ta/ohlcv/bop.rs
  function bop_py (line 32) | pub fn bop_py(
  function bop_inc_py (line 78) | pub fn bop_inc_py(

FILE: kand-py/src/ta/ohlcv/cci.rs
  function cci_py (line 37) | pub fn cci_py(
  function cci_inc_py (line 119) | pub fn cci_inc_py(

FILE: kand-py/src/ta/ohlcv/cdl_doji.rs
  function cdl_doji_py (line 30) | pub fn cdl_doji_py(
  function cdl_doji_inc_py (line 84) | pub fn cdl_doji_inc_py(

FILE: kand-py/src/ta/ohlcv/cdl_dragonfly_doji.rs
  function cdl_dragonfly_doji_py (line 31) | pub fn cdl_dragonfly_doji_py(
  function cdl_dragonfly_doji_inc_py (line 84) | pub fn cdl_dragonfly_doji_inc_py(

FILE: kand-py/src/ta/ohlcv/cdl_gravestone_doji.rs
  function cdl_gravestone_doji_py (line 31) | pub fn cdl_gravestone_doji_py(
  function cdl_gravestone_doji_inc_py (line 84) | pub fn cdl_gravestone_doji_inc_py(

FILE: kand-py/src/ta/ohlcv/cdl_hammer.rs
  function cdl_hammer_py (line 34) | pub fn cdl_hammer_py(
  function cdl_hammer_inc_py (line 98) | pub fn cdl_hammer_inc_py(

FILE: kand-py/src/ta/ohlcv/cdl_inverted_hammer.rs
  function cdl_inverted_hammer_py (line 34) | pub fn cdl_inverted_hammer_py(
  function cdl_inverted_hammer_inc_py (line 98) | pub fn cdl_inverted_hammer_inc_py(

FILE: kand-py/src/ta/ohlcv/cdl_long_shadow.rs
  function cdl_long_shadow_py (line 35) | pub fn cdl_long_shadow_py(
  function cdl_long_shadow_inc_py (line 100) | pub fn cdl_long_shadow_inc_py(

FILE: kand-py/src/ta/ohlcv/cdl_marubozu.rs
  function cdl_marubozu_py (line 35) | pub fn cdl_marubozu_py(
  function cdl_marubozu_inc_py (line 100) | pub fn cdl_marubozu_inc_py(

FILE: kand-py/src/ta/ohlcv/dema.rs
  function dema_py (line 27) | pub fn dema_py(
  function dema_inc_py (line 80) | pub fn dema_inc_py(

FILE: kand-py/src/ta/ohlcv/dx.rs
  function dx_py (line 34) | pub fn dx_py(
  function dx_inc_py (line 131) | pub fn dx_inc_py(

FILE: kand-py/src/ta/ohlcv/ecl.rs
  function ecl_py (line 30) | pub fn ecl_py(
  function ecl_inc_py (line 117) | pub fn ecl_inc_py(

FILE: kand-py/src/ta/ohlcv/ema.rs
  function ema_py (line 32) | pub fn ema_py(
  function ema_inc_py (line 78) | pub fn ema_inc_py(

FILE: kand-py/src/ta/ohlcv/macd.rs
  function macd_py (line 37) | pub fn macd_py(
  function macd_inc_py (line 123) | pub fn macd_inc_py(

FILE: kand-py/src/ta/ohlcv/medprice.rs
  function medprice_py (line 29) | pub fn medprice_py(
  function medprice_inc_py (line 64) | pub fn medprice_inc_py(py: Python, high: TAFloat, low: TAFloat) -> PyRes...

FILE: kand-py/src/ta/ohlcv/mfi.rs
  function mfi_py (line 37) | pub fn mfi_py(

FILE: kand-py/src/ta/ohlcv/midpoint.rs
  function midpoint_py (line 30) | pub fn midpoint_py(
  function midpoint_inc_py (line 93) | pub fn midpoint_inc_py(

FILE: kand-py/src/ta/ohlcv/midprice.rs
  function midprice_py (line 32) | pub fn midprice_py(
  function midprice_inc_py (line 101) | pub fn midprice_inc_py(

FILE: kand-py/src/ta/ohlcv/minus_di.rs
  function minus_di_py (line 36) | pub fn minus_di_py(
  function minus_di_inc_py (line 118) | pub fn minus_di_inc_py(

FILE: kand-py/src/ta/ohlcv/minus_dm.rs
  function minus_dm_py (line 29) | pub fn minus_dm_py(
  function minus_dm_inc_py (line 82) | pub fn minus_dm_inc_py(

FILE: kand-py/src/ta/ohlcv/mom.rs
  function mom_py (line 28) | pub fn mom_py(
  function mom_inc_py (line 70) | pub fn mom_inc_py(py: Python, current_price: TAFloat, old_price: TAFloat...

FILE: kand-py/src/ta/ohlcv/natr.rs
  function natr_py (line 31) | pub fn natr_py(
  function natr_inc_py (line 94) | pub fn natr_inc_py(

FILE: kand-py/src/ta/ohlcv/obv.rs
  function obv_py (line 30) | pub fn obv_py(
  function obv_inc_py (line 78) | pub fn obv_inc_py(

FILE: kand-py/src/ta/ohlcv/plus_di.rs
  function plus_di_py (line 34) | pub fn plus_di_py(
  function plus_di_inc_py (line 112) | pub fn plus_di_inc_py(

FILE: kand-py/src/ta/ohlcv/plus_dm.rs
  function plus_dm_py (line 29) | pub fn plus_dm_py(
  function plus_dm_inc_py (line 81) | pub fn plus_dm_inc_py(

FILE: kand-py/src/ta/ohlcv/rma.rs
  function rma_py (line 30) | pub fn rma_py(
  function rma_inc_py (line 70) | pub fn rma_inc_py(current_price: TAFloat, prev_rma: TAFloat, period: usi...

FILE: kand-py/src/ta/ohlcv/roc.rs
  function roc_py (line 29) | pub fn roc_py(
  function roc_inc_py (line 70) | pub fn roc_inc_py(current_price: TAFloat, prev_price: TAFloat) -> PyResu...

FILE: kand-py/src/ta/ohlcv/rocp.rs
  function rocp_py (line 29) | pub fn rocp_py(
  function rocp_inc_py (line 70) | pub fn rocp_inc_py(current_price: TAFloat, prev_price: TAFloat) -> PyRes...

FILE: kand-py/src/ta/ohlcv/rocr.rs
  function rocr_py (line 29) | pub fn rocr_py(
  function rocr_inc_py (line 70) | pub fn rocr_inc_py(current_price: TAFloat, prev_price: TAFloat) -> PyRes...

FILE: kand-py/src/ta/ohlcv/rocr100.rs
  function rocr100_py (line 30) | pub fn rocr100_py(
  function rocr100_inc_py (line 71) | pub fn rocr100_inc_py(current_price: TAFloat, prev_price: TAFloat) -> Py...

FILE: kand-py/src/ta/ohlcv/rsi.rs
  function rsi_py (line 30) | pub fn rsi_py(
  function rsi_inc_py (line 90) | pub fn rsi_inc_py(

FILE: kand-py/src/ta/ohlcv/sar.rs
  function sar_py (line 31) | pub fn sar_py(
  function sar_inc_py (line 100) | pub fn sar_inc_py(

FILE: kand-py/src/ta/ohlcv/sma.rs
  function sma_py (line 30) | pub fn sma_py(
  function sma_inc_py (line 77) | pub fn sma_inc_py(

FILE: kand-py/src/ta/ohlcv/stoch.rs
  function stoch_py (line 37) | pub fn stoch_py(

FILE: kand-py/src/ta/ohlcv/supertrend.rs
  function supertrend_py (line 37) | pub fn supertrend_py(
  function supertrend_inc_py (line 145) | pub fn supertrend_inc_py(

FILE: kand-py/src/ta/ohlcv/t3.rs
  function t3_py (line 35) | pub fn t3_py(
  function t3_inc_py (line 130) | pub fn t3_inc_py(

FILE: kand-py/src/ta/ohlcv/tema.rs
  function tema_py (line 31) | pub fn tema_py(
  function tema_inc_py (line 98) | pub fn tema_inc_py(

FILE: kand-py/src/ta/ohlcv/trange.rs
  function trange_py (line 32) | pub fn trange_py(
  function trange_inc_py (line 74) | pub fn trange_inc_py(high: TAFloat, low: TAFloat, prev_close: TAFloat) -...

FILE: kand-py/src/ta/ohlcv/trima.rs
  function trima_py (line 30) | pub fn trima_py(
  function trima_inc_py (line 86) | pub fn trima_inc_py(

FILE: kand-py/src/ta/ohlcv/trix.rs
  function trix_py (line 31) | pub fn trix_py(
  function trix_inc_py (line 98) | pub fn trix_inc_py(

FILE: kand-py/src/ta/ohlcv/typprice.rs
  function typprice_py (line 31) | pub fn typprice_py(
  function typprice_inc_py (line 75) | pub fn typprice_inc_py(high: TAFloat, low: TAFloat, close: TAFloat) -> P...

FILE: kand-py/src/ta/ohlcv/vegas.rs
  function vegas_py (line 29) | pub fn vegas_py(
  function vegas_inc_py (line 100) | pub fn vegas_inc_py(

FILE: kand-py/src/ta/ohlcv/vwap.rs
  function vwap_py (line 31) | pub fn vwap_py(
  function vwap_inc_py (line 92) | pub fn vwap_inc_py(

FILE: kand-py/src/ta/ohlcv/wclprice.rs
  function wclprice_py (line 30) | pub fn wclprice_py(
  function wclprice_inc_py (line 68) | pub fn wclprice_inc_py(high: TAFloat, low: TAFloat, close: TAFloat) -> P...

FILE: kand-py/src/ta/ohlcv/willr.rs
  function willr_py (line 35) | pub fn willr_py(
  function willr_inc_py (line 105) | pub fn willr_inc_py(

FILE: kand-py/src/ta/ohlcv/wma.rs
  function wma_py (line 29) | pub fn wma_py(
  function wma_inc_py (line 66) | pub fn wma_inc_py(input_window: Vec<TAFloat>, period: usize) -> PyResult...

FILE: kand-py/src/ta/stats/correl.rs
  function correl_py (line 38) | pub fn correl_py(
  function correl_inc_py (line 137) | pub fn correl_inc_py(

FILE: kand-py/src/ta/stats/max.rs
  function max_py (line 23) | pub fn max_py(
  function max_inc_py (line 62) | pub fn max_inc_py(

FILE: kand-py/src/ta/stats/min.rs
  function min_py (line 25) | pub fn min_py(
  function min_inc_py (line 64) | pub fn min_inc_py(

FILE: kand-py/src/ta/stats/stddev.rs
  function stddev_py (line 30) | pub fn stddev_py(
  function stddev_inc_py (line 93) | pub fn stddev_inc_py(

FILE: kand-py/src/ta/stats/sum.rs
  function sum_py (line 26) | pub fn sum_py(
  function sum_inc_py (line 68) | pub fn sum_inc_py(

FILE: kand-py/src/ta/stats/var.rs
  function var_py (line 29) | pub fn var_py(
  function var_inc_py (line 92) | pub fn var_inc_py(

FILE: kand-wasm/src/ta/ohlcv/ad.rs
  function ad_lookback_wasm (line 9) | pub fn ad_lookback_wasm() -> Result<usize, JsValue> {
  function ad_wasm (line 23) | pub fn ad_wasm(
  function ad_inc_wasm (line 52) | pub fn ad_inc_wasm(

FILE: kand-wasm/src/ta/ohlcv/adosc.rs
  function adosc_lookback_wasm (line 12) | pub fn adosc_lookback_wasm(
  function adosc_wasm (line 31) | pub fn adosc_wasm(
  function adosc_inc_wasm (line 77) | pub fn adosc_inc_wasm(

FILE: kand-wasm/src/ta/ohlcv/ema.rs
  function ema_lookback_wasm (line 11) | pub fn ema_lookback_wasm(opt_period: usize) -> Result<usize, JsValue> {
  function ema_wasm (line 24) | pub fn ema_wasm(
  function ema_inc_wasm (line 47) | pub fn ema_inc_wasm(

FILE: kand/benches/benchmarks/ohlcv/ad_bench.rs
  function bench_ad (line 8) | fn bench_ad(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/adosc_bench.rs
  function bench_adosc (line 8) | fn bench_adosc(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/adr_bench.rs
  function bench_adr (line 8) | fn bench_adr(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/adx_bench.rs
  function bench_adx (line 8) | fn bench_adx(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/adxr_bench.rs
  function bench_adxr (line 8) | fn bench_adxr(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/aroon_bench.rs
  function bench_aroon (line 8) | fn bench_aroon(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/aroonosc_bench.rs
  function bench_aroonosc (line 8) | fn bench_aroonosc(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/atr_bench.rs
  function bench_atr (line 8) | fn bench_atr(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/bbands_bench.rs
  function bench_bbands (line 8) | fn bench_bbands(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/bop_bench.rs
  function bench_bop (line 8) | fn bench_bop(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/cci_bench.rs
  function bench_cci (line 8) | fn bench_cci(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/cdl_doji_bench.rs
  function bench_cdl_doji (line 8) | fn bench_cdl_doji(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/cdl_dragonfly_doji_bench.rs
  function bench_cdl_dragonfly_doji (line 8) | fn bench_cdl_dragonfly_doji(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/cdl_gravestone_doji_bench.rs
  function bench_cdl_gravestone_doji (line 8) | fn bench_cdl_gravestone_doji(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/cdl_hammer_bench.rs
  function bench_cdl_hammer (line 7) | fn bench_cdl_hammer(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/cdl_inverted_hammer_bench.rs
  function bench_cdl_inverted_hammer (line 7) | fn bench_cdl_inverted_hammer(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/cdl_long_shadow_bench.rs
  function bench_cdl_long_shadow (line 7) | fn bench_cdl_long_shadow(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/cdl_marubozu_bench.rs
  function bench_cdl_marubozu (line 8) | fn bench_cdl_marubozu(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/dema_bench.rs
  function bench_dema (line 7) | fn bench_dema(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/dx_bench.rs
  function bench_dx (line 8) | fn bench_dx(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/ecl_bench.rs
  function bench_ecl (line 9) | fn bench_ecl(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/ema_bench.rs
  function bench_ema (line 8) | fn bench_ema(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/macd_bench.rs
  function bench_macd (line 8) | fn bench_macd(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/medprice_bench.rs
  function bench_medprice (line 8) | fn bench_medprice(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/mfi_bench.rs
  function bench_mfi (line 8) | fn bench_mfi(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/midpoint_bench.rs
  function bench_midpoint (line 8) | fn bench_midpoint(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/midprice_bench.rs
  function bench_midprice (line 8) | fn bench_midprice(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/minus_di_bench.rs
  function bench_minus_di (line 8) | fn bench_minus_di(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/minus_dm_bench.rs
  function bench_minus_dm (line 8) | fn bench_minus_dm(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/mom_bench.rs
  function bench_mom (line 8) | fn bench_mom(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/natr_bench.rs
  function bench_natr (line 8) | fn bench_natr(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/obv_bench.rs
  function bench_obv (line 8) | fn bench_obv(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/plus_di_bench.rs
  function bench_plus_di (line 8) | fn bench_plus_di(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/plus_dm_bench.rs
  function bench_plus_dm (line 8) | fn bench_plus_dm(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/rma_bench.rs
  function bench_rma (line 8) | fn bench_rma(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/roc_bench.rs
  function bench_roc (line 8) | fn bench_roc(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/rocp_bench.rs
  function bench_rocp (line 8) | fn bench_rocp(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/rocr100_bench.rs
  function bench_rocr100 (line 8) | fn bench_rocr100(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/rocr_bench.rs
  function bench_rocr (line 8) | fn bench_rocr(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/rsi_bench.rs
  function bench_rsi (line 8) | fn bench_rsi(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/sar_bench.rs
  function bench_sar (line 7) | fn bench_sar(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/sma_bench.rs
  function bench_sma (line 8) | fn bench_sma(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/stoch_bench.rs
  function bench_stoch (line 8) | fn bench_stoch(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/supertrend_bench.rs
  function bench_supertrend (line 8) | fn bench_supertrend(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/t3_bench.rs
  function bench_t3 (line 7) | fn bench_t3(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/tema_bench.rs
  function bench_tema (line 8) | fn bench_tema(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/trange_bench.rs
  function bench_trange (line 8) | fn bench_trange(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/trima_bench.rs
  function bench_trima (line 8) | fn bench_trima(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/trix_bench.rs
  function bench_trix (line 8) | fn bench_trix(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/typprice_bench.rs
  function bench_typprice (line 8) | fn bench_typprice(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/vegas_bench.rs
  function bench_vegas (line 8) | fn bench_vegas(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/vwap_bench.rs
  function bench_vwap (line 8) | fn bench_vwap(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/wclprice_bench.rs
  function bench_wclprice (line 8) | fn bench_wclprice(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/willr_bench.rs
  function bench_willr (line 8) | fn bench_willr(c: &mut Criterion) {

FILE: kand/benches/benchmarks/ohlcv/wma_bench.rs
  function bench_wma (line 8) | fn bench_wma(c: &mut Criterion) {

FILE: kand/benches/benchmarks/stats/beta_bench.rs
  function bench_beta (line 7) | fn bench_beta(c: &mut Criterion) {

FILE: kand/benches/benchmarks/stats/correl_bench.rs
  function bench_correl (line 8) | fn bench_correl(c: &mut Criterion) {

FILE: kand/benches/benchmarks/stats/max_bench.rs
  function bench_max (line 8) | fn bench_max(c: &mut Criterion) {

FILE: kand/benches/benchmarks/stats/min_bench.rs
  function bench_min (line 8) | fn bench_min(c: &mut Criterion) {

FILE: kand/benches/benchmarks/stats/stddev_bench.rs
  function bench_stddev (line 8) | fn bench_stddev(c: &mut Criterion) {

FILE: kand/benches/benchmarks/stats/sum_bench.rs
  function bench_sum (line 8) | fn bench_sum(c: &mut Criterion) {

FILE: kand/benches/benchmarks/stats/var_bench.rs
  function bench_var (line 8) | fn bench_var(c: &mut Criterion) {

FILE: kand/benches/helper.rs
  function generate_test_data (line 12) | pub fn generate_test_data(size: usize) -> Vec<TAFloat> {

FILE: kand/src/error.rs
  type KandError (line 2) | pub enum KandError {
  type Result (line 31) | pub type Result<T> = std::result::Result<T, KandError>;

FILE: kand/src/helper.rs
  function lowest_bars (line 34) | pub fn lowest_bars(
  function highest_bars (line 86) | pub fn highest_bars(
  function period_to_k (line 117) | pub fn period_to_k(period: usize) -> Result<TAFloat, KandError> {
  function real_body_length (line 133) | pub fn real_body_length(open: TAFloat, close: TAFloat) -> TAFloat {
  function upper_shadow_length (line 147) | pub fn upper_shadow_length(high: TAFloat, open: TAFloat, close: TAFloat)...
  function lower_shadow_length (line 161) | pub fn lower_shadow_length(low: TAFloat, open: TAFloat, close: TAFloat) ...
  function has_real_body_gap_up (line 180) | pub fn has_real_body_gap_up(
  function has_real_body_gap_down (line 200) | pub fn has_real_body_gap_down(

FILE: kand/src/lib.rs
  type TAFloat (line 105) | pub type TAFloat = f32;
  type TAFloat (line 108) | pub type TAFloat = f64;
  type TAInt (line 122) | pub type TAInt = i32;
  type TAInt (line 125) | pub type TAInt = i64;
  type TAPeriod (line 131) | pub type TAPeriod = usize;
  constant EPSILON (line 140) | pub const EPSILON: TAFloat = f32::EPSILON;
  constant EPSILON (line 143) | pub const EPSILON: TAFloat = f64::EPSILON;

FILE: kand/src/ta/ohlcv/ad.rs
  function lookback (line 19) | pub const fn lookback() -> Result<TAPeriod, KandError> {
  function ad_raw (line 42) | pub fn ad_raw(
  function ad (line 112) | pub fn ad(
  function ad_inc_raw (line 191) | pub fn ad_inc_raw(
  function ad_inc (line 238) | pub fn ad_inc(
  constant INPUT_HIGH (line 273) | const INPUT_HIGH: [f64; 25] = [
  constant INPUT_LOW (line 279) | const INPUT_LOW: [f64; 25] = [
  constant INPUT_CLOSE (line 285) | const INPUT_CLOSE: [f64; 25] = [
  constant INPUT_VOLUME (line 291) | const INPUT_VOLUME: [f64; 25] = [
  constant EXPECTED_VALUES (line 297) | const EXPECTED_VALUES: [f64; 25] = [
  function test_ad_with_nan (line 328) | fn test_ad_with_nan() {
  function test_ad_without_nan (line 367) | fn test_ad_without_nan() {

FILE: kand/src/ta/ohlcv/adosc.rs
  function lookback (line 20) | pub const fn lookback(opt_fast_period: usize, opt_slow_period: usize) ->...
  function adosc (line 90) | pub fn adosc(
  function adosc_inc (line 192) | pub fn adosc_inc(
  function test_adosc_calculation (line 247) | fn test_adosc_calculation() {

FILE: kand/src/ta/ohlcv/adr.rs
  function lookback (line 20) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function adr (line 60) | pub fn adr(
  function adr_inc (line 135) | pub fn adr_inc(
  function test_adr_calculation (line 176) | fn test_adr_calculation() {

FILE: kand/src/ta/ohlcv/adx.rs
  function lookback (line 25) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function adx (line 110) | pub fn adx(
  function adx_inc (line 242) | pub fn adx_inc(
  function test_adx_calculation (line 310) | fn test_adx_calculation() {

FILE: kand/src/ta/ohlcv/adxr.rs
  function lookback (line 22) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function adxr (line 95) | pub fn adxr(
  function adxr_inc (line 225) | pub fn adxr_inc(
  function test_adxr_calculation (line 297) | fn test_adxr_calculation() {

FILE: kand/src/ta/ohlcv/aroon.rs
  function lookback (line 28) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function aroon (line 104) | pub fn aroon(
  function aroon_inc (line 254) | pub fn aroon_inc(
  function test_aroon_calculation (line 325) | fn test_aroon_calculation() {

FILE: kand/src/ta/ohlcv/aroonosc.rs
  function lookback (line 29) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function aroonosc (line 103) | pub fn aroonosc(
  function aroonosc_inc (line 238) | pub fn aroonosc_inc(
  function test_aroonosc_calculation (line 307) | fn test_aroonosc_calculation() {

FILE: kand/src/ta/ohlcv/atr.rs
  function lookback (line 26) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function atr (line 92) | pub fn atr(
  function atr_inc (line 194) | pub fn atr_inc(
  function test_atr_calculation (line 229) | fn test_atr_calculation() {

FILE: kand/src/ta/ohlcv/bbands.rs
  function lookback (line 29) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function bbands (line 109) | pub fn bbands(
  function bbands_inc (line 244) | pub fn bbands_inc(
  function test_bbands_calculation (line 302) | fn test_bbands_calculation() {

FILE: kand/src/ta/ohlcv/bop.rs
  function lookback (line 24) | pub const fn lookback() -> Result<usize, KandError> {
  function bop (line 80) | pub fn bop(
  function bop_inc (line 166) | pub fn bop_inc(
  function test_bop_calculation (line 196) | fn test_bop_calculation() {

FILE: kand/src/ta/ohlcv/cci.rs
  function lookback (line 27) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function cci (line 106) | pub fn cci(
  function cci_inc (line 254) | pub fn cci_inc(
  function test_cci_calculation (line 325) | fn test_cci_calculation() {

FILE: kand/src/ta/ohlcv/cdl_doji.rs
  function lookback (line 26) | pub const fn lookback() -> Result<usize, KandError> {
  function cdl_doji (line 93) | pub fn cdl_doji(
  function cdl_doji_inc (line 183) | pub fn cdl_doji_inc(
  function test_cdl_doji (line 250) | fn test_cdl_doji() {

FILE: kand/src/ta/ohlcv/cdl_dragonfly_doji.rs
  function lookback (line 26) | pub const fn lookback() -> Result<usize, KandError> {
  function cdl_dragonfly_doji (line 85) | pub fn cdl_dragonfly_doji(
  function cdl_dragonfly_doji_inc (line 181) | pub fn cdl_dragonfly_doji_inc(
  function test_cdl_dragonfly_doji (line 227) | fn test_cdl_dragonfly_doji() {

FILE: kand/src/ta/ohlcv/cdl_gravestone_doji.rs
  function lookback (line 26) | pub const fn lookback() -> Result<usize, KandError> {
  function cdl_gravestone_doji (line 80) | pub fn cdl_gravestone_doji(
  function cdl_gravestone_doji_inc (line 174) | pub fn cdl_gravestone_doji_inc(
  function test_cdl_gravestone_doji (line 211) | fn test_cdl_gravestone_doji() {

FILE: kand/src/ta/ohlcv/cdl_hammer.rs
  function lookback (line 28) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function cdl_hammer (line 101) | pub fn cdl_hammer(
  function cdl_hammer_inc (line 232) | pub fn cdl_hammer_inc(
  function test_cdl_hammer (line 294) | fn test_cdl_hammer() {

FILE: kand/src/ta/ohlcv/cdl_inverted_hammer.rs
  function lookback (line 31) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function cdl_inverted_hammer (line 105) | pub fn cdl_inverted_hammer(
  function cdl_inverted_hammer_inc (line 231) | pub fn cdl_inverted_hammer_inc(
  function test_cdl_inverted_hammer (line 283) | fn test_cdl_inverted_hammer() {

FILE: kand/src/ta/ohlcv/cdl_long_shadow.rs
  function lookback (line 31) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function cdl_long_shadow (line 107) | pub fn cdl_long_shadow(
  function cdl_long_shadow_inc (line 251) | pub fn cdl_long_shadow_inc(
  function test_cdl_long_shadow (line 319) | fn test_cdl_long_shadow() {

FILE: kand/src/ta/ohlcv/cdl_marubozu.rs
  function lookback (line 32) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function cdl_marubozu (line 106) | pub fn cdl_marubozu(
  function cdl_marubozu_inc (line 250) | pub fn cdl_marubozu_inc(
  function test_cdl_marubozu (line 315) | fn test_cdl_marubozu() {

FILE: kand/src/ta/ohlcv/dema.rs
  function lookback (line 24) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function dema (line 87) | pub fn dema(
  function dema_inc (line 206) | pub fn dema_inc(
  function test_dema_calculation (line 243) | fn test_dema_calculation() {

FILE: kand/src/ta/ohlcv/dx.rs
  function lookback (line 26) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function dx (line 98) | pub fn dx(
  function dx_inc (line 242) | pub fn dx_inc(
  function test_dx_calculation (line 319) | fn test_dx_calculation() {

FILE: kand/src/ta/ohlcv/ecl.rs
  function lookback (line 22) | pub const fn lookback() -> Result<usize, KandError> {
  function ecl (line 95) | pub fn ecl(
  function ecl_inc (line 234) | pub fn ecl_inc(
  function test_ecl_calculation (line 286) | fn test_ecl_calculation() {

FILE: kand/src/ta/ohlcv/ema.rs
  function lookback (line 25) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function ema (line 81) | pub fn ema(
  function ema_inc (line 182) | pub fn ema_inc(
  function test_ema_calculation (line 219) | fn test_ema_calculation() {

FILE: kand/src/ta/ohlcv/ha.rs
  function lookback (line 14) | pub const fn lookback() -> Result<usize, KandError> {
  function ha (line 77) | pub fn ha(
  function ha_inc (line 192) | pub fn ha_inc(
  function test_ha_calculation (line 229) | fn test_ha_calculation() {

FILE: kand/src/ta/ohlcv/macd.rs
  function lookback (line 25) | pub fn lookback(
  function macd (line 113) | pub fn macd(
  function macd_inc (line 243) | pub fn macd_inc(

FILE: kand/src/ta/ohlcv/medprice.rs
  function lookback (line 21) | pub const fn lookback() -> Result<usize, KandError> {
  function medprice (line 66) | pub fn medprice(
  function medprice_inc (line 127) | pub const fn medprice_inc(input_high: TAFloat, input_low: TAFloat) -> Re...
  function test_medprice_calculation (line 145) | fn test_medprice_calculation() {

FILE: kand/src/ta/ohlcv/mfi.rs
  function lookback (line 25) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function mfi (line 100) | pub fn mfi(
  function test_mfi_calculation (line 200) | fn test_mfi_calculation() {

FILE: kand/src/ta/ohlcv/midpoint.rs
  function lookback (line 26) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function midpoint (line 94) | pub fn midpoint(
  function midpoint_inc (line 203) | pub const fn midpoint_inc(
  function test_midpoint_calculation (line 237) | fn test_midpoint_calculation() {

FILE: kand/src/ta/ohlcv/midprice.rs
  function lookback (line 24) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function midprice (line 83) | pub fn midprice(
  function midprice_inc (line 181) | pub const fn midprice_inc(
  function test_midprice_calculation (line 220) | fn test_midprice_calculation() {

FILE: kand/src/ta/ohlcv/minus_di.rs
  function lookback (line 21) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function minus_di (line 107) | pub fn minus_di(
  function minus_di_inc (line 283) | pub fn minus_di_inc(
  function test_minus_di_calculation (line 355) | fn test_minus_di_calculation() {

FILE: kand/src/ta/ohlcv/minus_dm.rs
  function lookback (line 25) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function minus_dm (line 90) | pub fn minus_dm(
  function minus_dm_inc (line 218) | pub fn minus_dm_inc(
  function test_minus_dm_calculation (line 267) | fn test_minus_dm_calculation() {

FILE: kand/src/ta/ohlcv/mom.rs
  function lookback (line 26) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function mom (line 82) | pub fn mom(
  function mom_inc (line 156) | pub fn mom_inc(
  function test_mom_calculation (line 177) | fn test_mom_calculation() {

FILE: kand/src/ta/ohlcv/natr.rs
  function lookback (line 25) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function natr (line 83) | pub fn natr(
  function natr_inc (line 185) | pub fn natr_inc(
  function test_natr_calculation (line 225) | fn test_natr_calculation() {

FILE: kand/src/ta/ohlcv/obv.rs
  function lookback (line 20) | pub const fn lookback() -> Result<usize, KandError> {
  function obv (line 72) | pub fn obv(
  function obv_inc (line 154) | pub fn obv_inc(
  function test_obv_calculation (line 188) | fn test_obv_calculation() {

FILE: kand/src/ta/ohlcv/plus_di.rs
  function lookback (line 22) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function plus_di (line 105) | pub fn plus_di(
  function plus_di_inc (line 281) | pub fn plus_di_inc(
  function test_plus_di_calculation (line 347) | fn test_plus_di_calculation() {

FILE: kand/src/ta/ohlcv/plus_dm.rs
  function lookback (line 24) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function plus_dm (line 83) | pub fn plus_dm(
  function plus_dm_inc (line 204) | pub fn plus_dm_inc(
  function test_plus_dm_calculation (line 253) | fn test_plus_dm_calculation() {

FILE: kand/src/ta/ohlcv/rma.rs
  function lookback (line 25) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function rma (line 75) | pub fn rma(
  function rma_inc (line 163) | pub fn rma_inc(
  function test_rma_calculation (line 195) | fn test_rma_calculation() {
  function test_rma_incremental (line 228) | fn test_rma_incremental() {
  function test_rma_edge_cases (line 256) | fn test_rma_edge_cases() {
  function test_rma_with_extended_data (line 278) | fn test_rma_with_extended_data() {
  function test_rma_error_conditions (line 327) | fn test_rma_error_conditions() {

FILE: kand/src/ta/ohlcv/roc.rs
  function lookback (line 25) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function roc (line 81) | pub fn roc(
  function roc_inc (line 172) | pub fn roc_inc(current_price: TAFloat, prev_price: TAFloat) -> Result<TA...
  function test_roc_calculation (line 195) | fn test_roc_calculation() {

FILE: kand/src/ta/ohlcv/rocp.rs
  function lookback (line 25) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function rocp (line 80) | pub fn rocp(
  function rocp_inc (line 160) | pub fn rocp_inc(input: TAFloat, prev: TAFloat) -> Result<TAFloat, KandEr...
  function test_rocp_calculation (line 178) | fn test_rocp_calculation() {

FILE: kand/src/ta/ohlcv/rocr.rs
  function lookback (line 22) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function rocr (line 75) | pub fn rocr(
  function rocr_inc (line 148) | pub fn rocr_inc(input: TAFloat, prev: TAFloat) -> Result<TAFloat, KandEr...
  function test_rocr_calculation (line 166) | fn test_rocr_calculation() {

FILE: kand/src/ta/ohlcv/rocr100.rs
  function lookback (line 25) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function rocr100 (line 79) | pub fn rocr100(
  function rocr100_inc (line 154) | pub fn rocr100_inc(input: TAFloat, prev: TAFloat) -> Result<TAFloat, Kan...
  function test_rocr100_calculation (line 172) | fn test_rocr100_calculation() {

FILE: kand/src/ta/ohlcv/rsi.rs
  function lookback (line 25) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function rsi (line 99) | pub fn rsi(
  function rsi_inc (line 245) | pub fn rsi_inc(
  function test_rsi_calculation (line 301) | fn test_rsi_calculation() {

FILE: kand/src/ta/ohlcv/sar.rs
  function lookback (line 28) | pub const fn lookback(
  function sar (line 100) | pub fn sar(
  function sar_inc (line 276) | pub fn sar_inc(
  function test_sar_calculation (line 351) | fn test_sar_calculation() {

FILE: kand/src/ta/ohlcv/sma.rs
  function lookback_raw (line 12) | pub const fn lookback_raw(opt_period: TAPeriod) -> TAPeriod {
  function lookback (line 22) | pub const fn lookback(opt_period: TAPeriod) -> Result<TAPeriod, KandErro...
  function sma_raw (line 41) | pub fn sma_raw(input: &[TAFloat], opt_period: TAPeriod, output: &mut [TA...
  function sma (line 70) | pub fn sma(
  function sma_inc_raw (line 118) | pub fn sma_inc_raw(
  function sma_inc (line 139) | pub fn sma_inc(
  constant PERIOD (line 170) | const PERIOD: TAPeriod = 14;
  constant LOOKBACK (line 171) | const LOOKBACK: TAPeriod = PERIOD - 1;
  constant INPUT_DATA (line 173) | const INPUT_DATA: [f64; 39] = [
  constant EXPECTED_VALUES (line 180) | const EXPECTED_VALUES: [f64; 13] = [
  function test_sma_with_nan (line 199) | fn test_sma_with_nan() {
  function test_sma_without_nan (line 225) | fn test_sma_without_nan() {

FILE: kand/src/ta/ohlcv/stoch.rs
  function lookback (line 31) | pub const fn lookback(
  function stoch (line 114) | pub fn stoch(
  function test_stoch_calculation (line 210) | fn test_stoch_calculation() {

FILE: kand/src/ta/ohlcv/supertrend.rs
  function lookback (line 27) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function supertrend (line 94) | pub fn supertrend(
  function supertrend_inc (line 264) | pub fn supertrend_inc(
  function test_supertrend_calculation (line 348) | fn test_supertrend_calculation() {

FILE: kand/src/ta/ohlcv/t3.rs
  function lookback (line 13) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function t3 (line 99) | pub fn t3(
  function t3_inc (line 335) | pub fn t3_inc(
  function test_t3_calculation (line 412) | fn test_t3_calculation() {

FILE: kand/src/ta/ohlcv/tema.rs
  function lookback (line 25) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function tema (line 94) | pub fn tema(
  function tema_inc (line 209) | pub fn tema_inc(
  function test_tema_calculation (line 245) | fn test_tema_calculation() {

FILE: kand/src/ta/ohlcv/trange.rs
  function lookback (line 24) | pub const fn lookback() -> Result<usize, KandError> {
  function trange (line 79) | pub fn trange(
  function trange_inc (line 167) | pub fn trange_inc(
  function test_trange_calculation (line 194) | fn test_trange_calculation() {

FILE: kand/src/ta/ohlcv/trima.rs
  function lookback (line 25) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function trima (line 87) | pub fn trima(
  function trima_inc (line 215) | pub fn trima_inc(
  function test_trima_calculation (line 270) | fn test_trima_calculation() {

FILE: kand/src/ta/ohlcv/trix.rs
  function lookback (line 27) | pub fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function trix (line 82) | pub fn trix(
  function trix_inc (line 205) | pub fn trix_inc(
  function test_trix_calculation (line 241) | fn test_trix_calculation() {

FILE: kand/src/ta/ohlcv/typprice.rs
  function lookback (line 19) | pub const fn lookback() -> Result<usize, KandError> {
  function typprice (line 63) | pub fn typprice(
  function typprice_inc (line 128) | pub fn typprice_inc(
  function test_typprice_calculation (line 151) | fn test_typprice_calculation() {

FILE: kand/src/ta/ohlcv/vegas.rs
  function lookback (line 19) | pub const fn lookback() -> Result<usize, KandError> {
  function vegas (line 76) | pub fn vegas(
  function vegas_inc (line 174) | pub fn vegas_inc(

FILE: kand/src/ta/ohlcv/vwap.rs
  function lookback (line 30) | pub const fn lookback() -> Result<usize, KandError> {
  function vwap (line 92) | pub fn vwap(
  function vwap_inc (line 202) | pub fn vwap_inc(
  function test_vwap_calculation (line 228) | fn test_vwap_calculation() {

FILE: kand/src/ta/ohlcv/wclprice.rs
  function lookback (line 20) | pub const fn lookback() -> Result<usize, KandError> {
  function wclprice (line 67) | pub fn wclprice(
  function wclprice_inc (line 128) | pub fn wclprice_inc(
  function test_wclprice_calculation (line 150) | fn test_wclprice_calculation() {

FILE: kand/src/ta/ohlcv/willr.rs
  function lookback (line 27) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function willr (line 97) | pub fn willr(
  function willr_inc (line 211) | pub fn willr_inc(
  function test_willr_calculation (line 271) | fn test_willr_calculation() {

FILE: kand/src/ta/ohlcv/wma.rs
  function lookback (line 26) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function wma (line 77) | pub fn wma(input: &[TAFloat], opt_period: usize, output: &mut [TAFloat])...
  function wma_inc (line 162) | pub fn wma_inc(input_window: &[TAFloat], opt_period: usize) -> Result<TA...
  function test_wma_calculation (line 201) | fn test_wma_calculation() {

FILE: kand/src/ta/stats/correl.rs
  function lookback (line 24) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function correl (line 111) | pub fn correl(
  function correl_inc (line 308) | pub fn correl_inc(
  function test_correl_perfect_positive (line 388) | fn test_correl_perfect_positive() {
  function test_correl_perfect_negative (line 443) | fn test_correl_perfect_negative() {
  function test_correl_no_variance (line 475) | fn test_correl_no_variance() {
  function test_correl_lookback (line 507) | fn test_correl_lookback() {
  function test_talib_compatibility (line 523) | fn test_talib_compatibility() {

FILE: kand/src/ta/stats/max.rs
  function lookback (line 24) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function max (line 73) | pub fn max(
  function max_inc (line 162) | pub fn max_inc(
  function test_max_calculation (line 205) | fn test_max_calculation() {

FILE: kand/src/ta/stats/min.rs
  function lookback (line 24) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function min (line 79) | pub fn min(
  function min_inc (line 169) | pub fn min_inc(
  function test_min_calculation (line 214) | fn test_min_calculation() {

FILE: kand/src/ta/stats/stddev.rs
  function lookback (line 24) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function stddev (line 79) | pub fn stddev(
  function stddev_inc (line 165) | pub fn stddev_inc(
  function test_stddev_calculation (line 190) | fn test_stddev_calculation() {

FILE: kand/src/ta/stats/sum.rs
  function lookback (line 24) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function sum (line 77) | pub fn sum(
  function sum_inc (line 165) | pub fn sum_inc(
  function test_sum_calculation (line 188) | fn test_sum_calculation() {

FILE: kand/src/ta/stats/var.rs
  function lookback (line 25) | pub const fn lookback(opt_period: usize) -> Result<usize, KandError> {
  function var (line 92) | pub fn var(
  function var_inc (line 205) | pub fn var_inc(
  function test_var_calculation (line 252) | fn test_var_calculation() {

FILE: kand/src/ta/types.rs
  type MAType (line 25) | pub enum MAType {
  type MAType (line 41) | pub enum MAType {
  method default (line 63) | fn default() -> Self {
  type Signal (line 85) | pub enum Signal {
  type Signal (line 97) | pub enum Signal {
  method default (line 111) | fn default() -> Self {

FILE: scripts/gen_stub.py
  function generate_stub_file (line 9) | def generate_stub_file(package_name: str, output_path: str):
Condensed preview — 365 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,252K chars).
[
  {
    "path": ".gitattributes",
    "chars": 607,
    "preview": "# Basic settings\n* text=auto eol=lf\n\n# Source code files\n*.rs    text diff=rust\n*.toml  text diff=toml\n\n# Scripts and co"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 455,
    "preview": "# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where "
  },
  {
    "path": ".github/workflows/CI.yml",
    "chars": 5012,
    "preview": "# This file is autogenerated by maturin v1.9.3\n# To update, run\n#\n#    maturin generate-ci github\n#\nname: CI\n\non:\n  push"
  },
  {
    "path": ".github/workflows/publish-doc.yml",
    "chars": 1255,
    "preview": "name: Deploy Documentation\non:\n  push:\n    branches:\n      - master\n      - main\npermissions:\n  contents: write\njobs:\n  "
  },
  {
    "path": ".github/workflows/publish-docker.yml",
    "chars": 1473,
    "preview": "name: Docker Package\n\non:\n  push:\n    tags: [ 'v*.*.*' ]\n\nenv:\n  REGISTRY: ghcr.io\n  IMAGE_NAME: ${{ github.repository }"
  },
  {
    "path": ".github/workflows/publish-rust.yml",
    "chars": 491,
    "preview": "name: Publish to crates.io\n\non:\n  push:\n    tags:\n      - 'v*.*.*'\n\nenv:\n  CARGO_TERM_COLOR: always\n\njobs:\n  publish:\n  "
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 1240,
    "preview": "name: Automatic Release\n\non:\n  push:\n    tags:\n      - 'v*.*.*'\n\npermissions:\n  contents: write  # Grants permission to "
  },
  {
    "path": ".github/workflows/rust.yml",
    "chars": 198,
    "preview": "name: Rust\n\non:\n  push:\n    branches: [ \"main\" ]\n  pull_request:\n    branches: [ \"main\" ]\n\nenv:\n  CARGO_TERM_COLOR: alwa"
  },
  {
    "path": ".github/workflows/stale.yml",
    "chars": 176,
    "preview": "name: Close Stale Issues and PRs\n\non:\n  schedule:\n    - cron: \"30 1 * * *\"\n  workflow_dispatch:\n\njobs:\n  close-stale:\n  "
  },
  {
    "path": ".gitignore",
    "chars": 3965,
    "preview": "# Generated by Cargo\n# will have compiled files and executables\ndebug/\ntarget/\n\n# Remove Cargo.lock from gitignore if cr"
  },
  {
    "path": ".python-version",
    "chars": 5,
    "preview": "3.11\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 2398,
    "preview": "# Changelog\n\nThis document records all significant updates and changes to the Kand project.\n\n## [unreleased]\n\n### 🚀 Feat"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 6719,
    "preview": "# Contributing to Kand\n\nFirst off, thank you for considering contributing to Kand! It's people like you that make Kand s"
  },
  {
    "path": "Cargo.toml",
    "chars": 957,
    "preview": "[workspace]\nmembers = [\"kand\", \"kand-py\", \"kand-wasm\"]\n# Only check / build main crates by default (check all with `--wo"
  },
  {
    "path": "Dockerfile",
    "chars": 2252,
    "preview": "FROM --platform=$BUILDPLATFORM python:3.12-slim-bullseye AS build\nENV HOME=\"/root\"\nWORKDIR $HOME\n\n# Install build depend"
  },
  {
    "path": "LICENSE-APACHE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "LICENSE-MIT",
    "chars": 1064,
    "preview": "MIT License\n\nCopyright (c) 2025 Kand TA\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof"
  },
  {
    "path": "Makefile",
    "chars": 2438,
    "preview": "# Makefile for Rust project using Cargo\n\n.PHONY: all\nall: pre-commit\n\n# Build the project with all features enabled in r"
  },
  {
    "path": "README.md",
    "chars": 13618,
    "preview": "<h1 align=\"center\">\n  <img src=\"docs/assets/logo.png\" alt=\"Kand Logo\" width=\"250\">\n</h1>\n<div align=\"center\">\n  <a href="
  },
  {
    "path": "cliff.toml",
    "chars": 3315,
    "preview": "# git-cliff ~ default configuration file\n# https://git-cliff.org/docs/configuration\n#\n# Lines starting with \"#\" are comm"
  },
  {
    "path": "clippy.toml",
    "chars": 124,
    "preview": "too-many-arguments-threshold = 20\ntype-complexity-threshold = 500\nallow-expect-in-tests = true\nallow-unwrap-in-tests = t"
  },
  {
    "path": "docs/about.md",
    "chars": 2888,
    "preview": "# About Kand\n\n## The Motivation\n\nTALib has long been a cornerstone for financial indicator calculations, valued for its "
  },
  {
    "path": "docs/advance.md",
    "chars": 3276,
    "preview": "# Advanced Configuration Guide\n\nThis guide explains how to customize `kand` for numerical precision, optimization, and c"
  },
  {
    "path": "docs/api.md",
    "chars": 10,
    "preview": "\n::: kand\n"
  },
  {
    "path": "docs/install.md",
    "chars": 1793,
    "preview": "# Installation Guide\n\nGet started with `kand` through Python or Docker. This guide covers all installation methods and s"
  },
  {
    "path": "docs/performance.md",
    "chars": 6001,
    "preview": "# Performance Testing\n\n## Introduction\n\nThis document showcases the performance testing results for Exponential Moving A"
  },
  {
    "path": "kand/Cargo.toml",
    "chars": 1346,
    "preview": "[package]\nname = \"kand\"\nversion = \"0.2.2\"\nedition = \"2024\"\nauthors = [\"CtrlX <gitctrlx@gmail.com>\"]\nreadme = \"../README."
  },
  {
    "path": "kand/benches/bench_main.rs",
    "chars": 2859,
    "preview": "use criterion::criterion_main;\n\nmod benchmarks;\nmod helper;\n\ncriterion_main! {\n    // OHLCV benchmarks\n    benchmarks::o"
  },
  {
    "path": "kand/benches/benchmarks/helper.rs",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand/benches/benchmarks/mod.rs",
    "chars": 50,
    "preview": "pub mod ohlcv;\npub mod stats;\n\n// pub mod helper;\n"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/ad_bench.rs",
    "chars": 1127,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::ad::ad;\nuse std::hint::black_box;\n\nuse crate:"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/adosc_bench.rs",
    "chars": 2000,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::adosc::adosc;\nuse std::hint::black_box;\n\nuse "
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/adr_bench.rs",
    "chars": 1167,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::adr::adr;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/adx_bench.rs",
    "chars": 1656,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::adx::adx;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/adxr_bench.rs",
    "chars": 1766,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::adxr::adxr;\nuse std::hint::black_box;\n\nuse cr"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/aroon_bench.rs",
    "chars": 1789,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ta::ohlcv::aroon::aroon;\nuse std::hint::black_box;\n\n"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/aroonosc_bench.rs",
    "chars": 1687,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::aroonosc::aroonosc;\nuse std::hint::black_box;"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/atr_bench.rs",
    "chars": 1236,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::atr::atr;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/bbands_bench.rs",
    "chars": 1781,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::bbands::bbands;\nuse std::hint::black_box;\n\nus"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/bop_bench.rs",
    "chars": 1057,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::bop::bop;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/cci_bench.rs",
    "chars": 1600,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::cci::cci;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/cdl_doji_bench.rs",
    "chars": 1165,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::cdl_doji::cdl_doji;\nuse std::hint::black_box;"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/cdl_dragonfly_doji_bench.rs",
    "chars": 1189,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::cdl_dragonfly_doji::cdl_dragonfly_doji;\nuse s"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/cdl_gravestone_doji_bench.rs",
    "chars": 1195,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::cdl_gravestone_doji::cdl_gravestone_doji;\nuse"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/cdl_hammer_bench.rs",
    "chars": 1278,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::cdl_hammer::cdl_hammer;\nuse std::hint::black_"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/cdl_inverted_hammer_bench.rs",
    "chars": 1607,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::cdl_inverted_hammer::cdl_inverted_hammer;\nuse"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/cdl_long_shadow_bench.rs",
    "chars": 1583,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::cdl_long_shadow::cdl_long_shadow;\nuse std::hi"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/cdl_marubozu_bench.rs",
    "chars": 1566,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::cdl_marubozu::cdl_marubozu;\nuse std::hint::bl"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/dema_bench.rs",
    "chars": 1246,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::dema::dema;\nuse std::hint::black_box;\n\nuse cr"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/dx_bench.rs",
    "chars": 1648,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::dx::dx;\nuse std::hint::black_box;\n\nuse crate:"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/ecl_bench.rs",
    "chars": 1853,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::ecl::ecl;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/ema_bench.rs",
    "chars": 1101,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::ema::ema;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/macd_bench.rs",
    "chars": 2082,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::macd::macd;\nuse std::hint::black_box;\n\nuse cr"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/medprice_bench.rs",
    "chars": 905,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::medprice::medprice;\nuse std::hint::black_box;"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/mfi_bench.rs",
    "chars": 1816,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::mfi::mfi;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/midpoint_bench.rs",
    "chars": 1301,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::midpoint::midpoint;\nuse std::hint::black_box;"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/midprice_bench.rs",
    "chars": 1418,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::midprice::midprice;\nuse std::hint::black_box;"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/minus_di_bench.rs",
    "chars": 1532,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::minus_di::minus_di;\nuse std::hint::black_box;"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/minus_dm_bench.rs",
    "chars": 1197,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::minus_dm::minus_dm;\nuse std::hint::black_box;"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/mod.rs",
    "chars": 1208,
    "preview": "pub mod ad_bench;\npub mod adosc_bench;\npub mod adr_bench;\npub mod adx_bench;\npub mod adxr_bench;\npub mod aroon_bench;\npu"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/mom_bench.rs",
    "chars": 945,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::mom::mom;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/natr_bench.rs",
    "chars": 1242,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::natr::natr;\nuse std::hint::black_box;\n\nuse cr"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/obv_bench.rs",
    "chars": 874,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::obv::obv;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/plus_di_bench.rs",
    "chars": 1522,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::plus_di::plus_di;\nuse std::hint::black_box;\n\n"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/plus_dm_bench.rs",
    "chars": 1191,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::plus_dm::plus_dm;\nuse std::hint::black_box;\n\n"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/rma_bench.rs",
    "chars": 945,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::rma::rma;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/roc_bench.rs",
    "chars": 945,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::roc::roc;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/rocp_bench.rs",
    "chars": 951,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::rocp::rocp;\nuse std::hint::black_box;\n\nuse cr"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/rocr100_bench.rs",
    "chars": 997,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::rocr100::rocr100;\nuse std::hint::black_box;\n\n"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/rocr_bench.rs",
    "chars": 951,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::rocr::rocr;\nuse std::hint::black_box;\n\nuse cr"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/rsi_bench.rs",
    "chars": 1280,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::rsi::rsi;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/sar_bench.rs",
    "chars": 1225,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::sar::sar;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/sma_bench.rs",
    "chars": 945,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::sma::sma;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/stoch_bench.rs",
    "chars": 2006,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::stoch::stoch;\nuse std::hint::black_box;\n\nuse "
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/supertrend_bench.rs",
    "chars": 1677,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::supertrend::supertrend;\nuse std::hint::black_"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/t3_bench.rs",
    "chars": 1823,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::t3::t3;\nuse std::hint::black_box;\n\nuse crate:"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/tema_bench.rs",
    "chars": 1339,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::tema::tema;\nuse std::hint::black_box;\n\nuse cr"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/trange_bench.rs",
    "chars": 969,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::trange::trange;\nuse std::hint::black_box;\n\nus"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/trima_bench.rs",
    "chars": 1149,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::trima::trima;\nuse std::hint::black_box;\n\nuse "
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/trix_bench.rs",
    "chars": 1341,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::trix::trix;\nuse std::hint::black_box;\n\nuse cr"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/typprice_bench.rs",
    "chars": 1017,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::typprice::typprice;\nuse std::hint::black_box;"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/vegas_bench.rs",
    "chars": 1173,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::vegas::vegas;\nuse std::hint::black_box;\n\nuse "
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/vwap_bench.rs",
    "chars": 1256,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::vwap::vwap;\nuse std::hint::black_box;\n\nuse cr"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/wclprice_bench.rs",
    "chars": 984,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::wclprice::wclprice;\nuse std::hint::black_box;"
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/willr_bench.rs",
    "chars": 1487,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::willr::willr;\nuse std::hint::black_box;\n\nuse "
  },
  {
    "path": "kand/benches/benchmarks/ohlcv/wma_bench.rs",
    "chars": 945,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::ohlcv::wma::wma;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/other/mod.rs",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand/benches/benchmarks/stats/beta_bench.rs",
    "chars": 939,
    "preview": "use criterion::{black_box, criterion_group, BenchmarkId, Criterion};\nuse kand::ohlcv::beta::beta;\n\nuse crate::helpers::g"
  },
  {
    "path": "kand/benches/benchmarks/stats/correl_bench.rs",
    "chars": 965,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse std::hint::black_box;\nuse kand::stats::correl::correl;\n\nus"
  },
  {
    "path": "kand/benches/benchmarks/stats/max_bench.rs",
    "chars": 945,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::stats::max::max;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/stats/min_bench.rs",
    "chars": 945,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::stats::min::min;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/stats/mod.rs",
    "chars": 98,
    "preview": "pub mod max_bench;\npub mod min_bench;\npub mod stddev_bench;\npub mod sum_bench;\npub mod var_bench;\n"
  },
  {
    "path": "kand/benches/benchmarks/stats/stddev_bench.rs",
    "chars": 1284,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::stats::stddev::stddev;\nuse std::hint::black_box;\n\nus"
  },
  {
    "path": "kand/benches/benchmarks/stats/sum_bench.rs",
    "chars": 945,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::stats::sum::sum;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/benchmarks/stats/var_bench.rs",
    "chars": 1266,
    "preview": "use criterion::{BenchmarkId, Criterion, criterion_group};\nuse kand::stats::var::var;\nuse std::hint::black_box;\n\nuse crat"
  },
  {
    "path": "kand/benches/helper.rs",
    "chars": 896,
    "preview": "use kand::TAFloat;\nuse rand::Rng;\n\n/// Generate a vector of floating point values simulating price movements\n///\n/// # P"
  },
  {
    "path": "kand/src/error.rs",
    "chars": 802,
    "preview": "#[derive(thiserror::Error, Debug)]\npub enum KandError {\n    #[error(\"Invalid parameter value provided to the function\")]"
  },
  {
    "path": "kand/src/helper.rs",
    "chars": 5730,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Find the number of bars back to the lowest value in a lookback period\n///\n/// # Ar"
  },
  {
    "path": "kand/src/lib.rs",
    "chars": 5415,
    "preview": "//! # Kand\n//!\n//! A high-performance technical analysis library for Rust, inspired by TA-Lib.\n//!\n//! ## Overview\n//!\n/"
  },
  {
    "path": "kand/src/ta/mod.rs",
    "chars": 46,
    "preview": "pub mod ohlcv;\npub mod stats;\n\npub mod types;\n"
  },
  {
    "path": "kand/src/ta/ohlcv/ad.rs",
    "chars": 11644,
    "preview": "use crate::{KandError, TAFloat, TAPeriod};\n\n/// Returns the lookback period required for A/D calculation.\n///\n/// The A/"
  },
  {
    "path": "kand/src/ta/ohlcv/adosc.rs",
    "chars": 17656,
    "preview": "use super::{ad, ema};\nuse crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for A/D Oscillator calc"
  },
  {
    "path": "kand/src/ta/ohlcv/adr.rs",
    "chars": 12518,
    "preview": "use super::sma;\nuse crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for Average Daily Range (ADR)"
  },
  {
    "path": "kand/src/ta/ohlcv/adx.rs",
    "chars": 14048,
    "preview": "use super::dx;\nuse crate::{KandError, TAFloat};\n\n/// Calculate the lookback period required for ADX calculation\n///\n/// "
  },
  {
    "path": "kand/src/ta/ohlcv/adxr.rs",
    "chars": 14186,
    "preview": "use super::adx;\nuse crate::{KandError, TAFloat};\n\n/// Calculates the lookback period required for ADXR calculation\n///\n/"
  },
  {
    "path": "kand/src/ta/ohlcv/aroon.rs",
    "chars": 15582,
    "preview": "use crate::{\n    TAFloat,\n    error::KandError,\n    helper::{highest_bars, lowest_bars},\n};\n\n/// Returns the lookback pe"
  },
  {
    "path": "kand/src/ta/ohlcv/aroonosc.rs",
    "chars": 12496,
    "preview": "use crate::{\n    TAFloat,\n    error::KandError,\n    helper::{highest_bars, lowest_bars},\n};\n\n/// Returns the lookback pe"
  },
  {
    "path": "kand/src/ta/ohlcv/atr.rs",
    "chars": 9399,
    "preview": "use super::trange;\nuse crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for ATR calculation.\n///\n/"
  },
  {
    "path": "kand/src/ta/ohlcv/bbands.rs",
    "chars": 15102,
    "preview": "use crate::{\n    KandError, TAFloat,\n    ta::{ohlcv::sma, stats::var},\n};\n\n/// Returns the lookback period required for "
  },
  {
    "path": "kand/src/ta/ohlcv/bop.rs",
    "chars": 7861,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for Balance of Power (BOP) calculation.\n///\n/"
  },
  {
    "path": "kand/src/ta/ohlcv/cci.rs",
    "chars": 13069,
    "preview": "use super::{sma, typprice};\nuse crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for CCI calculati"
  },
  {
    "path": "kand/src/ta/ohlcv/cdl_doji.rs",
    "chars": 12153,
    "preview": "use crate::{\n    KandError, TAFloat, TAInt,\n    helper::{lower_shadow_length, real_body_length, upper_shadow_length},\n  "
  },
  {
    "path": "kand/src/ta/ohlcv/cdl_dragonfly_doji.rs",
    "chars": 10038,
    "preview": "use crate::{\n    KandError, TAFloat, TAInt,\n    helper::{real_body_length, upper_shadow_length},\n    types::Signal,\n};\n\n"
  },
  {
    "path": "kand/src/ta/ohlcv/cdl_gravestone_doji.rs",
    "chars": 8791,
    "preview": "use crate::{\n    KandError, TAFloat, TAInt,\n    helper::{lower_shadow_length, real_body_length},\n    types::Signal,\n};\n\n"
  },
  {
    "path": "kand/src/ta/ohlcv/cdl_hammer.rs",
    "chars": 13350,
    "preview": "use crate::{\n    KandError, TAFloat, TAInt,\n    helper::{lower_shadow_length, period_to_k, real_body_length, upper_shado"
  },
  {
    "path": "kand/src/ta/ohlcv/cdl_inverted_hammer.rs",
    "chars": 12676,
    "preview": "use crate::{\n    KandError, TAFloat, TAInt,\n    helper::{lower_shadow_length, period_to_k, real_body_length, upper_shado"
  },
  {
    "path": "kand/src/ta/ohlcv/cdl_long_shadow.rs",
    "chars": 12838,
    "preview": "use crate::{\n    KandError, TAFloat, TAInt,\n    helper::{lower_shadow_length, period_to_k, real_body_length, upper_shado"
  },
  {
    "path": "kand/src/ta/ohlcv/cdl_marubozu.rs",
    "chars": 14486,
    "preview": "use crate::{\n    KandError, TAFloat, TAInt,\n    helper::{lower_shadow_length, period_to_k, real_body_length, upper_shado"
  },
  {
    "path": "kand/src/ta/ohlcv/dema.rs",
    "chars": 9480,
    "preview": "use crate::{TAFloat, error::KandError, helper::period_to_k};\n\n/// Returns the lookback period required for DEMA calculat"
  },
  {
    "path": "kand/src/ta/ohlcv/dx.rs",
    "chars": 12221,
    "preview": "use super::{minus_di, plus_di};\nuse crate::{KandError, TAFloat};\n\n/// Calculate the lookback period required for DX calc"
  },
  {
    "path": "kand/src/ta/ohlcv/ecl.rs",
    "chars": 11818,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for Expanded Camarilla Levels (ECL) calculati"
  },
  {
    "path": "kand/src/ta/ohlcv/ema.rs",
    "chars": 8483,
    "preview": "use crate::{KandError, TAFloat, helper::period_to_k};\n\n/// Returns the lookback period required for EMA calculation.\n///"
  },
  {
    "path": "kand/src/ta/ohlcv/ha.rs",
    "chars": 9332,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for Heikin-Ashi calculation\n///\n/// # Descrip"
  },
  {
    "path": "kand/src/ta/ohlcv/macd.rs",
    "chars": 9288,
    "preview": "use super::ema;\nuse crate::{KandError, TAFloat};\n\n/// Calculate the lookback period required for MACD calculation\n///\n//"
  },
  {
    "path": "kand/src/ta/ohlcv/medprice.rs",
    "chars": 5330,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Calculates the lookback period required for MEDPRICE calculation.\n///\n/// # Descri"
  },
  {
    "path": "kand/src/ta/ohlcv/mfi.rs",
    "chars": 9243,
    "preview": "use crate::{KandError, TAFloat, ta::ohlcv::typprice};\n\n/// Calculates the lookback period required for Money Flow Index "
  },
  {
    "path": "kand/src/ta/ohlcv/midpoint.rs",
    "chars": 8929,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Calculates the lookback period required for Midpoint calculation.\n///\n/// # Descri"
  },
  {
    "path": "kand/src/ta/ohlcv/midprice.rs",
    "chars": 8766,
    "preview": "use crate::{\n    TAFloat,\n    error::KandError,\n    helper::{highest_bars, lowest_bars},\n};\n\n/// Calculates the lookback"
  },
  {
    "path": "kand/src/ta/ohlcv/minus_di.rs",
    "chars": 13887,
    "preview": "use super::trange;\nuse crate::{KandError, TAFloat};\n\n/// Calculates the lookback period required for -DI (Minus Directio"
  },
  {
    "path": "kand/src/ta/ohlcv/minus_dm.rs",
    "chars": 9804,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Calculates the lookback period required for Minus Directional Movement (-DM) calcu"
  },
  {
    "path": "kand/src/ta/ohlcv/mod.rs",
    "chars": 890,
    "preview": "pub mod ad;\npub mod adosc;\npub mod adr;\npub mod adx;\npub mod adxr;\npub mod aroon;\npub mod aroonosc;\npub mod atr;\npub mod"
  },
  {
    "path": "kand/src/ta/ohlcv/mom.rs",
    "chars": 6376,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for Momentum (MOM) calculation\n///\n/// # Desc"
  },
  {
    "path": "kand/src/ta/ohlcv/natr.rs",
    "chars": 9230,
    "preview": "use super::atr;\nuse crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for NATR calculation\n///\n/// "
  },
  {
    "path": "kand/src/ta/ohlcv/obv.rs",
    "chars": 6732,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for On Balance Volume (OBV) calculation\n///\n/"
  },
  {
    "path": "kand/src/ta/ohlcv/plus_di.rs",
    "chars": 13342,
    "preview": "use super::trange;\nuse crate::{KandError, TAFloat};\n\n/// Returns the lookback period needed for +DI calculation\n///\n/// "
  },
  {
    "path": "kand/src/ta/ohlcv/plus_dm.rs",
    "chars": 9593,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for Plus DM calculation\n///\n/// # Description"
  },
  {
    "path": "kand/src/ta/ohlcv/rma.rs",
    "chars": 11402,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Calculates the lookback period required for RMA calculation.\n///\n/// Returns the n"
  },
  {
    "path": "kand/src/ta/ohlcv/roc.rs",
    "chars": 7330,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for ROC (Rate of Change) calculation\n///\n/// "
  },
  {
    "path": "kand/src/ta/ohlcv/rocp.rs",
    "chars": 6672,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Returns the lookback period for Rate of Change Percentage (ROCP) calculation.\n///\n"
  },
  {
    "path": "kand/src/ta/ohlcv/rocr.rs",
    "chars": 6209,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Calculates the lookback period required for Rate of Change Ratio (ROCR) calculatio"
  },
  {
    "path": "kand/src/ta/ohlcv/rocr100.rs",
    "chars": 6747,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Calculates the lookback period required for ROCR100 (Rate of Change Ratio * 100) c"
  },
  {
    "path": "kand/src/ta/ohlcv/rsi.rs",
    "chars": 11748,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Calculates the lookback period required for RSI (Relative Strength Index) calculat"
  },
  {
    "path": "kand/src/ta/ohlcv/sar.rs",
    "chars": 13509,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Returns the lookback period required by the Parabolic SAR indicator.\n///\n/// # Des"
  },
  {
    "path": "kand/src/ta/ohlcv/sma.rs",
    "chars": 7394,
    "preview": "use crate::{KandError, TAFloat, TAPeriod};\n\n/// Returns the lookback period for Simple Moving Average (SMA) without inpu"
  },
  {
    "path": "kand/src/ta/ohlcv/stoch.rs",
    "chars": 9033,
    "preview": "use crate::{KandError, TAFloat, ta::ohlcv::sma};\n\n/// Calculates the lookback period required for Stochastic Oscillator "
  },
  {
    "path": "kand/src/ta/ohlcv/supertrend.rs",
    "chars": 15294,
    "preview": "use super::atr;\nuse crate::{KandError, TAFloat, TAInt, types::Signal};\n\n/// Returns the lookback period required for Sup"
  },
  {
    "path": "kand/src/ta/ohlcv/t3.rs",
    "chars": 15582,
    "preview": "use crate::{TAFloat, error::KandError};\n\n/// Calculates the lookback period required for T3 indicator\n///\n/// # Argument"
  },
  {
    "path": "kand/src/ta/ohlcv/tema.rs",
    "chars": 9731,
    "preview": "use crate::{KandError, TAFloat, ta::ohlcv::ema};\n\n/// Calculates the lookback period required for Triple Exponential Mov"
  },
  {
    "path": "kand/src/ta/ohlcv/trange.rs",
    "chars": 6757,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for True Range (TR) calculation\n///\n/// # Des"
  },
  {
    "path": "kand/src/ta/ohlcv/trima.rs",
    "chars": 12807,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for Triangular Moving Average (TRIMA) calcula"
  },
  {
    "path": "kand/src/ta/ohlcv/trix.rs",
    "chars": 9920,
    "preview": "use super::{ema, roc};\nuse crate::{KandError, TAFloat};\n\n/// Calculates the lookback period required for TRIX calculatio"
  },
  {
    "path": "kand/src/ta/ohlcv/typprice.rs",
    "chars": 6182,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for Typical Price calculation.\n///\n/// Determ"
  },
  {
    "path": "kand/src/ta/ohlcv/vegas.rs",
    "chars": 6391,
    "preview": "use super::ema;\nuse crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for VEGAS (Volume and EMA Gui"
  },
  {
    "path": "kand/src/ta/ohlcv/vwap.rs",
    "chars": 8943,
    "preview": "use super::typprice;\nuse crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for VWAP calculation.\n//"
  },
  {
    "path": "kand/src/ta/ohlcv/wclprice.rs",
    "chars": 6000,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Returns the lookback period required for Weighted Close Price (WCLPRICE) calculati"
  },
  {
    "path": "kand/src/ta/ohlcv/willr.rs",
    "chars": 11275,
    "preview": "use crate::{\n    EPSILON, KandError, TAFloat,\n    helper::{highest_bars, lowest_bars},\n};\n\n/// Returns the lookback peri"
  },
  {
    "path": "kand/src/ta/ohlcv/wma.rs",
    "chars": 7471,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Calculates the lookback period required for Weighted Moving Average (WMA).\n///\n///"
  },
  {
    "path": "kand/src/ta/other/mod.rs",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand/src/ta/stats/alpha.rs",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand/src/ta/stats/beta.rs",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand/src/ta/stats/calmar.rs",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand/src/ta/stats/correl.rs",
    "chars": 19625,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Calculates the lookback period required for Correlation calculation.\n///\n/// The l"
  },
  {
    "path": "kand/src/ta/stats/drawdown.rs",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand/src/ta/stats/fv.rs",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand/src/ta/stats/kelly.rs",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand/src/ta/stats/max.rs",
    "chars": 7374,
    "preview": "use crate::{EPSILON, KandError, TAFloat};\n\n/// Calculates the lookback period required for Maximum Value calculation.\n//"
  },
  {
    "path": "kand/src/ta/stats/min.rs",
    "chars": 7861,
    "preview": "use crate::{EPSILON, KandError, TAFloat};\n\n/// Calculates the lookback period required for Minimum Value calculation.\n//"
  },
  {
    "path": "kand/src/ta/stats/mod.rs",
    "chars": 101,
    "preview": "// pub mod beta;\npub mod correl;\npub mod max;\npub mod min;\npub mod stddev;\npub mod sum;\npub mod var;\n"
  },
  {
    "path": "kand/src/ta/stats/nper.rs",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand/src/ta/stats/ret.rs",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand/src/ta/stats/sharpe.rs",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand/src/ta/stats/sortino.rs",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand/src/ta/stats/stddev.rs",
    "chars": 7881,
    "preview": "use crate::{KandError, TAFloat, ta::stats::var};\n\n/// Calculates the lookback period required for Standard Deviation cal"
  },
  {
    "path": "kand/src/ta/stats/sum.rs",
    "chars": 6976,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Calculates the lookback period required for Sum calculation.\n///\n/// The lookback "
  },
  {
    "path": "kand/src/ta/stats/var.rs",
    "chars": 9961,
    "preview": "use crate::{KandError, TAFloat};\n\n/// Calculates the lookback period required for Variance calculation.\n///\n/// # Descri"
  },
  {
    "path": "kand/src/ta/stats/winrate.rs",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand/src/ta/types.rs",
    "chars": 3167,
    "preview": "use num_enum::{IntoPrimitive, TryFromPrimitive};\n\n/// Moving Average types for technical analysis.\n///\n/// The integer r"
  },
  {
    "path": "kand-py/.gitignore",
    "chars": 686,
    "preview": "/target\n\n# Byte-compiled / optimized / DLL files\n__pycache__/\n.pytest_cache/\n*.py[cod]\n\n# C extensions\n*.so\n\n# Distribut"
  },
  {
    "path": "kand-py/Cargo.toml",
    "chars": 1313,
    "preview": "[package]\nname = \"kand-py\"\nversion = \"0.2.2\"\nedition = \"2024\"\nreadme = \"../README.md\"\nauthors = [\"CtrlX <gitctrlx@gmail."
  },
  {
    "path": "kand-py/python/benches/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand-py/python/benches/bench_ema.py",
    "chars": 5711,
    "preview": "import numpy as np\nimport talib\nfrom kand import ema\nimport time\nimport matplotlib.pyplot as plt\n\n# Set modern, professi"
  },
  {
    "path": "kand-py/python/benches/bench_ema_incremental.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand-py/python/benches/bench_ema_incremental_mt.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand-py/python/benches/bench_ema_mt.py",
    "chars": 6446,
    "preview": "import numpy as np\nimport talib\nfrom kand import ema\nimport time\nimport matplotlib.pyplot as plt\nfrom concurrent.futures"
  },
  {
    "path": "kand-py/python/benches/ema.py",
    "chars": 5051,
    "preview": "import numpy as np\nimport pandas as pd\nimport talib\nimport kand\nimport time\nfrom typing import List, Dict\nimport matplot"
  },
  {
    "path": "kand-py/python/examples/sma.py",
    "chars": 383,
    "preview": "import numpy as np\nfrom kand import sma\nimport time\n\ndata = np.array([float(i) for i in range(10_000_000)])\n\nstart_time "
  },
  {
    "path": "kand-py/python/examples/sma_thread.py",
    "chars": 947,
    "preview": "import numpy as np\nimport time\nfrom concurrent.futures import ThreadPoolExecutor\nfrom kand import sma\n\n# Generate test d"
  },
  {
    "path": "kand-py/python/kand/__init__.py",
    "chars": 21,
    "preview": "from ._kand import *\n"
  },
  {
    "path": "kand-py/python/kand/_kand.pyi",
    "chars": 107195,
    "preview": "# Auto-generated stub file for kand\n\"\"\"\nType hints and function signatures stub file for IDE autocompletion.\nAuto-genera"
  },
  {
    "path": "kand-py/python/kand/py.typed",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand-py/src/helper.rs",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "kand-py/src/lib.rs",
    "chars": 8940,
    "preview": "use pyo3::prelude::*;\n\npub mod ta;\n\n/// A Python module implemented in Rust.\n#[rustfmt::skip]\n#[pymodule]\n#[pyo3(name = "
  },
  {
    "path": "kand-py/src/ta/mod.rs",
    "chars": 30,
    "preview": "pub mod ohlcv;\npub mod stats;\n"
  },
  {
    "path": "kand-py/src/ta/ohlcv/ad.rs",
    "chars": 3483,
    "preview": "use kand::{TAFloat, ohlcv::ad};\nuse numpy::{IntoPyArray, PyArray1, PyReadonlyArray1};\nuse pyo3::prelude::*;\n\n/// Compute"
  },
  {
    "path": "kand-py/src/ta/ohlcv/adosc.rs",
    "chars": 5067,
    "preview": "use kand::{TAFloat, ohlcv::adosc};\nuse numpy::{IntoPyArray, PyArray1, PyReadonlyArray1};\nuse pyo3::prelude::*;\n\n/// Calc"
  },
  {
    "path": "kand-py/src/ta/ohlcv/adr.rs",
    "chars": 3175,
    "preview": "use kand::{TAFloat, ohlcv::adr};\nuse numpy::{IntoPyArray, PyArray1, PyReadonlyArray1};\nuse pyo3::prelude::*;\n\n/// Comput"
  },
  {
    "path": "kand-py/src/ta/ohlcv/adx.rs",
    "chars": 4908,
    "preview": "use kand::{TAFloat, ohlcv::adx};\nuse numpy::{IntoPyArray, PyArray1, PyReadonlyArray1};\nuse pyo3::prelude::*;\n\n/// Calcul"
  },
  {
    "path": "kand-py/src/ta/ohlcv/adxr.rs",
    "chars": 5092,
    "preview": "use kand::{TAFloat, ohlcv::adxr};\nuse numpy::{IntoPyArray, PyArray1, PyReadonlyArray1};\nuse pyo3::prelude::*;\n\n/// Calcu"
  },
  {
    "path": "kand-py/src/ta/ohlcv/aroon.rs",
    "chars": 4535,
    "preview": "use kand::{TAFloat, ohlcv::aroon};\nuse numpy::{IntoPyArray, PyArray1, PyReadonlyArray1};\nuse pyo3::prelude::*;\n\n/// Calc"
  },
  {
    "path": "kand-py/src/ta/ohlcv/aroonosc.rs",
    "chars": 4390,
    "preview": "use kand::{TAFloat, ohlcv::aroonosc};\nuse numpy::{IntoPyArray, PyArray1, PyReadonlyArray1};\nuse pyo3::prelude::*;\n\n/// C"
  }
]

// ... and 165 more files (download for full content)

About this extraction

This page contains the full source code of the kand-ta/kand GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 365 files (1.1 MB), approximately 348.8k tokens, and a symbol index with 612 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!