InSync Index

Parameters: emo_divisor = 10000 | emo_length = 14 | fast_length = 12 | slow_length = 26 | mfi_length = 20 | bb_length = 20 | bb_multiplier = 2 | cci_length = 14 | dpo_length = 18 | roc_length = 10 | rsi_length = 14 | stoch_length = 14 | stoch_d_length = 3 | stoch_k_length = 1 | sma_length = 10

Overview

InSync Index is a composite scoring model that blends several familiar studies into one alignment readout. It uses Bollinger-style position, CCI, an EMO-derived volume signal, MACD-style trend structure, MFI, DPO, ROC, RSI, and stochastic components, then adds or subtracts score increments depending on whether those internal signals are pointing toward strength or weakness.

The result is a single values series instead of a multi-line bundle. That makes the indicator useful when you want a compact confirmation layer for screening, ranking, or strategy filters rather than monitoring each component separately. The calculation expects full OHLCV input because several internal signals depend on high, low, close, and volume together.

Defaults: InSync Index uses `emo_divisor = 10000`, `emo_length = 14`, `fast_length = 12`, `slow_length = 26`, `mfi_length = 20`, `bb_length = 20`, `bb_multiplier = 2.0`, `cci_length = 14`, `dpo_length = 18`, `roc_length = 10`, `rsi_length = 14`, `stoch_length = 14`, `stoch_d_length = 3`, `stoch_k_length = 1`, and `sma_length = 10`.

Implementation Examples

Compute the composite alignment score from OHLCV slices or a Candles dataset.

use vector_ta::indicators::insync_index::{
    insync_index,
    InsyncIndexInput,
    InsyncIndexParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};

let output = insync_index(
    &InsyncIndexInput::from_slices(
        &high,
        &low,
        &close,
        &volume,
        InsyncIndexParams::default(),
    ),
)?;

let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_output = insync_index(&InsyncIndexInput::with_default_candles(&candles))?;

println!("{:?}", output.values.last());
println!("{:?}", candle_output.values.last());

API Reference

Input Methods
// From candles
InsyncIndexInput::from_candles(&Candles, InsyncIndexParams) -> InsyncIndexInput

// From slices
InsyncIndexInput::from_slices(&[f64], &[f64], &[f64], &[f64], InsyncIndexParams) -> InsyncIndexInput

// From candles with default parameters
InsyncIndexInput::with_default_candles(&Candles) -> InsyncIndexInput
Parameters Structure
pub struct InsyncIndexParams {
    pub emo_divisor: Option<usize>,
    pub emo_length: Option<usize>,
    pub fast_length: Option<usize>,
    pub slow_length: Option<usize>,
    pub mfi_length: Option<usize>,
    pub bb_length: Option<usize>,
    pub bb_multiplier: Option<f64>,
    pub cci_length: Option<usize>,
    pub dpo_length: Option<usize>,
    pub roc_length: Option<usize>,
    pub rsi_length: Option<usize>,
    pub stoch_length: Option<usize>,
    pub stoch_d_length: Option<usize>,
    pub stoch_k_length: Option<usize>,
    pub sma_length: Option<usize>,
}
Output Structure
pub struct InsyncIndexOutput {
    pub values: Vec<f64>,
}
Validation, Warmup & NaNs
  • High, low, close, and volume arrays must be non-empty and equal in length.
  • At least one valid OHLCV bar is required; bars are valid only when values are finite, volume is positive, and high is not below low.
  • All period parameters must be greater than zero, and bb_multiplier must be finite and positive.
  • Streaming resets on invalid bars and returns None for those updates.
  • Batch mode validates each sweep axis and rejects unsupported kernels through InvalidKernelForBatch.
