indicator/lib.rs
1//! Abstractions for stream aggregation that we call "Indicator" s.
2//!
3//! This crate provides abstractions of different levels to build indicators:
4//!
5//! - Indicators are the combinations of [`Operator`]s. We can chain them by [`OperatorExt::then`]
6//! and apply them to the same input "simultaneously" by [`OperatorExt::facet`].
7//!
8//! - To handle [Time series] better, we introduced utils for ticked operators, which are defined in [`TickedOperatorExt`],
9//! of which the input and output are both [`Tickable`] and sharing the same [`Tick`].
10//! We provide many ticked version utils. For example, we can apply different [`TickedOperatorExt`]s
11//! (using [`TickedOperatorExt::facet_t`] or [`ticked::FacetMap`]) to the same [`Tickable`] stream to
12//! get a "synced" result stream of the combined outputs of those operators sharing the same [`Tick`]
13//! of theirs input. Each item of a "synced" stream will have the form of `TickValue<(O1, O2)>`.
14//!
15//! - [`TumblingOperator`]s are defined by some operations on events of non-overlapping time windows ([`TumblingWindow`]).
16//! [Moving average] is one of the famous examples, which is defined by the average of the numbers
17//! from those events occur in the same tumbling window. We call those operations [`TumblingOperation`]s.
18//! We can use [`tumbling`] function to create a [`TumblingOperator`] from a [`TumblingOperation`].
19//!
20//! - Finally, we can apply the indicators to [`Iterator`]s or [`Stream`](futures::stream::Stream)s
21//! by using [`IndicatorIteratorExt::indicator`] or [`IndicatorStreamExt::indicator`] accordingly.
22//!
23//!
24//! [Time series]: https://en.wikipedia.org/wiki/Time_series
25//! [Moving average]: https://en.wikipedia.org/wiki/Moving_average
26//!
27//! # Example
28//! ```
29//! use indicator::*;
30//! use rust_decimal::Decimal;
31//! use rust_decimal_macros::dec;
32//! use time::macros::offset;
33//! use arrayvec::ArrayVec;
34//!
35//! /// Return an indicator that calculates `hl2` and `ohlc4` simultaneously.
36//! fn hl2_ohlc4(period: Period) -> impl Operator<TickValue<Decimal>, Output = (Decimal, Decimal)> {
37//! tumbling(
38//! period,
39//! |_w: &ArrayVec<[Decimal; 4], 0>, y: &mut Option<[Decimal; 4]>, x| match y {
40//! Some(ohlc) => {
41//! ohlc[1] = ohlc[1].max(x);
42//! ohlc[2] = ohlc[2].min(x);
43//! ohlc[3] = x;
44//! *ohlc
45//! }
46//! None => {
47//! let ohlc = [x; 4];
48//! *y = Some(ohlc);
49//! ohlc
50//! }
51//! },
52//! )
53//! .then(facet_t(
54//! map_t(|ohlc: [Decimal; 4]| (ohlc[1] + ohlc[2]) / dec!(2)),
55//! map_t(|ohlc: [Decimal; 4]| (ohlc[0] + ohlc[1] + ohlc[2] + ohlc[3]) / dec!(4)),
56//! ))
57//! .map(|v| v.value)
58//! }
59//!```
60
61#![deny(missing_docs)]
62#![cfg_attr(not(feature = "std"), no_std)]
63
64#[cfg(feature = "alloc")]
65extern crate alloc;
66
67/// Operator.
68pub mod operator;
69
70/// Time window.
71pub mod window;
72
73/// Ticked operators.
74pub mod ticked;
75
76/// Iterator extension trait.
77pub mod iter;
78
79/// Operator using GAT.
80#[cfg(feature = "gat")]
81pub mod gat;
82
83#[cfg(feature = "stream")]
84/// Stream extension trait.
85pub mod stream;
86
87/// Rayon supported combinator.
88#[cfg(feature = "parallel")]
89pub mod rayon;
90
91/// Async operator support.
92#[cfg(feature = "async")]
93pub mod async_operator;
94
95/// Reactive streams pattern.
96#[cfg(feature = "reactive")]
97pub mod reactive;
98
99/// Context Pattern.
100#[cfg(feature = "context")]
101pub mod context;
102
103/// Prelude.
104pub mod prelude {
105 #[cfg(feature = "context")]
106 pub use crate::context::{
107 extractor::{Data, Env, In, Prev},
108 input, insert_and_output, insert_env_and_output,
109 layer::{layer_fn, stack::id_layer, BoxLayer, Layer, LayerExt},
110 output, BoxContextOperator, ContextOperator, ContextOperatorExt, Value, ValueRef,
111 };
112 #[cfg(feature = "gat")]
113 pub use crate::gat::*;
114 pub use crate::operator::{BoxOperator, LocalBoxOperator, Operator, OperatorExt};
115 pub use crate::window::{Period, Tick, TickValue, TumblingWindow};
116 #[cfg(feature = "indicator_macros")]
117 pub use indicator_macros::*;
118}
119
120#[cfg(feature = "indicator_macros")]
121pub use indicator_macros as macros;
122
123pub use iter::IndicatorIteratorExt;
124pub use operator::{facet, map, Operator, OperatorExt};
125pub use ticked::{
126 facet_t, map_t,
127 tumbling::{
128 cached, iterated, tumbling, Cached, CachedOperation, Iterated, IteratedOperation,
129 QueueCapAtLeast, TumblingOperation, TumblingOperator, TumblingQueue,
130 },
131 tuple_t, TickedOperatorExt,
132};
133pub use window::{Period, PeriodKind, Tick, TickValue, Tickable, TumblingWindow};
134
135#[cfg(feature = "std")]
136pub use ticked::facet_map_t;
137
138#[cfg(feature = "std")]
139pub use facet::facet_map;
140
141#[cfg(feature = "std")]
142pub use ticked::{shared, SharedMap};
143
144#[cfg(feature = "stream")]
145pub use stream::IndicatorStreamExt;
146
147#[cfg(feature = "array-vec")]
148pub use ticked::array_t;
149
150#[cfg(feature = "async")]
151pub use async_operator::AsyncOperator;
152
153#[cfg(feature = "tower")]
154pub use async_operator::ServiceOperator;