Williams Alligator
jaw_period = 13 (5–60) • jaw_offset = 8 (0–20) • teeth_period = 8 (3–40) • teeth_offset = 5 (0–15) • lips_period = 5 (2–30) • lips_offset = 3 (0–10) Overview
The Williams Alligator layers three displaced smoothed moving averages to expose when trend energy is rising or fading. The Jaw (slow), Teeth (medium), and Lips (fast) lines expand and contract around price, providing an intuitive read on participation without relying on oscillators.
When the lines weave together the Alligator is "sleeping" and conditions are range-bound. As the Lips cross and pull away from the Teeth and Jaw, the Alligator "awakens," signaling a potential breakout. Sustained line separation confirms a feeding trend, while converging lines warn that momentum is exhausting.
Implementation Examples
Compute the Jaw, Teeth, and Lips series from raw price slices or candle data:
use vectorta::indicators::alligator::{alligator, AlligatorInput, AlligatorParams};
use vectorta::utilities::data_loader::Candles;
// Example price history
let prices = vec![100.0, 101.5, 99.8, 102.2, 104.0, 103.4];
let params = AlligatorParams {
jaw_period: Some(13),
jaw_offset: Some(8),
teeth_period: Some(8),
teeth_offset: Some(5),
lips_period: Some(5),
lips_offset: Some(3),
};
let input = AlligatorInput::from_slice(&prices, params);
let output = alligator(&input)?;
// Iterate the three smoothed series
for idx in 0..output.jaw.len() {
println!(
"[{}] jaw={:.2} teeth={:.2} lips={:.2}",
idx, output.jaw[idx], output.teeth[idx], output.lips[idx]
);
}
// Using default configuration with candles (hl2 source, 13/8/5 periods & offsets)
let candles: Candles = load_candles_from_disk()?;
let input = AlligatorInput::with_default_candles(&candles);
let output = alligator(&input)?; API Reference
Input Methods ▾
// Price slices
AlligatorInput::from_slice(&[f64], AlligatorParams) -> AlligatorInput
// Candle data with explicit source (e.g. "hl2")
AlligatorInput::from_candles(&Candles, &str, AlligatorParams) -> AlligatorInput
// Candles with defaults (hl2 field, 13/8/5 periods & offsets)
AlligatorInput::with_default_candles(&Candles) -> AlligatorInput Parameter Structure ▾
#[derive(Default, Clone)]
pub struct AlligatorParams {
pub jaw_period: Option<usize>, // defaults to Some(13)
pub jaw_offset: Option<usize>, // defaults to Some(8)
pub teeth_period: Option<usize>, // defaults to Some(8)
pub teeth_offset: Option<usize>, // defaults to Some(5)
pub lips_period: Option<usize>, // defaults to Some(5)
pub lips_offset: Option<usize>, // defaults to Some(3)
} Output Structure ▾
pub struct AlligatorOutput {
pub jaw: Vec<f64>, // Smoothed Jaw line aligned to input length
pub teeth: Vec<f64>, // Smoothed Teeth line aligned to input length
pub lips: Vec<f64>, // Smoothed Lips line aligned to input length
} Builder Utilities ▾
use vectorta::indicators::alligator::AlligatorBuilder;
use vectorta::utilities::enums::Kernel;
let builder = AlligatorBuilder::new()
.jaw_period(21)
.jaw_offset(13)
.teeth_period(13)
.teeth_offset(8)
.lips_period(8)
.lips_offset(5)
.kernel(Kernel::Auto);
let slice_output = builder.apply_slice(&prices)?;
let candle_output = builder.apply(&candles)?;
let stream = builder.into_stream()?; // Builder implements Copy, reuse after calls Streaming API ▾
use vectorta::indicators::alligator::{AlligatorParams, AlligatorStream};
let mut stream = AlligatorStream::try_new(AlligatorParams::default())?;
while let Some(price) = next_price() {
if let Some((jaw, teeth, lips)) = stream.update(price) {
emit_signals(jaw, teeth, lips);
}
} Batch Operations ▾
use vectorta::indicators::alligator::{AlligatorBatchBuilder, AlligatorParams};
let batch = AlligatorBatchBuilder::new()
.jaw_period_range(10, 30, 5)
.teeth_period_range(6, 18, 2)
.lips_period_range(4, 12, 2)
.apply_slice(&prices)?;
println!("rows={}, cols={}", batch.rows, batch.cols);
println!("combos tested={}", batch.combos.len());
if let Some((jaw, teeth, lips)) = batch.values_for(&AlligatorParams {
jaw_period: Some(15),
teeth_period: Some(9),
lips_period: Some(6),
jaw_offset: Some(8),
teeth_offset: Some(5),
lips_offset: Some(3),
}) {
score_combo(jaw, teeth, lips);
} Error Handling ▾
use vectorta::indicators::alligator::AlligatorError;
match alligator(&input) {
Ok(output) => consume(output),
Err(AlligatorError::AllValuesNaN) => log::warn!("All inputs were NaN"),
Err(AlligatorError::InvalidJawPeriod { period, data_len }) => handle_bad_period("jaw", period, data_len),
Err(AlligatorError::InvalidJawOffset { offset, data_len }) => handle_bad_offset("jaw", offset, data_len),
Err(AlligatorError::InvalidTeethPeriod { period, data_len }) => handle_bad_period("teeth", period, data_len),
Err(AlligatorError::InvalidTeethOffset { offset, data_len }) => handle_bad_offset("teeth", offset, data_len),
Err(AlligatorError::InvalidLipsPeriod { period, data_len }) => handle_bad_period("lips", period, data_len),
Err(AlligatorError::InvalidLipsOffset { offset, data_len }) => handle_bad_offset("lips", offset, data_len),
Err(AlligatorError::InvalidKernel { kernel }) => panic!("Unsupported kernel: {kernel:?}"),
} Python Bindings
Basic Usage ▾
Calculate and access the Jaw, Teeth, and Lips arrays directly as NumPy vectors:
import numpy as np
from vectorta import alligator
prices = np.asarray([100, 101.5, 99.8, 102.2, 104.0, 103.4], dtype=np.float64)
result = alligator(prices)
jaw = result["jaw"]
teeth = result["teeth"]
lips = result["lips"]
# Override periods, offsets, and kernel when needed
result = alligator(
prices,
jaw_period=21,
jaw_offset=13,
teeth_period=13,
teeth_offset=8,
lips_period=8,
lips_offset=5,
kernel="avx2", # "auto", "scalar", and "avx2" are accepted
) Streaming Updates ▾
Maintain live state with the helper exposed through PyO3:
from vectorta import AlligatorStream
stream = AlligatorStream() # defaults to 13/8/5 periods and 8/5/3 offsets
for price in live_prices():
triple = stream.update(float(price))
if triple is not None:
jaw, teeth, lips = triple
handle_realtime(jaw, teeth, lips) Batch Sweeps ▾
Run parameter grids efficiently and inspect the resulting combinations:
from vectorta import alligator_batch
sweep = alligator_batch(
prices,
jaw_period_range=(10, 26, 4),
jaw_offset_range=(4, 16, 4),
teeth_period_range=(8, 20, 4),
teeth_offset_range=(3, 11, 2),
lips_period_range=(5, 13, 2),
lips_offset_range=(2, 8, 2),
kernel="auto",
)
jaw_grid = sweep["jaw"] # rows x len(prices)
teeth_grid = sweep["teeth"]
lips_grid = sweep["lips"]
# Metadata vectors align with each row
jaw_periods = sweep["jaw_periods"]
jaw_offsets = sweep["jaw_offsets"] Return Structure ▾
# alligator(...)
{
"jaw": np.ndarray, # shape (len(prices),)
"teeth": np.ndarray,
"lips": np.ndarray,
}
# alligator_batch(...)
{
"jaw": np.ndarray, # shape (rows, len(prices))
"teeth": np.ndarray,
"lips": np.ndarray,
"jaw_periods": np.ndarray,
"jaw_offsets": np.ndarray,
"teeth_periods": np.ndarray,
"teeth_offsets": np.ndarray,
"lips_periods": np.ndarray,
"lips_offsets": np.ndarray,
} JavaScript / WASM Bindings
Quick Usage ▾
Invoke the Alligator kernel directly from your browser or Node runtime:
import { alligator_js } from 'vectorta-wasm';
const prices = new Float64Array([100, 101.5, 99.8, 102.2, 104.0, 103.4]);
const flattened = alligator_js(prices, 13, 8, 8, 5, 5, 3);
// Results are flattened: [jaw..., teeth..., lips...]
const length = prices.length;
const jaw = flattened.slice(0, length);
const teeth = flattened.slice(length, length * 2);
const lips = flattened.slice(length * 2); Memory-Efficient Operations ▾
Allocate output buffers once and fill them via zero-copy transfers:
import { alligator_alloc, alligator_free, alligator_into, memory } from 'vectorta-wasm';
const prices = new Float64Array(loadPrices());
const len = prices.length;
const jawPtr = alligator_alloc(len);
const teethPtr = alligator_alloc(len);
const lipsPtr = alligator_alloc(len);
const inputView = new Float64Array(memory.buffer, 0, len);
inputView.set(prices);
alligator_into(
inputView.byteOffset,
jawPtr,
teethPtr,
lipsPtr,
len,
13, 8,
8, 5,
5, 3
);
// Copy results out when needed
const jaw = new Float64Array(memory.buffer, jawPtr, len);
const teeth = new Float64Array(memory.buffer, teethPtr, len);
const lips = new Float64Array(memory.buffer, lipsPtr, len);
alligator_free(jawPtr, len);
alligator_free(teethPtr, len);
alligator_free(lipsPtr, len); Batch & Metadata ▾
Enumerate parameter grids and keep outputs aligned with metadata descriptors:
import { alligator_batch_js, alligator_batch_metadata_js, alligator_batch_unified_js } from 'vectorta-wasm';
const prices = new Float64Array(loadBacktest());
const metadata = alligator_batch_metadata_js(
10, 30, 5,
5, 15, 5,
8, 20, 4,
3, 11, 2,
5, 13, 2,
2, 8, 2
);
const combos = metadata.length / 6;
const flattened = alligator_batch_js(
prices,
10, 30, 5,
5, 15, 5,
8, 20, 4,
3, 11, 2,
5, 13, 2,
2, 8, 2
);
// Each block is len(prices) and retains jaw/teeth/lips order
const block = prices.length;
const firstJaw = flattened.slice(0, block);
const firstTeeth = flattened.slice(block, block * 2);
const firstLips = flattened.slice(block * 2, block * 3);
// Alternatively consume structured JSON
const unified = alligator_batch_unified_js(prices, {
jaw_period_range: [10, 30, 5],
jaw_offset_range: [5, 15, 5],
teeth_period_range: [8, 20, 4],
teeth_offset_range: [3, 11, 2],
lips_period_range: [5, 13, 2],
lips_offset_range: [2, 8, 2],
});
console.log(unified.jaw.length, unified.combos.length); Performance Analysis
Related Indicators
Average Directional Index
Technical analysis indicator
Average Directional Movement Index Rating
Technical analysis indicator
Aroon
Technical analysis indicator
Aroon Oscillator
Technical analysis indicator
Directional Indicator (+DI/-DI)
Technical analysis indicator
Directional Movement
Technical analysis indicator