finance_query/backtesting/refs/
volume.rs1use crate::backtesting::strategy::StrategyContext;
2use crate::indicators::Indicator;
3
4use super::IndicatorRef;
5
6#[derive(Debug, Clone, Copy)]
8pub struct ObvRef;
9
10impl IndicatorRef for ObvRef {
11 fn key(&self) -> &str {
12 "obv"
13 }
14
15 fn required_indicators(&self) -> Vec<(String, Indicator)> {
16 vec![("obv".to_string(), Indicator::Obv)]
17 }
18
19 fn value(&self, ctx: &StrategyContext) -> Option<f64> {
20 ctx.indicator(self.key())
21 }
22
23 fn prev_value(&self, ctx: &StrategyContext) -> Option<f64> {
24 ctx.indicator_prev(self.key())
25 }
26}
27
28#[inline]
30pub fn obv() -> ObvRef {
31 ObvRef
32}
33
34#[derive(Debug, Clone, Copy)]
36pub struct VwapRef;
37
38impl IndicatorRef for VwapRef {
39 fn key(&self) -> &str {
40 "vwap"
41 }
42
43 fn required_indicators(&self) -> Vec<(String, Indicator)> {
44 vec![("vwap".to_string(), Indicator::Vwap)]
45 }
46
47 fn value(&self, ctx: &StrategyContext) -> Option<f64> {
48 ctx.indicator(self.key())
49 }
50
51 fn prev_value(&self, ctx: &StrategyContext) -> Option<f64> {
52 ctx.indicator_prev(self.key())
53 }
54}
55
56#[inline]
58pub fn vwap() -> VwapRef {
59 VwapRef
60}
61
62#[derive(Debug, Clone)]
64pub struct CmfRef {
65 pub period: usize,
66 key: String,
67}
68
69impl IndicatorRef for CmfRef {
70 fn key(&self) -> &str {
71 &self.key
72 }
73
74 fn required_indicators(&self) -> Vec<(String, Indicator)> {
75 vec![(self.key.clone(), Indicator::Cmf(self.period))]
76 }
77
78 fn value(&self, ctx: &StrategyContext) -> Option<f64> {
79 ctx.indicator(self.key())
80 }
81
82 fn prev_value(&self, ctx: &StrategyContext) -> Option<f64> {
83 ctx.indicator_prev(self.key())
84 }
85}
86
87#[inline]
89pub fn cmf(period: usize) -> CmfRef {
90 CmfRef {
91 period,
92 key: format!("cmf_{period}"),
93 }
94}
95
96#[derive(Debug, Clone, Copy)]
98pub struct AccumulationDistributionRef;
99
100#[inline]
102pub fn accumulation_distribution() -> AccumulationDistributionRef {
103 AccumulationDistributionRef
104}
105
106impl IndicatorRef for AccumulationDistributionRef {
107 fn key(&self) -> &str {
108 "ad"
109 }
110
111 fn required_indicators(&self) -> Vec<(String, Indicator)> {
112 vec![("ad".to_string(), Indicator::AccumulationDistribution)]
113 }
114
115 fn value(&self, ctx: &StrategyContext) -> Option<f64> {
116 ctx.indicator(self.key())
117 }
118
119 fn prev_value(&self, ctx: &StrategyContext) -> Option<f64> {
120 ctx.indicator_prev(self.key())
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127 use crate::backtesting::refs::{balance_of_power, chaikin_oscillator, mfi};
128
129 #[test]
130 fn test_volume_keys() {
131 assert_eq!(obv().key(), "obv");
132 assert_eq!(vwap().key(), "vwap");
133 assert_eq!(mfi(14).key(), "mfi_14");
134 assert_eq!(cmf(20).key(), "cmf_20");
135 assert_eq!(chaikin_oscillator().key(), "chaikin_osc");
136 assert_eq!(accumulation_distribution().key(), "ad");
137 assert_eq!(balance_of_power(Some(14)).key(), "bop_14");
138 assert_eq!(balance_of_power(None).key(), "bop");
139 }
140}