pub struct NormalizedTick {
pub exchange: Exchange,
pub symbol: String,
pub price: Decimal,
pub quantity: Decimal,
pub side: Option<TradeSide>,
pub trade_id: Option<String>,
pub exchange_ts_ms: Option<u64>,
pub received_at_ms: u64,
}Expand description
Canonical normalized tick — exchange-agnostic.
Fields§
§exchange: ExchangeSource exchange.
symbol: StringInstrument symbol in the canonical form used by this crate.
price: DecimalTrade price (exact decimal, never f64).
quantity: DecimalTrade quantity (exact decimal).
side: Option<TradeSide>Direction of the aggressing order, if available from the exchange.
trade_id: Option<String>Exchange-assigned trade identifier, if available.
exchange_ts_ms: Option<u64>Exchange-side timestamp (ms since Unix epoch), if included in the feed.
received_at_ms: u64Local system-clock timestamp when this tick was received.
Implementations§
Source§impl NormalizedTick
impl NormalizedTick
Sourcepub fn value(&self) -> Decimal
pub fn value(&self) -> Decimal
Notional trade value: price × quantity.
Returns the total value transferred in this trade. Useful for VWAP calculations and volume-weighted aggregations without requiring callers to multiply at every use site.
Sourcepub fn age_ms(&self, now_ms: u64) -> u64
pub fn age_ms(&self, now_ms: u64) -> u64
Age of this tick in milliseconds relative to now_ms.
Returns now_ms - received_at_ms, saturating at zero (never negative).
Useful for staleness checks: tick.age_ms(now) > threshold_ms.
Sourcepub fn is_stale(&self, now_ms: u64, threshold_ms: u64) -> bool
pub fn is_stale(&self, now_ms: u64, threshold_ms: u64) -> bool
Returns true if this tick is older than threshold_ms relative to now_ms.
Equivalent to self.age_ms(now_ms) > threshold_ms. Use this for filtering
stale ticks before passing them into aggregation pipelines.
Sourcepub fn is_buy(&self) -> bool
pub fn is_buy(&self) -> bool
Returns true if the tick is a buyer-initiated trade.
Returns false if side is Sell or None (side unknown).
Sourcepub fn is_sell(&self) -> bool
pub fn is_sell(&self) -> bool
Returns true if the tick is a seller-initiated trade.
Returns false if side is Buy or None (side unknown).
Sourcepub fn is_neutral(&self) -> bool
pub fn is_neutral(&self) -> bool
Returns true if the trade side is unknown (None).
Many exchanges do not report the aggressor side. This method lets
callers explicitly test for the “no side information” case rather than
relying on both is_buy() and is_sell() returning false.
Sourcepub fn is_large_trade(&self, threshold: Decimal) -> bool
pub fn is_large_trade(&self, threshold: Decimal) -> bool
Returns true if the traded quantity meets or exceeds threshold.
Useful for isolating institutional-size trades (“block trades”) from
the general flow. The threshold is in the same units as quantity.
Sourcepub fn with_side(self, side: TradeSide) -> Self
pub fn with_side(self, side: TradeSide) -> Self
Return a copy of this tick with the trade side set to side.
Useful in tests and feed normalizers that determine the aggressor side after initial tick construction.
Sourcepub fn with_exchange_ts(self, ts_ms: u64) -> Self
pub fn with_exchange_ts(self, ts_ms: u64) -> Self
Return a copy of this tick with the exchange timestamp set to ts_ms.
Useful in tests and feed normalizers to inject an authoritative exchange timestamp after the tick has already been constructed.
Sourcepub fn price_move_from(&self, prev: &NormalizedTick) -> Decimal
pub fn price_move_from(&self, prev: &NormalizedTick) -> Decimal
Signed price movement from prev to this tick: self.price − prev.price.
Positive when price rose, negative when price fell, zero when unchanged. Only meaningful when both ticks share the same symbol and exchange.
Sourcepub fn is_more_recent_than(&self, other: &NormalizedTick) -> bool
pub fn is_more_recent_than(&self, other: &NormalizedTick) -> bool
Returns true if this tick arrived more recently than other.
Compares received_at_ms timestamps. Equal timestamps return false.
Sourcepub fn latency_ms(&self) -> Option<i64>
pub fn latency_ms(&self) -> Option<i64>
Transport latency in milliseconds: received_at_ms − exchange_ts_ms.
Returns None if the exchange timestamp is unavailable. A positive
value indicates how long the tick took to travel from exchange to this
system; negative values suggest clock skew between exchange and consumer.
Sourcepub fn volume_notional(&self) -> Decimal
pub fn volume_notional(&self) -> Decimal
Notional value of this trade: price × quantity.
Sourcepub fn has_exchange_ts(&self) -> bool
pub fn has_exchange_ts(&self) -> bool
Returns true if this tick carries an exchange-provided timestamp.
When false, only the local received_at_ms is available. Use
latency_ms to measure round-trip latency when
this returns true.
Sourcepub fn side_str(&self) -> &'static str
pub fn side_str(&self) -> &'static str
Human-readable trade direction: "buy", "sell", or "unknown".
Sourcepub fn is_round_lot(&self) -> bool
pub fn is_round_lot(&self) -> bool
Returns true if the quantity is a whole number (no fractional part).
Useful for detecting atypical fractional order sizes, or as a simple round-lot check in integer-quantity markets.
Sourcepub fn is_same_symbol_as(&self, other: &NormalizedTick) -> bool
pub fn is_same_symbol_as(&self, other: &NormalizedTick) -> bool
Returns true if this tick’s symbol matches other’s symbol exactly.
Sourcepub fn price_distance_from(&self, other: &NormalizedTick) -> Decimal
pub fn price_distance_from(&self, other: &NormalizedTick) -> Decimal
Absolute price difference between this tick and other.
Returns |self.price - other.price|. Useful for computing price drift
between two ticks of the same instrument without caring about direction.
Sourcepub fn exchange_latency_ms(&self) -> Option<i64>
pub fn exchange_latency_ms(&self) -> Option<i64>
Signed latency between the local receipt timestamp and the exchange timestamp, in milliseconds.
Returns ts_ms as i64 - exchange_ts_ms as i64. Positive values mean
the tick arrived at the local system after the exchange stamped it
(normal network latency). Negative values indicate clock skew between
the exchange and local clock. Returns None if exchange_ts_ms is
absent.
Sourcepub fn is_notional_large_trade(&self, threshold: Decimal) -> bool
pub fn is_notional_large_trade(&self, threshold: Decimal) -> bool
Returns true if the notional value of this trade (price × quantity)
exceeds threshold.
Unlike is_large_trade (which compares raw
quantity), this method uses the trade’s dollar value, making it useful
for comparing block-trade size across instruments with different prices.
Sourcepub fn is_zero_price(&self) -> bool
pub fn is_zero_price(&self) -> bool
Returns true if this tick’s price is zero.
A zero price typically indicates a malformed or uninitialized tick.
Sourcepub fn is_fresh(&self, now_ms: u64, max_age_ms: u64) -> bool
pub fn is_fresh(&self, now_ms: u64, max_age_ms: u64) -> bool
Returns true if the tick is still fresh relative to now_ms.
“Fresh” means the tick arrived within the last max_age_ms milliseconds.
Returns false when now_ms < ts_ms (clock skew guard).
Sourcepub fn is_above(&self, price: Decimal) -> bool
pub fn is_above(&self, price: Decimal) -> bool
Returns true if this tick’s price is strictly above price.
Sourcepub fn is_below(&self, price: Decimal) -> bool
pub fn is_below(&self, price: Decimal) -> bool
Returns true if this tick’s price is strictly below price.
Sourcepub fn is_aggressive(&self) -> bool
pub fn is_aggressive(&self) -> bool
Returns true if the tick has a definite direction (buy or sell).
Neutral ticks (where side is None) return false.
Sourcepub fn price_diff_from(&self, other: &NormalizedTick) -> Decimal
pub fn price_diff_from(&self, other: &NormalizedTick) -> Decimal
Signed price difference: self.price - other.price.
Positive when this tick’s price is higher than the other’s.
Sourcepub fn is_micro_trade(&self, threshold: Decimal) -> bool
pub fn is_micro_trade(&self, threshold: Decimal) -> bool
Returns true if the trade quantity is strictly less than threshold.
The inverse of is_large_trade.
Sourcepub fn is_buying_pressure(&self, midpoint: Decimal) -> bool
pub fn is_buying_pressure(&self, midpoint: Decimal) -> bool
Returns true if this tick occurred above the given midpoint price.
A tick above the midpoint is typically associated with buying pressure.
Sourcepub fn age_secs(&self, now_ms: u64) -> f64
pub fn age_secs(&self, now_ms: u64) -> f64
Age of this tick in seconds: (now_ms - received_at_ms) / 1000.0.
Returns 0.0 if now_ms is before received_at_ms.
Sourcepub fn is_same_exchange_as(&self, other: &NormalizedTick) -> bool
pub fn is_same_exchange_as(&self, other: &NormalizedTick) -> bool
Returns true if this tick originated from the same exchange as other.
Sourcepub fn quote_age_ms(&self, now_ms: u64) -> u64
pub fn quote_age_ms(&self, now_ms: u64) -> u64
Age of this tick in milliseconds: now_ms - received_at_ms.
Returns 0 if now_ms is before received_at_ms.
Sourcepub fn notional_value(&self) -> Decimal
pub fn notional_value(&self) -> Decimal
Notional value of this tick: price × quantity.
Sourcepub fn is_high_value_tick(&self, threshold: Decimal) -> bool
pub fn is_high_value_tick(&self, threshold: Decimal) -> bool
Returns true if the notional value (price × quantity) exceeds threshold.
Sourcepub fn side_as_str(&self) -> Option<&'static str>
pub fn side_as_str(&self) -> Option<&'static str>
Returns the trade side as a string slice: "buy", "sell", or None.
Sourcepub fn is_above_price(&self, reference: Decimal) -> bool
pub fn is_above_price(&self, reference: Decimal) -> bool
Returns true if this tick’s price is strictly above reference.
Sourcepub fn price_change_from(&self, reference: Decimal) -> Decimal
pub fn price_change_from(&self, reference: Decimal) -> Decimal
Signed price change relative to reference: self.price - reference.
Sourcepub fn is_market_open_tick(
&self,
session_start_ms: u64,
session_end_ms: u64,
) -> bool
pub fn is_market_open_tick( &self, session_start_ms: u64, session_end_ms: u64, ) -> bool
Returns true if this tick’s received_at_ms falls within a trading session window.
Sourcepub fn is_at_price(&self, target: Decimal) -> bool
pub fn is_at_price(&self, target: Decimal) -> bool
Returns true if this tick’s price exactly equals target.
Sourcepub fn is_below_price(&self, reference: Decimal) -> bool
pub fn is_below_price(&self, reference: Decimal) -> bool
Returns true if this tick’s price is strictly below reference.
Sourcepub fn is_round_number(&self, step: Decimal) -> bool
pub fn is_round_number(&self, step: Decimal) -> bool
Returns true if this tick’s price is divisible by step with no remainder.
Useful for identifying round-number price levels (e.g., step = 100).
Returns false if step is zero.
Sourcepub fn signed_quantity(&self) -> Decimal
pub fn signed_quantity(&self) -> Decimal
Returns the trade quantity signed by side: +quantity for Buy, -quantity for Sell, 0 for unknown.
Sourcepub fn as_price_level(&self) -> (Decimal, Decimal)
pub fn as_price_level(&self) -> (Decimal, Decimal)
Returns (price, quantity) as a convenient tuple.
Sourcepub fn quantity_above(&self, threshold: Decimal) -> bool
pub fn quantity_above(&self, threshold: Decimal) -> bool
Returns true if this tick’s quantity is strictly above threshold.
Sourcepub fn is_recent(&self, threshold_ms: u64, now_ms: u64) -> bool
pub fn is_recent(&self, threshold_ms: u64, now_ms: u64) -> bool
Returns true if this tick was received within threshold_ms of now_ms.
Sourcepub fn is_buy_side(&self) -> bool
pub fn is_buy_side(&self) -> bool
Returns true if this tick is on the buy side.
Returns false if the side is Sell or None.
Sourcepub fn is_sell_side(&self) -> bool
pub fn is_sell_side(&self) -> bool
Returns true if this tick is on the sell side.
Returns false if the side is Buy or None.
Sourcepub fn is_zero_quantity(&self) -> bool
pub fn is_zero_quantity(&self) -> bool
Returns true if this tick’s quantity is zero (may indicate a cancel or correction).
Sourcepub fn is_within_spread(&self, bid: Decimal, ask: Decimal) -> bool
pub fn is_within_spread(&self, bid: Decimal, ask: Decimal) -> bool
Returns true if this tick’s price is strictly between bid and ask.
Sourcepub fn is_away_from_price(&self, reference: Decimal, threshold: Decimal) -> bool
pub fn is_away_from_price(&self, reference: Decimal, threshold: Decimal) -> bool
Returns true if this tick’s price deviates from reference by more than threshold.
Sourcepub fn is_large_tick(&self, threshold: Decimal) -> bool
pub fn is_large_tick(&self, threshold: Decimal) -> bool
Returns true if this tick’s quantity is strictly above threshold.
Sourcepub fn price_in_range(&self, low: Decimal, high: Decimal) -> bool
pub fn price_in_range(&self, low: Decimal, high: Decimal) -> bool
Returns true if this tick’s price is within [low, high] (inclusive).
Sourcepub fn rounded_price(&self, tick_size: Decimal) -> Decimal
pub fn rounded_price(&self, tick_size: Decimal) -> Decimal
Price rounded down to the nearest multiple of tick_size.
Returns the original price if tick_size is zero.
Sourcepub fn is_large_spread_from(
&self,
other: &NormalizedTick,
threshold: Decimal,
) -> bool
pub fn is_large_spread_from( &self, other: &NormalizedTick, threshold: Decimal, ) -> bool
Returns true if the absolute price difference from other exceeds threshold.
Sourcepub fn volume_notional_f64(&self) -> f64
pub fn volume_notional_f64(&self) -> f64
Notional value of this tick as f64 (price × quantity).
Sourcepub fn price_velocity(
&self,
prev: &NormalizedTick,
dt_ms: u64,
) -> Option<Decimal>
pub fn price_velocity( &self, prev: &NormalizedTick, dt_ms: u64, ) -> Option<Decimal>
Rate of price change relative to a prior tick: (price - prev.price) / dt_ms.
Returns None if dt_ms is zero (same timestamp).
Sourcepub fn vwap(ticks: &[NormalizedTick]) -> Option<Decimal>
pub fn vwap(ticks: &[NormalizedTick]) -> Option<Decimal>
Volume-weighted average price across a slice of ticks.
Returns None if the slice is empty or total volume is zero.
Sourcepub fn is_reversal(&self, prev: &NormalizedTick, min_move: Decimal) -> bool
pub fn is_reversal(&self, prev: &NormalizedTick, min_move: Decimal) -> bool
Returns true if price reversed direction by at least min_move from prev.
A reversal means the direction of (self.price - prev.price) is opposite to
the direction of (prev.price - prev_prev.price), and the magnitude ≥ min_move.
This two-argument form checks: |self.price - prev.price| >= min_move.
Sourcepub fn spread_crossed(
bid_tick: &NormalizedTick,
ask_tick: &NormalizedTick,
) -> bool
pub fn spread_crossed( bid_tick: &NormalizedTick, ask_tick: &NormalizedTick, ) -> bool
Returns true if a trade crossed the spread: bid_tick.price >= ask_tick.price.
A spread-crossed condition indicates an aggressive order consumed the best opposing quote.
Sourcepub fn dollar_value(&self) -> Decimal
pub fn dollar_value(&self) -> Decimal
Dollar (notional) value of this tick: price * quantity.
Sourcepub fn contract_value(&self, multiplier: Decimal) -> Decimal
pub fn contract_value(&self, multiplier: Decimal) -> Decimal
Contract value using a futures/options multiplier: price * quantity * multiplier.
Sourcepub fn tick_imbalance(ticks: &[NormalizedTick]) -> Option<f64>
pub fn tick_imbalance(ticks: &[NormalizedTick]) -> Option<f64>
Tick imbalance: (buy_qty - sell_qty) / total_qty across a tick slice.
Buy ticks are those with side == Some(TradeSide::Buy).
Returns None if total quantity is zero.
Sourcepub fn quote_midpoint(
bid: &NormalizedTick,
ask: &NormalizedTick,
) -> Option<Decimal>
pub fn quote_midpoint( bid: &NormalizedTick, ask: &NormalizedTick, ) -> Option<Decimal>
Theoretical quote midpoint: (bid.price + ask.price) / 2.
Returns None if either tick has a non-positive price or if the bid
price exceeds the ask price (crossed market).
Trait Implementations§
Source§impl Clone for NormalizedTick
impl Clone for NormalizedTick
Source§fn clone(&self) -> NormalizedTick
fn clone(&self) -> NormalizedTick
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more