Builder, Streaming & Batch APIs
// Builder
InsyncIndexBuilder::new()
    .emo_divisor(usize)
    .emo_length(usize)
    .fast_length(usize)
    .slow_length(usize)
    .mfi_length(usize)
    .bb_length(usize)
    .bb_multiplier(f64)
    .cci_length(usize)
    .dpo_length(usize)
    .roc_length(usize)
    .rsi_length(usize)
    .stoch_length(usize)
    .stoch_d_length(usize)
    .stoch_k_length(usize)
    .sma_length(usize)
    .kernel(Kernel)
    .apply(&Candles)

InsyncIndexBuilder::new()
    .apply_slices(&[f64], &[f64], &[f64], &[f64])
    .into_stream()

// Stream
InsyncIndexStream::try_new(InsyncIndexParams)
InsyncIndexStream::update(f64, f64, f64, f64) -> Option<f64>
InsyncIndexStream::reset()

// Batch
InsyncIndexBatchBuilder::new()
    .emo_length_range(usize, usize, usize)
    .fast_length_range(usize, usize, usize)
    .bb_multiplier_range(f64, f64, f64)
    .apply_slices(&[f64], &[f64], &[f64], &[f64])
Error Handling
pub enum InsyncIndexError {
    EmptyInputData,
    DataLengthMismatch,
    AllValuesNaN,
    InvalidPeriod { name: &'static str, value: usize },
    InvalidFloat { name: &'static str, value: f64 },
    OutputLengthMismatch { expected: usize, got: usize },
    InvalidRange { name: &'static str, start: String, end: String, step: String },
    InvalidKernelForBatch(Kernel),
}

Python Bindings

Python exposes a scalar function, a stream class, and a batch sweep. The scalar function returns one NumPy array of composite scores. The stream class returns one score per update. Batch returns a dictionary with the flattened values matrix, dimensions, and one parameter array for each swept axis.

import numpy as np
from vector_ta import (
    insync_index,
    insync_index_batch,
    InsyncIndexStream,
)

high = np.asarray(high_values, dtype=np.float64)
low = np.asarray(low_values, dtype=np.float64)
close = np.asarray(close_values, dtype=np.float64)
volume = np.asarray(volume_values, dtype=np.float64)

values = insync_index(
    high,
    low,
    close,
    volume,
    emo_divisor=10000,
    emo_length=14,
    fast_length=12,
    slow_length=26,
    kernel="auto",
)

stream = InsyncIndexStream()
print(stream.update(float(high[-1]), float(low[-1]), float(close[-1]), float(volume[-1])))

batch = insync_index_batch(
    high,
    low,
    close,
    volume,
    emo_length_range=(10, 14, 2),
    fast_length_range=(10, 14, 2),
    bb_multiplier_range=(2.0, 3.0, 0.5),
    kernel="auto",
)

print(batch["values"].shape)
print(batch["fast_lengths"])

JavaScript/WASM Bindings

The WASM layer exposes scalar, batch, and into-buffer helpers. The scalar binding returns a plain array of InSync scores. The batch binding returns an object with `values`, `rows`, `cols`, and the tested parameter `combos`.

import init, {
  insync_index_js,
  insync_index_batch_js,
} from "@vectoralpha/vector_ta";

await init();

const values = insync_index_js(
  high,
  low,
  close,
  volume,
  10000,
  14,
  12,
  26,
  20,
  20,
  2.0,
  14,
  18,
  10,
  14,
  14,
  3,
  1,
  10,
);

const batch = insync_index_batch_js(high, low, close, volume, {
  emo_length_range: [10, 14, 2],
  fast_length_range: [10, 14, 2],
  bb_multiplier_range: [2.0, 3.0, 0.5],
});

console.log(values.at(-1));
console.log(batch.rows, batch.cols);
console.log(batch.combos[0]);

CUDA Bindings (Rust)

Additional details for the CUDA bindings can be found inside the VectorTA repository.

Performance Analysis

Comparison:
View:
Placeholder data (no recorded benchmarks for this indicator)

Across sizes, Rust CPU runs about 1.14× faster than Tulip C in this benchmark.

Loading chart...

AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU)

Related Indicators