Streaming / Stateful¶
tulip_rs indicators implement a from_state path: once the initial lookback has been computed, each subsequent bar is updated using only the saved state — no need to reprocess the full history.
All timings are nanoseconds (ns). Lower is better.
- Batch (ns) — full indicator computation over the complete 6,705-bar dataset
- Streaming 1-bar (ns) — time to update one new bar using saved state
- Batch / Streaming — how many times faster the streaming path is vs a full batch recompute
| Indicator | Batch Rust (ns) | Streaming 1-bar (ns) | Batch / Streaming |
|---|---|---|---|
| ad | 4,779 | 25 | 191.2× |
| adosc | 6,556 | 27 | 242.8× |
| adx | 9,999 | 80 | 125.0× |
| adxr | 11,039 | 75 | 147.2× |
| ao | 5,393 | 14 | 385.2× |
| apo | 4,595 | 23 | 199.8× |
| aroon | 17,988 | 38 | 473.4× |
| aroonosc | 19,873 | 33 | 602.2× |
| atr | 4,559 | 23 | 198.2× |
| avgprice | 1,362 | 22 | 61.9× |
| bbands | 7,114 | 34 | 209.2× |
| bop | 2,312 | 24 | 96.3× |
| cci | 55,726 | 40 | 1393.2× |
| chaikinmf | 6,833 | 19 | 359.6× |
| chandelierexit | 17,252 | 38 | 454.0× |
| cmo | 5,959 | 29 | 205.5× |
| cvi | 5,926 | 16 | 370.4× |
| dema | 5,993 | 22 | 272.4× |
| di | 9,713 | 109 | 89.1× |
| dm | 6,611 | 66 | 100.2× |
| donchianchannel | 15,182 | 36 | 421.7× |
| dpo | 2,528 | 24 | 105.3× |
| dx | 8,441 | 66 | 127.9× |
| ef | 4,574 | 25 | 183.0× |
| elderray | 6,197 | 25 | 247.9× |
| ema | 4,547 | 14 | 324.8× |
| emv | 2,295 | 24 | 95.6× |
| fisher | 48,523 | 36 | 1347.9× |
| fosc | 7,513 | 32 | 234.8× |
| hma | 8,114 | 31 | 261.7× |
| kama | 6,892 | 24 | 287.2× |
| keltnerchannel | 6,182 | 33 | 187.3× |
| kvo | 9,068 | 30 | 302.3× |
| linreg | 6,228 | 29 | 214.8× |
| macd | 7,045 | 21 | 335.5× |
| marketfi | 2,309 | 24 | 96.2× |
| mass | 5,568 | 18 | 309.3× |
| max | 5,360 | 27 | 198.5× |
| md | 12,120 | 28 | 432.9× |
| medprice | 1,009 | 23 | 43.9× |
| mfi | 7,513 | 27 | 278.3× |
| min | 7,808 | 28 | 278.9× |
| mom | 838 | 26 | 32.2× |
| msw | 625,817 | 114 | 5489.6× |
| natr | 4,712 | 26 | 181.2× |
| nvi | 2,395 | 23 | 104.1× |
| obv | 3,325 | 23 | 144.6× |
| ppo | 4,823 | 25 | 192.9× |
| psar | 10,055 | 25 | 402.2× |
| pvi | 2,400 | 23 | 104.3× |
| qstick | 2,731 | 27 | 101.1× |
| roc | 2,294 | 26 | 88.2× |
| rocr | 2,289 | 26 | 88.0× |
| rsi | 4,719 | 69 | 68.4× |
| sma | 2,451 | 24 | 102.1× |
| smaenvelope | 7,266 | 31 | 234.4× |
| stddev | 3,601 | 30 | 120.0× |
| stoch | 20,391 | 40 | 509.8× |
| stochrsi | 19,106 | 44 | 434.2× |
| tema | 6,734 | 26 | 259.0× |
| tr | 1,545 | 23 | 67.2× |
| trima | 5,408 | 25 | 216.3× |
| trix | 6,457 | 27 | 239.1× |
| trvi | 6,010 | 19 | 316.3× |
| tsf | 6,270 | 29 | 216.2× |
| typprice | 1,128 | 14 | 80.6× |
| ultosc | 16,033 | 28 | 572.6× |
| vhf | 14,842 | 29 | 511.8× |
| vidya | 11,607 | 35 | 331.6× |
| volatility | 8,689 | 29 | 299.6× |
| vortex | 7,504 | 28 | 268.0× |
| vosc | 3,791 | 27 | 140.4× |
| vwma | 3,310 | 30 | 110.3× |
| wad | 3,751 | 23 | 163.1× |
| wcprice | 1,058 | 22 | 48.1× |
| wilders | 4,536 | 14 | 324.0× |
| willr | 17,218 | 34 | 506.4× |
| wma | 6,155 | 16 | 384.7× |
| zlema | 5,716 | 24 | 238.2× |
RustTa processes data one bar at a time (streaming), so its batch time is effectively its per-update cost × 6,705 bars. The comparison below shows tulip_rs streaming (single-bar) vs RustTa's full-batch equivalent for 20 indicators.
| Indicator | tulip_rs Streaming 1-bar (ns) | RustTa Batch (ns) | RustTa / tulip_rs |
|---|---|---|---|
| atr | 23 | 9,342 | 406× |
| bbands | 34 | 8,093 | 238× |
| cci | 40 | 65,098 | 1627× |
| chandelierexit | 38 | 42,341 | 1114× |
| ef | 25 | 26,694 | 1068× |
| ema | 14 | 7,919 | 566× |
| keltnerchannel | 33 | 12,597 | 382× |
| macd | 21 | 7,891 | 376× |
| max | 27 | 17,229 | 638× |
| md | 28 | 26,952 | 963× |
| mfi | 27 | 23,766 | 880× |
| min | 28 | 22,910 | 818× |
| obv | 23 | 5,216 | 227× |
| ppo | 25 | 7,900 | 316× |
| roc | 26 | 2,860 | 110× |
| rsi | 69 | 7,909 | 115× |
| sma | 24 | 4,533 | 189× |
| stddev | 30 | 8,346 | 278× |
| stoch | 40 | 46,721 | 1168× |
| tr | 23 | 7,502 | 326× |
Key findings
- All 79 indicators implement the stateful streaming path
- Median streaming time: ~27 ns per bar update
- Fastest —
ao,ema,typprice,wildersat 14 ns/bar - Slowest —
mswat 114 ns/bar - The streaming path is 100–5,489× faster than full batch recompute depending on the indicator
tulip_rsstreaming is 100–1,627× faster than RustTa's effective per-update cost across 20 indicators
| Rank | Indicator | Batch / Streaming | Why streaming wins so much |
|---|---|---|---|
| 1 | msw |
5490× | Mesa Sine Wave requires FFT-style computation over the full window |
| 2 | cci |
1393× | Large rolling sum + mean deviation computed over every bar in batch |
| 3 | fisher |
1348× | Complex normalisation over entire input range |
| 4 | aroonosc |
602× | Full lookback window scan for highest/lowest on every batch call |
| 5 | ultosc |
573× | Three-period weighted TR average; all periods recomputed in batch |
| 6 | vhf |
512× | Rolling highest high / lowest low + sum of price changes |
| 7 | stoch |
510× | Rolling high/low window scan |
| 8 | willr |
506× | Rolling high/low window scan |
| 9 | aroon |
473× | Same as aroonosc |
| 10 | chandelierexit |
454× | Rolling highest high / lowest low + ATR across full window in batch |