fin-primitives
A zero-panic, decimal-precise foundation for high-frequency trading and quantitative
systems in Rust. fin-primitives provides the building blocks: validated types,
order book, OHLCV aggregation, 712+ streaming technical indicators, position ledger,
and composable risk monitoring — so that upstream crates and applications can focus on
strategy rather than infrastructure.
What Is Included
| Module | What it provides | Key guarantee |
|---|---|---|
[types] |
Price, Quantity, Symbol, NanoTimestamp, Side newtypes |
Validation at construction; no invalid value can exist at runtime |
[tick] |
Tick, TickFilter, TickReplayer |
Filter is pure; replayer always yields ticks in ascending timestamp order |
[orderbook] |
L2 OrderBook with apply_delta, spread, mid-price, VWAP, top-N levels |
Sequence validation; inverted spreads are detected and rolled back |
[ohlcv] |
OhlcvBar, Timeframe, OhlcvAggregator, OhlcvSeries (370+ analytics) |
Bar invariants (high >= low, etc.) enforced on every push |
[signals] |
Signal trait, SignalPipeline, 712+ built-in indicators, SignalMap (90+ methods) |
Returns Unavailable until warm-up period is satisfied; no silent NaN |
[position] |
Position, Fill, PositionLedger (145+ methods) |
VWAP average cost; realized and unrealized P&L net of commissions |
[risk] |
DrawdownTracker (120+ methods), RiskRule trait, RiskMonitor |
All breaches returned as a typed Vec<RiskBreach>; never silently swallowed |
Design Principles
- Zero panics. Every fallible operation returns
Result<_, FinError>. Nounwraporexpectin production code paths. - Decimal precision. All prices and quantities use [
rust_decimal::Decimal]. Floating-point drift is structurally impossible. - Nanosecond timestamps.
NanoTimestampis a newtype overi64nanoseconds since Unix epoch, suitable for microsecond-accurate event ordering and replay. - Composable by design.
RiskRule,Signal, andTickFilterare traits; plug in your own implementations without forking. - Separation of concerns. Each module has a documented responsibility contract and an explicit "NOT Responsible For" section.
Quickstart
Add to Cargo.toml:
[]
= "2.9"
= "1"
Example: Buy, mark-to-market, check risk
use ;
use ;
use ;
use dec;
use HashMap;
Example: Tick-to-OHLCV with SMA signal
use ;
use SignalPipeline;
use Sma;
use Tick;
use ;
use dec;
Example: RSI(14) computation
use Rsi;
use ;
use OhlcvBar;
use ;
use dec;
Technical Indicators (712+)
All indicators implement the Signal trait and return SignalValue::Unavailable
until warm-up is satisfied. No silent NaN or panic.
Trend / Moving Averages
Sma, Ema, Dema, Tema, Wma, HullMa, Alma, Smma, Zlema, T3,
Trima, Kama, Lsma, Vidya, Swma, McGinley, LinRegSlope, Frama,
DemaRatio, DemaCross, EmaCross, EmaSlope, EmaConvergence, TypicalPriceMa,
TrueRangeEma, CoralTrend, HalfTrend, MesaAdaptiveMa, JurikMa,
ChandeKrollStop, EmaRatio, EmaAlignment, EmaBandWidth, SmaDistancePct,
TrendMagic, AdaptiveSupertrend, RollingVwap
Momentum / Oscillators
Rsi, Macd, Cci, Roc, Momentum, Apo, Ppo, Cmo, Tsi, Rvi,
StochasticK, StochasticD, StochRsi, StochRsiSmoothed, WilliamsR,
UltimateOscillator, Coppock, Kst, Trix, Dpo, Pgo, Rmi, Cog,
Pfe, ConnorsRsi, DualRsi, RsiMa, RsiDivergence, SmoothedRsi,
AdaptiveRsi, RsiStochastic, VolumeWeightedRsi, Qqe, Pmo, Tii,
AwesomeOscillator, Smi, Ctm, PriceMomentumOscillator, MomentumOscillator,
DeltaMomentum, CumReturnMomentum, NormalizedMomentum, MomentumQuality,
MomentumReversal, MomentumStreak, MomentumDivergence, MomentumConsistency,
UpMomentumPct, BodyMomentum, SlopeOscillator, EhlersCyberCycle,
ChandeForecastOsc, ChandeMomentumSmoothed, DynamicMomentumIndex
Volatility
Atr, Natr, BollingerB, BollingerPctB, BollingerWidth, KeltnerChannel,
DonchianMidpoint, DonchianWidth, Vhf, ChoppinessIndex, HistoricalVolatility,
RelativeVolatility, ChaikinVolatility, VolatilityRatio, VolatilityBands,
VolatilityAdjustedMomentum, VolatilitySkew, StdDevChannel, LinRegChannel,
Inertia, Stiffness, TtmSqueeze, VolatilityOfVolatility, VolatilityBreak,
VolatilityMomentum, VolatilityPercentile, VolatilityRegimeDetector,
VolatilitySpike, VolatilityStop, RegimeVolatility, LogReturnVolatility,
WeightedCloseVolatility, AccelerationBands, AtrPercent, AtrNormalizedClose,
AtrRatio, DualATRRatio, WilderSmoothedRange, TrueRangeExpansion,
TrueRangePercentile, TrueRangeZScore, TrueRangeRatio
Volume
Cmf, Obv, Mfi, Vwap, Vwma, Pvo, Emv, Kvo, Vpt, Nvi,
ChaikinOsc, ForceIndex, NetVolume, VolumeRsi, VolumeSpike,
VolumeTrend, VolumeOscillator, VolumeImbalance, Vroc, ObvMomentum,
ClimaxVolume, BwMfi, Vzo, VwMomentum, VolumeBreadth, VolumeAcceleration,
VolumeWeightedClose, VolumeAccumulation, VolumeDeltaOscillator,
VolumeToRangeRatio, VolumeRateOfChange, VolumeSpikeRatio, VolumeSpikeScore,
VolumeReturnCorrelation, VolumeTrendSlope, VolumePriceEfficiency,
VolumePriceCorr, VolumePriceImpact, VolumeDirectionRatio, VolumeEnergy,
VolumeExhaustion, VolumeFlowRatio, VolumeDensity, VolumeDeviation,
VolumeClimaxRatio, VolumeMomentum, VolumeMomentumDivergence,
VolumeOpenBias, VolumePerRange, VolumeRatioSignal, VolumeSurge,
VolumeSurge2, VolumeUpDownRatio, VolumeWeightedAtr, VolumeWeightedRange,
VolumeWeightedStdDev, VolumeWeightedMomentum, UpVolumeFraction,
UpVolumeRatio, UpDownVolumeRatio, NegativeVolumeIndex, PositiveVolumeIndex,
RelativeVolumeRank, RelativeVolumeScore, NormalizedVolume, MedianVolume,
CumulativeVolume, CumulativeDelta, ConsecutiveVolumeGrowth, VolumeStreakCount,
RollingVolumeCV, DeltaVolume
Trend Direction / Multi-component
Adx, Dmi, Aroon, AroonOscillator, Ichimoku, ParabolicSar, SuperTrend,
ElderRay, ElderImpulse, ChandelierExit, Stc, Vortex, WilliamsAD,
GannHiLo, TrendFollowingFilter, TrendStrength, TrendAngle, TrendScore,
Alligator, Rwi, TrendAge, TrendConsistency, TrendConsistencyScore,
TrendPersistence, TrendPurity, MarketRegimeFilter, NetHighLowCount,
BullBearBalance, TdSequential, WilliamsFractal, KeyReversal
Price Structure / Pattern
PriceChannel, PriceCompression, PriceDistanceMa, PriceGap, PriceIntensity,
PriceOscillator, PriceOscillator2, PricePosition, PriceRangePct,
PriceAboveMa, PriceAboveMaPct, PriceAcceleration, PriceVelocity,
PriceVelocityRatio, PriceVelocityScore, PriceEnvelope, PriceReversal,
PriceReversalStrength, NormalizedPrice, DisparityIndex, DeviationFromMa,
LinearDeviation, PriceDensity, CandleBodySize, CandleColor, CandleMomentum,
CandlePattern, HeikinAshi, WickRatio, HighLowPct, HighLowPctRange,
HighLowSpread, HlRatio, OpenCloseRatio, CloseToOpen, CloseLocationValue,
WeightedClose, CloseToOpenGap, CloseToOpenReturn, HighLowReturnCorrelation,
UpperWickPct, LowerWickPct, HigherHighLowerLow, OpenHighLowCloseAvg,
CloseToLowDistance, ReturnMeanDeviation, PriceAboveRollingHigh,
OpenCloseSpread, GapFillRatio, PriceCompressionRatio, ShadowRatio,
PriceMeanDeviation, AbsReturnSum, AbsReturnMean, RollingMaxDrawdown,
PriceRelativeStrength, OpenLowRange, HighOpenRange, BodyAtrRatio,
GapStreak, BarEfficiency, MedianBodySize, WickAsymmetryStreak,
FibonacciRetrace, PriceEntropyScore, PriceCompressionIndex,
PriceCompressionBreakout, PriceSymmetry, PricePathEfficiency,
PriceEfficiencyRatio, PriceGravity, PriceImpulse, PriceBandwidth,
PriceLevelPct, PricePositionRank, PriceRangeExpansion, PriceRangeRank,
PriceToSmaRatio, PriceZScore, PriceOscillatorPct, PriceOscillatorSign,
PriceChangeCount, PriceChangePct, PriceChannelPosition, PriceChannelWidth,
PriceGapFrequency, OpenToHighRatio, RangeMomentum, RangePersistence,
RangeReturnRatio, RangeCompressionRatio, RangeContractionCount,
RangeExpansionIndex, RangeMidpointPosition, RangePctOfClose,
RangeTrendSlope, RangeZScore, RangeEfficiency, RangeBreakoutCount,
RangeReturnRatio, CloseMidpointDiff, CloseMidpointStrength,
CloseAboveMidpoint, CloseVsOpenRange, CloseVsPriorHigh, CloseVsVwap,
ClosePositionInRange, CloseRetracePct, CloseReturnAcceleration,
CloseReturnZ, CloseToHighRatio, CloseToMidRange, CloseToRangeTop,
CloseRelativeToEma, CloseRelativeToRange, ClosePctFromHigh, ClosePctFromLow,
CloseAboveEma, CloseAboveOpen, CloseAbovePrevClose, CloseAbovePrevClosePct,
CloseAbovePrevHigh, CloseAbovePriorClose, CloseAboveSmaStreak,
CloseAboveHighPrev, CloseBelowLowPrev, CloseDistanceFromEma, CloseDistanceFromOpen, CloseHighFrequency,
CloseMinusOpenMa, CloseOpenEma, CloseAcceleration, CloseAccelerationSign,
OpenAbovePrevClose, OpenCloseMomentum, OpenGapDirection, OpenGapPct,
OpenGapSize, OpenHighRatio, OpenRangeStrength, OpenToCloseRatio,
OpenToCloseReturn, OpenCloseSymmetry, OpenDrive, OpenMidpointDeviation,
OvernightReturn, IntrabarReturn,
HighBreakCount, HigherCloseStreak, HigherHighCount, HigherLowCount,
HigherLowStreak, HighLowCrossover, HighLowDivergence, HighLowMidpoint,
HighLowOscillator, HighOfPeriod, LowOfPeriod, LowerHighCount,
LowerHighStreak, LowerLowCount, LowerShadowRatio, UpperShadowRatio,
UpperToLowerWick, ShadowImbalance, WickImbalance, WickToAtrRatio,
WickToBodyRatio, WickRejectionScore, BodyDirectionRatio, BodyFillRatio,
BodyHeightRatio, BodySizeRank, BodyStreak, BodyToRangeRatio,
BarCloseRank, BarFollowThrough, BarMomentumIndex, BarMomentumScore,
BarOpenPosition, BarOverlapRatio, BarRangeConsistency, BarRangeExpansionPct,
BarRangeStdDev, BarStrengthIndex, BarType, BearishBarRatio,
BodyPosition, BodyToShadowRatio, HighVolumeBarRatio,
CandleEfficiency, CandleRangeMa, CandleSymmetry, FlatBarPct,
NarrowRangeBar, UpBarRatio, NetBarBias, ThreeBarPattern,
EngulfingDetector, EngulfingPattern, HammerDetector, HammerPattern,
DojiDetector, InsideBarCounter, InsideBarRatio, OutsideBarCount
Statistical / Adaptive
StdDev, PercentRank, Fisher, MassIndex, PsychologicalLine, KaufmanEr,
ZScore, Bop, Atrp, Envelope, Pivots, PivotDistance, PivotPoint,
PivotStrength, SupportResistanceDistance, AtrStop, ChangeFromHigh,
BarsSince, ConsecutiveBars, SwingIndex, Dsp, Usm, Vam,
LinRegR2, UlcerIndex, MeanReversionScore, MaxDrawdownWindow,
MaxAdverseExcursion, MaxDrawupWindow, RangeFilter, RangeRatio,
GapDetector, GapFillDetector, GapMomentum, GapRangeRatio, GapSignal,
SignedGapSum, AverageGap, AnchoredVwap, LaguerreRsi, BullBearPower,
BullPowerBearPower, VixFix, RocRatio, TypicalPrice, TypicalPriceDeviation,
MedianPrice, MedianCloseDev, MedianReturnDeviation, RollingMAD,
RollingKurtosis, RollingSkewness, RollingReturnKurtosis, RollingSkewReturns,
RollingMaxReturn, RollingMinReturn, RollingCorrelation, RollingHighLowPosition,
RollingHighLowRatio, RollingLowBreak, RollingOpenBias, RollingMaxDd,
AutoCorrelation1, ReturnAutoCorrelation, ReturnDispersion, ReturnIqr,
ReturnPersistence, ReturnSignChanges, ReturnSignSum, ReturnAboveZeroPct,
ReturnOverVolatility, ReturnPercentRank, CumulativeLogReturn,
DailyReturnSkew, DirectionChanges, DirectionalEfficiency, EfficiencyRatio, DownsideDeviation,
EaseOfMovement, FairValueGap, HurstExponent, AverageBarRange,
AverageGain, AverageLoss, AmplitudeRatio, Zscore, ZigZag,
ValueAtRisk5, ConditionalVar5, PayoffRatio, ProfitFactor,
VarianceRatio, ConsolidationScore, SupportTestCount,
CusumPriceChange, NewHighPct, NewHighStreak, NewLowPct,
RelativeBarRange, RelativeClose, TailRatio, TailRatioPct,
BreakoutSignal, MidpointOscillator, IntradaySpreadPct,
OhlcSpread, RobustZScore, RollingShadowBalance, AtrPercentile
Core formulas:
| Indicator | Formula | Warm-up bars |
|---|---|---|
| SMA(n) | sum(close, n) / n |
n |
| EMA(n) | close × k + prev × (1−k), k = 2/(n+1) |
n |
| RSI(n) | 100 − 100 / (1 + avg_gain / avg_loss) Wilder smoothing |
n + 1 |
| ATR(n) | Wilder-smoothed true range | n |
| MACD(f,s,sig) | EMA(f) − EMA(s); signal = EMA(sig) of MACD |
slow + signal |
| Fibonacci(n) | Swing high/low over n bars; 0/23.6/38.2/50/61.8/100% levels |
n |
| VolumeReturnCorrelation(n) | Pearson r between close return and volume | n + 1 |
| PriceEntropyScore(n) | Shannon entropy of up/flat/down bins, normalized to [0,1] | n + 1 |
| VolatilityOfVolatility(n) | Std dev of rolling ATR values | 2n − 1 |
OhlcvSeries Analytics (370+)
OhlcvSeries ships an extensive built-in analytics library. A selection:
Returns & Volatility: realized_volatility, rolling_sharpe, hurst_exponent,
ulcer_index, cvar, skewness, kurtosis, autocorrelation, std_dev,
close_returns, log_returns, drawdown_series, max_drawdown, max_drawdown_pct
Volume: vwap, vwap_deviation, volume_price_correlation, relative_volume,
volume_spike, up_down_volume_ratio, net_volume, volume_weighted_return,
close_above_vwap_pct, volume_coefficient_of_variation, avg_volume_on_up_bars,
avg_volume_on_down_bars
Momentum & Trend: close_momentum, price_velocity, price_acceleration,
close_momentum_ratio, recent_close_trend, trend_strength, trend_consistency,
momentum_score, close_above_ma_streak, bars_above_ma, bars_above_sma
Candle Patterns: count_doji, pct_doji, bullish_engulfing_count,
bearish_engulfing_count, is_hammer, is_shooting_star, is_marubozu,
inside_bar_count, outside_bar_count, candle_symmetry, candle_color_changes
Range & Structure: atr_series, true_range_series, high_low_range,
price_contraction, range_expansion_ratio, close_distance_from_high,
pct_from_low, is_breakout_up, reversal_count, open_gap_fill_rate,
pivot_highs, pivot_lows
Streaks: consecutive_higher_closes, consecutive_higher_highs,
consecutive_lower_lows, longest_winning_streak, longest_losing_streak,
longest_flat_streak, bars_since_new_high, bars_since_new_low
SignalValue Combinators (70+)
SignalValue carries a scalar or Unavailable and propagates unavailability
through every operation:
sv.abs / sv.negate / sv.signum
sv.clamp // clamp to [lo, hi]
sv.cap_at / sv.floor_at // one-sided clamps
sv.lerp // linear interpolation, t ∈ [0, 1]
sv.blend // weighted blend
sv.quantize // round to nearest multiple of step
sv.distance_to // absolute difference
sv.delta // signed change
sv.cross_above // true on upward threshold cross
sv.within_range // boolean range test
sv.as_percent / sv.pct_of // percentage helpers
sv.sign_match // true if same sign
sv.map / sv.zip_with // functor / applicative style
SignalMap Analytics (90+)
SignalMap is the output of SignalPipeline::update. Fleet-wide analytics:
map.average_scalar // mean of all scalar values
map.std_dev / .variance // dispersion
map.z_scores // HashMap<String, f64> z-score per signal
map.entropy // Shannon entropy of the distribution
map.gini_coefficient // Gini inequality coefficient
map.normalize_all // min-max normalize all scalars to [0, 1]
map.top_n / .bottom_n // top/bottom signals by value
map.weighted_sum // dot product with weight map
map.scale_all // multiply all scalars by factor
map.percentile_rank_of // percentile of one signal among all
map.signal_ratio // ratio of two named signals
map.count_positive / .count_negative / .count_zero
map.all_positive / .all_negative
PositionLedger Analytics (145+)
ledger.equity // cash + unrealized P&L
ledger.total_unrealized_pnl // sum of all open position P&L
ledger.concentration_ratio // Herfindahl-Hirschman Index
ledger.long_exposure / .short_exposure // directional gross exposure
ledger.avg_long_entry_price // VWAP of long entries
ledger.avg_short_entry_price // VWAP of short entries
ledger.pct_long / .pct_short // directional balance
ledger.win_rate // % of closed positions with positive P&L
ledger.largest_position / .smallest_position
ledger.symbols_with_unrealized_loss
ledger.risk_reward_ratio
ledger.kelly_fraction
DrawdownTracker Analytics (120+)
tracker.current_drawdown_pct // (peak − equity) / peak × 100
tracker.max_drawdown_pct // worst drawdown seen
tracker.calmar_ratio // annualized return / max drawdown
tracker.sharpe_ratio // using per-update equity changes
tracker.sortino_ratio // downside-deviation adjusted
tracker.win_rate // fraction of updates that gained equity
tracker.avg_gain_pct // average gain per gaining update
tracker.avg_loss_pct // average loss per losing update
tracker.equity_change_std // std dev of per-update equity changes
tracker.gain_loss_asymmetry // ratio of avg gain magnitude to avg loss magnitude
tracker.recovery_factor // net return / max drawdown
tracker.omega_ratio // probability-weighted gain/loss ratio
tracker.equity_multiple // current / initial equity
tracker.return_drawdown_ratio // net return % / worst drawdown %
tracker.streak_win_rate // max_gain_streak / total streak length
tracker.time_to_recover_est // estimated updates to recover from current drawdown
NanoTimestamp Utilities (120+)
now // current UTC nanoseconds
ts.add_days / .sub_days
ts.add_months // calendar-accurate month arithmetic
ts.start_of_week / .end_of_month
ts.start_of_quarter // Jan 1 / Apr 1 / Jul 1 / Oct 1
ts.end_of_quarter // last nanosecond of the quarter
ts.is_same_quarter // same calendar quarter and year
ts.floor_to_hour / .floor_to_minute / .floor_to_second
ts.is_market_hours // 09:30–16:00 ET (approximate)
ts.is_weekend
ts.quarter // 1–4
ts.elapsed_days / .elapsed_hours / .elapsed_minutes
ts.nanoseconds_between
ts.lerp // interpolate two timestamps
Mathematical Definitions
Price and Quantity Types
| Type | Invariant | Backing type |
|---|---|---|
Price |
d > 0 (strictly positive) |
rust_decimal::Decimal |
Quantity |
d >= 0 (non-negative) |
rust_decimal::Decimal |
NanoTimestamp |
any i64; nanoseconds since Unix epoch (UTC) |
i64 |
Symbol |
non-empty, no whitespace | String |
OHLCV Invariants
Every OhlcvBar that enters an OhlcvSeries has been validated to satisfy:
high >= open high >= close
low <= open low <= close
high >= low
Any bar that violates these relationships is rejected with FinError::BarInvariant.
Order Book Guarantees
- Bids are maintained in descending price order (best bid = highest price).
- Asks are maintained in ascending price order (best ask = lowest price).
- Sequence numbers are strictly monotone;
delta.sequencemust equalbook.sequence() + 1. - A delta that would produce
best_bid >= best_askis rejected and the book is rolled back atomically.
Risk Metrics
- Drawdown %:
(peak_equity − current_equity) / peak_equity × 100. Always ≥ 0. MaxDrawdownRuletriggers whendrawdown_pct > threshold_pct(strictly greater).MinEquityRuletriggers whenequity < floor(strictly less).
Position P&L
- Realized P&L (on reduce/close):
closed_qty × (fill_price − avg_cost)for long. - Unrealized P&L:
position_qty × (current_price − avg_cost). - Both are net of commissions.
API Reference
types module
new // d > 0
new // d >= 0
zero // non-empty, no whitespace
now // current UTC nanoseconds
orderbook module
new
.apply_delta .best_bid / .best_ask .spread // best_ask - best_bid
.mid_price .vwap_for_qty .top_bids / .top_asks
ohlcv module
new .push_tick .flush .push .closes .window
// ...370+ analytics methods
signals module
// Signal trait
new
.add // builder pattern; chainable
.update // SignalValue: Scalar(Decimal) | Unavailable
position module
new
.apply_fill .equity .unrealized_pnl_total .realized_pnl_total // ...145+ portfolio analytics methods
risk module
new
.update
.current_drawdown_pct .calmar_ratio // ...120+ risk/statistics methods
new
.add_rule // builder pattern
.update
Custom Implementations
Custom RiskRule
use ;
use Decimal;
Custom Signal
use ;
use OhlcvBar;
use FinError;
Architecture Overview
Tick stream
|
TickReplayer / TickFilter
|
+-----------+-----------+
| |
OhlcvAggregator OrderBook
| (apply_delta)
OhlcvSeries |
(370+ analytics) vwap_for_qty / spread
|
SignalPipeline
(540+ indicators)
|
SignalMap (90+ methods)
|
PositionLedger (145+ methods)
|
DrawdownTracker (120+ methods)
|
RiskMonitor
|
Vec<RiskBreach>
All arrows represent pure data flow. No shared mutable state crosses module
boundaries. Wrap any component in Arc<Mutex<_>> for multi-threaded use.
Performance Notes
- O(1) order book mutations:
apply_deltaperforms a singleBTreeMap::insertorBTreeMap::remove. Inverted-spread check reads two keys and does not allocate. - O(1) streaming indicators:
EmaandRsimaintain constant-size state regardless of history length.Smauses aVecDequecapped atperiodelements. - Zero-copy tick replay:
TickReplayersorts once at construction and returns shared references on each call; no per-tick heap allocation.
Running Tests
The test suite includes unit tests in every module and property-based tests using proptest.
Contributing
- Fork the repository and create a branch from
main. - All public items must have
///doc comments with purpose, arguments, return values, and errors. - All fallible operations must return
Result; nounwrap,expect, orpanic!in non-test code. - Every new behavior must have at least one happy-path test and one edge-case test.
- Run
cargo fmt,cargo clippy -- -D warnings, andcargo testbefore opening a PR.
License
MIT. See LICENSE.
Also used inside tokio-prompt-orchestrator, a production Rust orchestration layer for LLM pipelines.