Skip to content

sense / sense_tick

sense(candles, vol_period=20)

Convert a window of OHLCV candles into STRATA semantic signals.

Args:

Param Type Default Description
candles list[dict] OHLCV dicts, oldest→newest. Min 3. Optional: bid, ask keys.
vol_period int 20 Lookback for volume/volatility normalisation

Returns: dict

Key Range Description
trend [-1, 1] EMA crossover direction, ATR-normalised
vol [0, 1] Volatility intensity (ATR / median price)
liquidity_above [0, 1] Spread z-score (if bid/ask) or volume spike
break_structure [0, 1] Close beyond prior N-bar high/low
source str "spread" | "volume" | "none"

Example:

from strata import sense

# Volume-based (reactive)
signals = sense(candles)
# {"trend": 0.12, "vol": 0.03, "liquidity_above": 0.15, "break_structure": 0.0, "source": "volume"}

# Spread-based (anticipatory) — add bid/ask
candles[-1]["bid"] = 150.18
candles[-1]["ask"] = 150.22
signals = sense(candles)
# {"trend": 0.12, "vol": 0.03, "liquidity_above": 0.61, "break_structure": 0.0, "source": "spread"}

sense_tick(candles, vol_period=20)

Extended sense for full tick-level data. Adds spread_pressure and side_imbalance.

Requires: bid, ask fields per candle. Optional: bid_size, ask_size.

Returns: All sense() outputs plus:

Key Range Description
spread_pressure [0, 1] Current spread vs historical norm
side_imbalance [-1, 1] +1 = ask-heavy (sell), -1 = bid-heavy (buy)

Example:

from strata import sense_tick

candle = {
    "open": 150.0, "high": 150.5, "low": 149.8, "close": 150.2,
    "volume": 1_000_000,
    "bid": 150.18, "ask": 150.22,
    "bid_size": 2500, "ask_size": 800,
}
signals = sense_tick([...window..., candle])
# signals["spread_pressure"] = 0.12
# signals["side_imbalance"]  = -0.51   (bid-heavy = buy pressure)