Package Exports
- @junduck/trading-indi
Readme
trading-indi
A TypeScript library providing 80+ technical indicators for trading, designed for incremental, stateful calculation perfect for intraday and realtime trading applications.
Why trading-indi?
Traditional technical indicator libraries recalculate entire datasets on each new data point. trading-indi is different:
- 80+ Indicators: Comprehensive coverage including Foundation, Volatility, Momentum, Oscillators, Stochastic, Trend, Volume, and Statistical indicators
- Incremental Calculation: Each indicator maintains internal state and updates efficiently with each new data point
- Perfect for Realtime Trading: Designed for WebSocket streams, tick data, and intraday strategies
- Memory Efficient: Uses sliding windows and online algorithms
- Consistent API: Every indicator follows the same class/hook pattern
- Zero Dependencies: Clean, modern TypeScript
Performance
trading-indi is built for speed and efficiency, making it ideal for high-frequency trading applications:
Benchmark Results
- Processing Speed: 2+ million indicator calculations per second
- Latency: ~0.03ms to process a single bar with all 64 indicators
- Memory Efficiency: ~2.5KB per indicator instance
- Real-time Capability: Can handle tick data (1000+ bars/second) with ease
Real-time Trading Suitability
All trading strategies tested are feasible for real-time trading:
| Strategy | Indicators | Time per Bar | Max Bars/sec | Status |
|---|---|---|---|---|
| Scalping | 5 | 0.0017ms | 590,935 | ✅ FEASIBLE |
| Swing Trading | 6 | 0.0020ms | 502,162 | ✅ FEASIBLE |
| Trend Following | 6 | 0.0017ms | 597,488 | ✅ FEASIBLE |
| Mean Reversion | 6 | 0.0020ms | 488,757 | ✅ FEASIBLE |
| Volume Analysis | 6 | 0.0005ms | 1,840,082 | ✅ FEASIBLE |
| Multi-Timeframe | 11 | 0.0028ms | 358,709 | ✅ FEASIBLE |
The library can easily handle real-time trading scenarios, including tick data processing, with minimal memory footprint and excellent performance characteristics.
Installation
Install the package from npm:
npm install @junduck/trading-indi
# or
yarn add @junduck/trading-indi
# or
pnpm add @junduck/trading-indiQuick Start
Class-Based Usage (Stateful)
import { RSI, EMA, MACD, ATR, BBANDS, ADX } from '@junduck/trading-indi';
const rsi = new RSI({ period: 14 });
const ema = new EMA({ period: 20 });
const macd = new MACD({
period_short: 12,
period_long: 26,
period_signal: 9
});
const atr = new ATR({ period: 14 });
const bbands = new BBANDS({ period: 20, stddev: 2 });
const adx = new ADX({ period: 14 });
// Process streaming data
priceStream.on('data', (bar) => {
const rsiValue = rsi.onData(bar);
const emaValue = ema.onData(bar.close);
const { macd: macdLine, signal, histogram } = macd.onData(bar);
const atrValue = atr.onData(bar);
const { upper, middle, lower } = bbands.onData(bar.close);
const adxValue = adx.onData(bar);
console.log({ rsiValue, emaValue, macdLine, atrValue, bbands: { upper, middle, lower }, adxValue });
});Functional Usage (Hooks)
import { useRSI, useEMA, useMACD, useATR, useBBANDS, useADX } from '@junduck/trading-indi';
const getRSI = useRSI({ period: 14 });
const getEMA = useEMA({ period: 20 });
const getMACD = useMACD({
period_short: 12,
period_long: 26,
period_signal: 9
});
const getATR = useATR({ period: 14 });
const getBBANDS = useBBANDS({ period: 20, stddev: 2 });
const getADX = useADX({ period: 14 });
for (const bar of historicalData) {
const rsiValue = getRSI(bar);
const emaValue = getEMA(bar.close);
const { macd, signal, histogram } = getMACD(bar);
const atrValue = getATR(bar);
const { upper, middle, lower } = getBBANDS(bar.close);
const adxValue = getADX(bar);
}Available Indicators
Foundation
| Indicator | Parameters | Output |
|---|---|---|
| EMA | period or alpha |
number |
| EWMA | period |
number |
| SMA | period |
number |
| Variance | period, ddof? |
{mean: number, variance: number} |
| Stddev | period, ddof? |
{mean: number, stddev: number} |
| Min | period |
number |
| Max | period |
number |
| Sum | period |
number |
| MinMax | period |
{min: number, max: number} |
Statistics
| Indicator | Parameters | Output |
|---|---|---|
| VarianceEW | period or alpha, ddof? |
{mean: number, variance: number} |
| Cov | period, ddof? |
{meanX: number, meanY: number, covariance: number} |
| Corr | period, ddof? |
{meanX: number, meanY: number, covariance: number, correlation: number} |
| Beta | period, ddof? |
{meanX: number, meanY: number, covariance: number, beta: number} |
| ZSCORE | period |
number |
| CORRELATION | period |
number |
| BETA | period |
number |
Volatility
| Indicator | Parameters | Output |
|---|---|---|
| VOLATILITY | period, annualizedDays? |
number |
| CVI | period |
number |
| MASS | period |
number |
| TR | none | number |
| ATR | period |
number |
| NATR | period |
number |
| PriceChannel | period |
{upper, lower} |
| BBANDS | period, stddev? |
{upper, middle, lower} |
| KC | period, multiplier? |
{upper, middle, lower} |
| DC | period |
{upper, middle, lower} |
Momentum
| Indicator | Parameters | Output |
|---|---|---|
| BOP | none | number |
| MOM | period |
number |
| ROC | period |
number |
| ROCR | period |
number |
| RSI | period |
number |
| CMO | period |
number |
| WAD | none | number |
| RVI | period |
{rvi, signal} |
| TSI | long_period?, short_period?, signal_period? |
{tsi, signal} |
| BBPOWER | period |
{bull_power, bear_power} |
Oscillators
| Indicator | Parameters | Output |
|---|---|---|
| AO | none | number |
| APO | period_short, period_long |
number |
| DPO | period |
number |
| Fisher | period |
number |
| MACD | period_short, period_long, period_signal |
{macd, signal, histogram} |
| PPO | period_short, period_long |
number |
| QSTICK | period |
number |
| TRIX | period |
number |
| ULTOSC | period_short, period_med, period_long |
number |
Stochastic
| Indicator | Parameters | Output |
|---|---|---|
| STOCH | k_period?, k_slowing?, d_period? |
{k, d} |
| STOCHRSI | period |
number |
| WILLR | period |
number |
Trend
| Indicator | Parameters | Output |
|---|---|---|
| AROON | period |
{up, down} |
| AROONOSC | period |
number |
| CCI | period |
number |
| VHF | period |
number |
| DM | period |
{plus, minus} |
| DI | period |
{plus, minus} |
| DX | period |
number |
| ADX | period |
number |
| ADXR | period |
number |
| SAR | acceleration?, maximum? |
number |
| VI | period |
{vi_plus, vi_minus} |
| ICHIMOKU | tenkan_period?, kijun_period?, senkou_b_period?, displacement? |
{tenkan, kijun, senkou_a, senkou_b, chikou} |
Volume
| Indicator | Parameters | Output |
|---|---|---|
| AD | none | number |
| ADOSC | period_short, period_long |
number |
| KVO | period_short?, period_long? |
number |
| NVI | none | number |
| OBV | none | number |
| PVI | none | number |
| MFI | period |
number |
| EMV | none | number |
| MARKETFI | none | number |
| VOSC | period_short, period_long |
number |
| CMF | period |
number |
| CHO | period_short, period_long |
number |
| PVO | period_short, period_long, period_signal? |
{pvo, signal, histogram} |
| FI | period |
number |
| VROC | period |
number |
| PVT | none | number |
Real-World Example: Intraday Strategy
import { RSI, ATR, EMA, BBANDS, ADX, MACD, VOLUME } from '@junduck/trading-indi';
const rsi = new RSI({ period: 14 });
const atr = new ATR({ period: 14 });
const ema20 = new EMA({ period: 20 });
const ema50 = new EMA({ period: 50 });
const bbands = new BBANDS({ period: 20, stddev: 2 });
const adx = new ADX({ period: 14 });
const macd = new MACD({ period_short: 12, period_long: 26, period_signal: 9 });
const obv = new OBV();
websocket.on('tick', (bar) => {
const rsiValue = rsi.onData(bar);
const atrValue = atr.onData(bar);
const shortEMA = ema20.onData(bar.close);
const longEMA = ema50.onData(bar.close);
const { upper, middle, lower } = bbands.onData(bar.close);
const adxValue = adx.onData(bar);
const { macd: macdLine, signal, histogram } = macd.onData(bar);
const obvValue = obv.onData(bar);
// Multi-indicator strategy
const isOversold = rsiValue < 30;
const isBullishTrend = shortEMA > longEMA;
const isStrongTrend = adxValue > 25;
const isNearSupport = bar.close <= lower * 1.02; // Within 2% of lower band
const isMACDBullish = macdLine > signal && histogram > 0;
const isVolumeConfirming = obvValue > 0; // Positive volume flow
if (isOversold && isBullishTrend && isStrongTrend && isNearSupport && isMACDBullish && isVolumeConfirming) {
console.log('Strong Buy Signal - Multiple Confirmations');
console.log(`Entry: ${bar.close}`);
console.log(`Stop Loss: ${bar.close - (atrValue * 2)}`);
console.log(`Target: ${bar.close + (atrValue * 3)}`);
console.log(`RSI: ${rsiValue}, ADX: ${adxValue}, MACD: ${macdLine}`);
}
// Exit signal
const isOverbought = rsiValue > 70;
const isBearishMACD = macdLine < signal && histogram < 0;
const isNearResistance = bar.close >= upper * 0.98; // Within 2% of upper band
if (isOverbought || isBearishMACD || isNearResistance) {
console.log('Exit Signal - Consider Taking Profits');
console.log(`Current Price: ${bar.close}`);
console.log(`RSI: ${rsiValue}, MACD: ${macdLine}, BB Position: ${(bar.close - lower) / (upper - lower)}`);
}
});Statistical Analysis
The library includes advanced statistical indicators for quantitative analysis:
import { Corr, Beta, ZSCORE } from '@junduck/trading-indi';
// Correlation between two assets
const correlation = new Corr({ period: 20 });
const corrValue = correlation.onData(assetPrice, benchmarkPrice);
// Beta calculation for risk analysis
const beta = new Beta({ period: 252 }); // Daily data for 1 year
const betaValue = beta.onData(stockPrice, marketIndexPrice);
// Z-Score for statistical arbitrage
const zscore = new ZSCORE({ period: 20 });
const zValue = zscore.onData(price);Bar Data Types
Most indicators accept BarData with these properties:
interface BarData {
open?: number;
high?: number;
low?: number;
close: number;
volume?: number;
}Each indicator only requires the fields it needs. Check TypeScript types for specific requirements.
Changelog
See CHANGELOG.md for a detailed history of changes.
License
MIT