1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//! Abstractions for stream aggregation that we call "Indicator" s.
//!
//! This crate provides abstractions of different levels to build indicators:
//!
//! - Indicators are the combinations of [`Operator`]s. We can chain them by [`OperatorExt::then`]
//! and apply them to the same input "simultaneously" by [`OperatorExt::facet`].
//!
//! - To handle [Time series] better, we introduced utils for ticked operators, which are defined in [`TickedOperatorExt`],
//! of which the input and output are both [`Tickable`] and sharing the same [`Tick`].
//! We provide many ticked version utils. For example, we can apply different [`TickedOperatorExt`]s
//! (using [`TickedOperatorExt::facet_t`] or [`ticked::FacetMap`]) to the same [`Tickable`] stream to
//! get a "synced" result stream of the combined outputs of those operators sharing the same [`Tick`]
//! of theirs input. Each item of a "synced" stream will have the form of `TickValue<(O1, O2)>`.
//!
//! - [`TumblingOperator`]s are defined by some operations on events of non-overlapping time windows ([`TumblingWindow`]).
//! [Moving average] is one of the famous examples, which is defined by the average of the numbers
//! from those events occur in the same tumbling window. We call those operations [`TumblingOperation`]s.
//! We can use [`tumbling`] function to create a [`TumblingOperator`] from a [`TumblingOperation`].
//!
//! - Finally, we can apply the indicators to [`Iterator`]s or [`Stream`](futures::stream::Stream)s
//! by using [`IndicatorIteratorExt::indicator`] or [`IndicatorStreamExt::indicator`] accordingly.
//!
//!
//! [Time series]: https://en.wikipedia.org/wiki/Time_series
//! [Moving average]: https://en.wikipedia.org/wiki/Moving_average
//!
//! # Example
//! ```
//! use indicator::*;
//! use rust_decimal::Decimal;
//! use rust_decimal_macros::dec;
//! use time::macros::offset;
//! use arrayvec::ArrayVec;
//!
//! /// Return an indicator that calculates `hl2` and `ohlc4` simultaneously.
//! fn hl2_ohlc4(period: Period) -> impl Operator<TickValue<Decimal>, Output = (Decimal, Decimal)> {
//!     tumbling(
//!         period,
//!         |_w: &ArrayVec<[Decimal; 4], 0>, y: &mut Option<[Decimal; 4]>, x| match y {
//!             Some(ohlc) => {
//!                 ohlc[1] = ohlc[1].max(x);
//!                 ohlc[2] = ohlc[2].min(x);
//!                 ohlc[3] = x;
//!                 *ohlc
//!             }
//!             None => {
//!                 let ohlc = [x; 4];
//!                 *y = Some(ohlc);
//!                 ohlc
//!             }
//!         },
//!     )
//!     .then(facet_t(
//!         map_t(|ohlc: [Decimal; 4]| (ohlc[1] + ohlc[2]) / dec!(2)),
//!         map_t(|ohlc: [Decimal; 4]| (ohlc[0] + ohlc[1] + ohlc[2] + ohlc[3]) / dec!(4)),
//!     ))
//!     .map(|v| v.value)
//! }
//!```

#![deny(missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(feature = "alloc")]
extern crate alloc;

/// Operator.
pub mod operator;

/// Time window.
pub mod window;

/// Ticked operators.
pub mod ticked;

/// Iterator extension trait.
pub mod iter;

/// Operator using GAT.
#[cfg(feature = "gat")]
pub mod gat;

#[cfg(feature = "stream")]
/// Stream extension trait.
pub mod stream;

/// Rayon supported combinator.
#[cfg(feature = "parallel")]
pub mod rayon;

/// Async operator support.
#[cfg(feature = "async")]
pub mod async_operator;

/// Reactive streams pattern.
#[cfg(feature = "reactive")]
pub mod reactive;

/// Prelude.
pub mod prelude {
    #[cfg(feature = "gat")]
    pub use crate::gat::*;
    pub use crate::operator::{BoxOperator, LocalBoxOperator, Operator, OperatorExt};
    pub use crate::window::{Period, Tick, TickValue, TumblingWindow};
}

pub use iter::IndicatorIteratorExt;
pub use operator::{facet, map, Operator, OperatorExt};
pub use ticked::{
    facet_t, map_t,
    tumbling::{
        cached, iterated, tumbling, Cached, CachedOperation, Iterated, IteratedOperation,
        QueueCapAtLeast, TumblingOperation, TumblingOperator, TumblingQueue,
    },
    tuple_t, TickedOperatorExt,
};
pub use window::{Period, PeriodKind, Tick, TickValue, Tickable, TumblingWindow};

#[cfg(feature = "std")]
pub use ticked::facet_map_t;

#[cfg(feature = "std")]
pub use facet::facet_map;

#[cfg(feature = "std")]
pub use ticked::{shared, SharedMap};

#[cfg(feature = "stream")]
pub use stream::IndicatorStreamExt;

#[cfg(feature = "array-vec")]
pub use ticked::array_t;

#[cfg(feature = "async")]
pub use async_operator::AsyncOperator;

#[cfg(feature = "tower")]
pub use async_operator::ServiceOperator;