Component · L2

TA Indicators

github.com/juanmmm21/ta-indicators-from-scratch

NumPy-vectorized technical indicators implemented from scratch without third-party TA libraries.

Lines
623
Files
22
Test files
6
Commits
15
Started
29 Jun 2026
Last commit
6 Jul 2026
  • Python 100%

● Where it sits

Layer 2 of Quant — analytics.

Fed by

Lakehouse

Feeds into

Alpha Signals

Same layer

Alpha Signals

Vectorized technical analysis library that implements classic indicators from scratch with NumPy — no TA-Lib, pandas-ta, or third-party dependencies. Fourth module of the quant-core-infra ecosystem.

Repository: github.com/juanmmm21/ta-indicators-from-scratch

What it is and what problem it solves

Indicator libraries (TA-Lib, etc.) are black boxes: they return a number without the developer understanding the exact math. In a quantitative portfolio that's a problem: you can't audit, optimize, or explain the signals.

This project implements the formulas explicitly using vectorized NumPy operations:

  • You know exactly what happens in each warmup window
  • You can compose indicators into your own pipelines
  • Performance stays at C level thanks to vectorization

Consumes OHLCV candles from market-data-lakehouse and feeds alpha-signal-generator.


Role in quant-core-infra

market-data-lakehouse ──► OHLCV candles ──► ta-indicators-from-scratch ──► indicators
                                                    │
                                          alpha-signal-generator

Translates historical price into statistical features that strategies evaluate bar by bar.


Supported indicators

IndicatorFunctionDefault parametersKey formula
SMASimple moving averageperiod 20Arithmetic mean of N closes
EMAExponential moving averageperiod 20α = 2/(N+1), SMA seed
RSIRelative strength indexperiod 14Wilder's smoothing over gains/losses
MACDConvergence/divergence12 / 26 / 9Fast EMA − slow EMA, signal EMA
BollingerVolatility bandsperiod 20, σ 2.0Rolling SMA ± k·σ

All return NaN during the warmup window until enough candles have accumulated.


How it works

  1. Input: float64 arrays or JSONL with OHLCV fields.
  2. Container: OhlcvSeries validates lengths and finite values.
  3. Calculation: each indicator is a pure ndarray → ndarray function.
  4. Engine: TechnicalAnalysisEngine orchestrates all indicators over the same series.
  5. Output: IndicatorResult with arrays aligned by candle index.
  6. CLI: serializes to JSON with null wherever there's a NaN.

Architecture

OHLCV candles (JSONL / arrays)
        │
        ▼
OhlcvSeries
        │
        ▼
TechnicalAnalysisEngine
   ├─ sma / ema / rsi
   ├─ macd (line, signal, histogram)
   └─ bollinger_bands (mean, upper, lower)
        │
        ▼
IndicatorResult

Components

ModuleResponsibility
series.pyOHLCV container and record parsing
indicators/sma.pySMA via convolution + rolling std
indicators/ema.pyEMA with SMA seed
indicators/rsi.pyWilder RSI
indicators/macd.pyFull MACD stack
indicators/bollinger.pyBands around SMA
engine.pyMulti-indicator orchestration
pipeline.pyJSONL ingestion + serialization

Technical decisions

  • float64 for statistical math (acceptable for pure TA per ecosystem rules)
  • No pandas / TA-Lib — minimal dependency (NumPy only)
  • Explicit NaN — downstream strategies can filter warmup
  • MACD: the signal is calculated only over the finite portion of the MACD line

Requirements

  • Python 3.11+

Installation

cd ta-indicators-from-scratch
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

CLI usage

# All indicators
ta-indicators-from-scratch compute \
  --input samples/btcusdt_1m_candles.jsonl \
  --indicator all

# RSI only with custom period
ta-indicators-from-scratch compute \
  --input samples/btcusdt_1m_candles.jsonl \
  --indicator rsi \
  --rsi-period 14 \
  --output indicators.json

Configurable parameters

FlagIndicatorDefault
--sma-periodSMA20
--ema-periodEMA20
--rsi-periodRSI14
--macd-fast/slow/signalMACD12 / 26 / 9
--bollinger-period/stdBollinger20 / 2.0

Candle JSONL format

{
  "open": 100.5,
  "high": 101.0,
  "low": 99.5,
  "close": 100.8,
  "volume": 12.0
}

Programmatic usage

import numpy as np

from ta_indicators_from_scratch import OhlcvSeries, TechnicalAnalysisEngine, rsi, sma

close = np.linspace(100.0, 130.0, num=60, dtype=np.float64)
series = OhlcvSeries.from_arrays(
    open_=close - 0.5,
    high=close + 1.0,
    low=close - 1.0,
    close=close,
    volume=np.full(60, 10.0),
)

engine = TechnicalAnalysisEngine()
results = engine.compute_all(series)

# Direct access to individual functions
rsi_values = rsi(series.close, period=14)
sma_values = sma(series.close, period=20)

Development

pytest -q
ruff check src tests
mypy src

Roadmap

  • Additional indicators (ATR, Stochastic, VWAP)
  • Parquet export of indicator series
  • Direct pipeline from the lakehouse's DuckDB

License

MIT

esc
↑↓ navigate↵ open