1#[macro_export]
3macro_rules! native_pointwise_1 {
4 ($name:ident, $op:expr) => {
5 #[derive(Debug, Clone, Default)]
6 #[allow(non_camel_case_types)]
7 pub struct $name;
8
9 impl $name {
10 pub fn new() -> Self {
11 Self
12 }
13 }
14
15 impl $crate::traits::Next<f64> for $name {
16 type Output = f64;
17
18 fn next(&mut self, input: f64) -> Self::Output {
19 ($op)(input)
20 }
21
22 fn next_batch(&mut self, inputs: &[f64]) -> Vec<Self::Output>
23 where
24 f64: Copy,
25 {
26 inputs.iter().map(|&x| ($op)(x)).collect()
27 }
28 }
29 };
30}
31
32#[macro_export]
34macro_rules! native_binary_2 {
35 ($name:ident, $op:expr) => {
36 #[derive(Debug, Clone, Default)]
37 #[allow(non_camel_case_types)]
38 pub struct $name;
39
40 impl $name {
41 pub fn new() -> Self {
42 Self
43 }
44 }
45
46 impl $crate::traits::Next<(f64, f64)> for $name {
47 type Output = f64;
48
49 fn next(&mut self, (a, b): (f64, f64)) -> Self::Output {
50 ($op)(a, b)
51 }
52
53 fn next_batch(&mut self, inputs: &[(f64, f64)]) -> Vec<Self::Output>
54 where
55 (f64, f64): Copy,
56 {
57 inputs.iter().map(|&(a, b)| ($op)(a, b)).collect()
58 }
59 }
60 };
61}
62
63#[macro_export]
65macro_rules! native_cdl {
66 ($name:ident, $talib_func:path) => {
67 #[derive(Debug, Clone)]
68 #[allow(non_camel_case_types)]
69 pub struct $name {
70 open: Vec<f64>,
71 high: Vec<f64>,
72 low: Vec<f64>,
73 close: Vec<f64>,
74 }
75
76 impl $name {
77 const MAX_WINDOW: usize = 32;
78
79 pub fn new() -> Self {
80 Self {
81 open: Vec::with_capacity(Self::MAX_WINDOW),
82 high: Vec::with_capacity(Self::MAX_WINDOW),
83 low: Vec::with_capacity(Self::MAX_WINDOW),
84 close: Vec::with_capacity(Self::MAX_WINDOW),
85 }
86 }
87
88 #[inline]
89 fn trim_window(o: &mut Vec<f64>, h: &mut Vec<f64>, l: &mut Vec<f64>, c: &mut Vec<f64>) {
90 let max = Self::MAX_WINDOW;
91 if o.len() > max {
92 let drop = o.len() - max;
93 o.drain(0..drop);
94 h.drain(0..drop);
95 l.drain(0..drop);
96 c.drain(0..drop);
97 }
98 }
99
100 #[inline]
101 fn last_signal(o: &[f64], h: &[f64], l: &[f64], c: &[f64]) -> f64 {
102 $talib_func(o, h, l, c)
103 .ok()
104 .and_then(|res| res.last().copied())
105 .unwrap_or(0) as f64
106 }
107 }
108
109 impl $crate::traits::Next<(f64, f64, f64, f64)> for $name {
110 type Output = f64;
111
112 fn next(&mut self, (open, high, low, close): (f64, f64, f64, f64)) -> Self::Output {
113 self.open.push(open);
114 self.high.push(high);
115 self.low.push(low);
116 self.close.push(close);
117 Self::trim_window(
118 &mut self.open,
119 &mut self.high,
120 &mut self.low,
121 &mut self.close,
122 );
123 Self::last_signal(&self.open, &self.high, &self.low, &self.close)
124 }
125
126 fn next_batch(&mut self, inputs: &[(f64, f64, f64, f64)]) -> Vec<Self::Output>
127 where
128 (f64, f64, f64, f64): Copy,
129 {
130 self.open.clear();
131 self.high.clear();
132 self.low.clear();
133 self.close.clear();
134 for &(o, h, l, c) in inputs {
135 self.open.push(o);
136 self.high.push(h);
137 self.low.push(l);
138 self.close.push(c);
139 }
140 $talib_func(&self.open, &self.high, &self.low, &self.close)
141 .unwrap_or_default()
142 .into_iter()
143 .map(|v| v as f64)
144 .collect()
145 }
146 }
147 };
148}
149
150#[macro_export]
151macro_rules! talib_cdl {
152 ($name:ident, $talib_func:path) => {
153 #[derive(Debug, Clone)]
154 #[allow(non_camel_case_types)]
155 pub struct $name {
156 history_open: Vec<f64>,
157 history_high: Vec<f64>,
158 history_low: Vec<f64>,
159 history_close: Vec<f64>,
160 }
161
162 impl $name {
163 pub fn new() -> Self {
164 Self {
165 history_open: Vec::new(),
166 history_high: Vec::new(),
167 history_low: Vec::new(),
168 history_close: Vec::new(),
169 }
170 }
171 }
172
173 impl $crate::traits::Next<(f64, f64, f64, f64)> for $name {
174 type Output = f64;
175
176 fn next(&mut self, (open, high, low, close): (f64, f64, f64, f64)) -> Self::Output {
177 self.history_open.push(open);
178 self.history_high.push(high);
179 self.history_low.push(low);
180 self.history_close.push(close);
181 if let Ok(res) = $talib_func(
182 &self.history_open,
183 &self.history_high,
184 &self.history_low,
185 &self.history_close,
186 ) {
187 *res.last().unwrap_or(&0) as f64
188 } else {
189 0.0
190 }
191 }
192
193 fn next_batch(&mut self, inputs: &[(f64, f64, f64, f64)]) -> Vec<Self::Output>
194 where
195 (f64, f64, f64, f64): Copy,
196 {
197 self.history_open.clear();
198 self.history_high.clear();
199 self.history_low.clear();
200 self.history_close.clear();
201 for &(o, h, l, c) in inputs {
202 self.history_open.push(o);
203 self.history_high.push(h);
204 self.history_low.push(l);
205 self.history_close.push(c);
206 }
207 $talib_func(
208 &self.history_open,
209 &self.history_high,
210 &self.history_low,
211 &self.history_close,
212 )
213 .unwrap_or_default()
214 .into_iter()
215 .map(|v| v as f64)
216 .collect()
217 }
218 }
219 };
220}
221
222#[macro_export]
223macro_rules! talib_1_in_1_out_i32 {
224 ($name:ident, $talib_func:path $(, $param:ident: $ptype:ty)*) => {
225 #[derive(Debug, Clone)]
226 #[allow(non_camel_case_types)]
227 pub struct $name {
228 $( pub $param: $ptype, )*
229 history: Vec<f64>,
230 }
231
232 impl $name {
233 pub fn new($( $param: $ptype ),*) -> Self {
234 Self {
235 $( $param, )*
236 history: Vec::new(),
237 }
238 }
239 }
240
241 impl $crate::traits::Next<f64> for $name {
242 type Output = f64;
243
244 fn next(&mut self, input: f64) -> Self::Output {
245 self.history.push(input);
246 if let Ok(res) = $talib_func(&self.history, $( self.$param.clone() ),*) {
247 *res.last().unwrap_or(&0) as f64
248 } else {
249 0.0
250 }
251 }
252 }
253 };
254}
255
256#[macro_export]
257macro_rules! talib_1_in_1_out_no_result {
258 ($name:ident, $talib_func:path) => {
259 #[derive(Debug, Clone)]
260 #[allow(non_camel_case_types)]
261 pub struct $name {
262 history: Vec<f64>,
263 }
264
265 impl $name {
266 pub fn new() -> Self {
267 Self {
268 history: Vec::new(),
269 }
270 }
271 }
272
273 impl $crate::traits::Next<f64> for $name {
274 type Output = f64;
275
276 fn next(&mut self, input: f64) -> Self::Output {
277 self.history.push(input);
278 let res = $talib_func(&self.history);
279 *res.last().unwrap_or(&f64::NAN)
280 }
281 }
282 };
283}
284
285#[macro_export]
286macro_rules! talib_1_in_1_out {
287 ($name:ident, $talib_func:path $(, $param:ident: $ptype:ty)*) => {
288 #[derive(Debug, Clone)]
289 #[allow(non_camel_case_types)]
290 pub struct $name {
291 $( pub $param: $ptype, )*
292 history: Vec<f64>,
293 }
294
295 impl $name {
296 pub fn new($( $param: $ptype ),*) -> Self {
297 Self {
298 $( $param, )*
299 history: Vec::new(),
300 }
301 }
302 }
303
304 impl $crate::traits::Next<f64> for $name {
305 type Output = f64;
306
307 fn next(&mut self, input: f64) -> Self::Output {
308 self.history.push(input);
309 let res = $talib_func(&self.history, $( self.$param.clone() ),*).unwrap_or_default();
310 *res.last().unwrap_or(&f64::NAN)
311 }
312
313 fn next_batch(&mut self, inputs: &[f64]) -> Vec<Self::Output>
314 where
315 f64: Copy,
316 {
317 self.history.clear();
318 self.history.extend_from_slice(inputs);
319 $talib_func(&self.history, $( self.$param.clone() ),*).unwrap_or_default()
320 }
321 }
322 };
323}
324
325#[macro_export]
326macro_rules! talib_2_in_1_out {
327 ($name:ident, $talib_func:path $(, $param:ident: $ptype:ty)*) => {
328 #[derive(Debug, Clone)]
329 #[allow(non_camel_case_types)]
330 pub struct $name {
331 $( pub $param: $ptype, )*
332 history_high: Vec<f64>,
333 history_low: Vec<f64>,
334 }
335
336 impl $name {
337 #[allow(clippy::too_many_arguments)]
338 pub fn new($( $param: $ptype ),*) -> Self {
339 Self {
340 $( $param, )*
341 history_high: Vec::new(),
342 history_low: Vec::new(),
343 }
344 }
345 }
346
347 impl $crate::traits::Next<(f64, f64)> for $name {
348 type Output = f64;
349
350 fn next(&mut self, (high, low): (f64, f64)) -> Self::Output {
351 self.history_high.push(high);
352 self.history_low.push(low);
353 let res = $talib_func(&self.history_high, &self.history_low, $( self.$param.clone() ),*).unwrap_or_default();
354 *res.last().unwrap_or(&f64::NAN)
355 }
356
357 fn next_batch(&mut self, inputs: &[(f64, f64)]) -> Vec<Self::Output>
358 where
359 (f64, f64): Copy,
360 {
361 self.history_high.clear();
362 self.history_low.clear();
363 for &(h, l) in inputs {
364 self.history_high.push(h);
365 self.history_low.push(l);
366 }
367 $talib_func(&self.history_high, &self.history_low, $( self.$param.clone() ),*).unwrap_or_default()
368 }
369 }
370 };
371}
372
373#[macro_export]
374macro_rules! talib_1_in_2_out {
375 ($name:ident, $talib_func:path $(, $param:ident: $ptype:ty)*) => {
376 #[derive(Debug, Clone)]
377 #[allow(non_camel_case_types)]
378 pub struct $name {
379 $( pub $param: $ptype, )*
380 history: Vec<f64>,
381 }
382
383 impl $name {
384 pub fn new($( $param: $ptype ),*) -> Self {
385 Self {
386 $( $param, )*
387 history: Vec::new(),
388 }
389 }
390 }
391
392 impl $crate::traits::Next<f64> for $name {
393 type Output = (f64, f64);
394
395 fn next(&mut self, input: f64) -> Self::Output {
396 self.history.push(input);
397 if let Ok((res1, res2)) = $talib_func(&self.history, $( self.$param.clone() ),*) {
398 (*res1.last().unwrap_or(&f64::NAN), *res2.last().unwrap_or(&f64::NAN))
399 } else {
400 (f64::NAN, f64::NAN)
401 }
402 }
403
404 fn next_batch(&mut self, inputs: &[f64]) -> Vec<Self::Output>
405 where
406 f64: Copy,
407 {
408 self.history.clear();
409 self.history.extend_from_slice(inputs);
410 if let Ok((r1, r2)) = $talib_func(&self.history, $( self.$param.clone() ),*) {
411 r1.into_iter().zip(r2).map(|(a, b)| (a, b)).collect()
412 } else {
413 vec![(f64::NAN, f64::NAN); inputs.len()]
414 }
415 }
416 }
417 };
418}
419
420#[macro_export]
421macro_rules! talib_1_in_3_out {
422 ($name:ident, $talib_func:path $(, $param:ident: $ptype:ty)*) => {
423 #[derive(Debug, Clone)]
424 #[allow(non_camel_case_types)]
425 pub struct $name {
426 $( pub $param: $ptype, )*
427 history: Vec<f64>,
428 }
429
430 impl $name {
431 pub fn new($( $param: $ptype ),*) -> Self {
432 Self {
433 $( $param, )*
434 history: Vec::new(),
435 }
436 }
437 }
438
439 impl $crate::traits::Next<f64> for $name {
440 type Output = (f64, f64, f64);
441
442 fn next(&mut self, input: f64) -> Self::Output {
443 self.history.push(input);
444 if let Ok((res1, res2, res3)) = $talib_func(&self.history, $( self.$param.clone() ),*) {
445 (*res1.last().unwrap_or(&f64::NAN), *res2.last().unwrap_or(&f64::NAN), *res3.last().unwrap_or(&f64::NAN))
446 } else {
447 (f64::NAN, f64::NAN, f64::NAN)
448 }
449 }
450
451 fn next_batch(&mut self, inputs: &[f64]) -> Vec<Self::Output>
452 where
453 f64: Copy,
454 {
455 self.history.clear();
456 self.history.extend_from_slice(inputs);
457 if let Ok((r1, r2, r3)) = $talib_func(&self.history, $( self.$param.clone() ),*) {
458 r1.into_iter()
459 .zip(r2)
460 .zip(r3)
461 .map(|((a, b), c)| (a, b, c))
462 .collect()
463 } else {
464 vec![(f64::NAN, f64::NAN, f64::NAN); inputs.len()]
465 }
466 }
467 }
468 };
469}
470
471#[macro_export]
472macro_rules! talib_2_in_2_out {
473 ($name:ident, $talib_func:path $(, $param:ident: $ptype:ty)*) => {
474 #[derive(Debug, Clone)]
475 #[allow(non_camel_case_types)]
476 pub struct $name {
477 $( pub $param: $ptype, )*
478 history_1: Vec<f64>,
479 history_2: Vec<f64>,
480 }
481
482 impl $name {
483 pub fn new($( $param: $ptype ),*) -> Self {
484 Self {
485 $( $param, )*
486 history_1: Vec::new(),
487 history_2: Vec::new(),
488 }
489 }
490 }
491
492 impl $crate::traits::Next<(f64, f64)> for $name {
493 type Output = (f64, f64);
494
495 fn next(&mut self, (in1, in2): (f64, f64)) -> Self::Output {
496 self.history_1.push(in1);
497 self.history_2.push(in2);
498 if let Ok((res1, res2)) = $talib_func(&self.history_1, &self.history_2, $( self.$param.clone() ),*) {
499 (*res1.last().unwrap_or(&f64::NAN), *res2.last().unwrap_or(&f64::NAN))
500 } else {
501 (f64::NAN, f64::NAN)
502 }
503 }
504
505 fn next_batch(&mut self, inputs: &[(f64, f64)]) -> Vec<Self::Output>
506 where
507 (f64, f64): Copy,
508 {
509 self.history_1.clear();
510 self.history_2.clear();
511 for &(a, b) in inputs {
512 self.history_1.push(a);
513 self.history_2.push(b);
514 }
515 if let Ok((r1, r2)) = $talib_func(&self.history_1, &self.history_2, $( self.$param.clone() ),*) {
516 r1.into_iter().zip(r2).map(|(x, y)| (x, y)).collect()
517 } else {
518 vec![(f64::NAN, f64::NAN); inputs.len()]
519 }
520 }
521 }
522 };
523}
524
525#[macro_export]
526macro_rules! talib_3_in_1_out {
527 ($name:ident, $talib_func:path $(, $param:ident: $ptype:ty)*) => {
528 #[derive(Debug, Clone)]
529 #[allow(non_camel_case_types)]
530 pub struct $name {
531 $( pub $param: $ptype, )*
532 history_high: Vec<f64>,
533 history_low: Vec<f64>,
534 history_close: Vec<f64>,
535 }
536
537 impl $name {
538 pub fn new($( $param: $ptype ),*) -> Self {
539 Self {
540 $( $param, )*
541 history_high: Vec::new(),
542 history_low: Vec::new(),
543 history_close: Vec::new(),
544 }
545 }
546 }
547
548 impl $crate::traits::Next<(f64, f64, f64)> for $name {
549 type Output = f64;
550
551 fn next(&mut self, (high, low, close): (f64, f64, f64)) -> Self::Output {
552 self.history_high.push(high);
553 self.history_low.push(low);
554 self.history_close.push(close);
555 let res = $talib_func(&self.history_high, &self.history_low, &self.history_close, $( self.$param.clone() ),*).unwrap_or_default();
556 *res.last().unwrap_or(&f64::NAN)
557 }
558
559 fn next_batch(&mut self, inputs: &[(f64, f64, f64)]) -> Vec<Self::Output>
560 where
561 (f64, f64, f64): Copy,
562 {
563 self.history_high.clear();
564 self.history_low.clear();
565 self.history_close.clear();
566 for &(h, l, c) in inputs {
567 self.history_high.push(h);
568 self.history_low.push(l);
569 self.history_close.push(c);
570 }
571 $talib_func(
572 &self.history_high,
573 &self.history_low,
574 &self.history_close,
575 $( self.$param.clone() ),*
576 )
577 .unwrap_or_default()
578 }
579 }
580 };
581}
582
583#[macro_export]
584macro_rules! talib_3_in_2_out {
585 ($name:ident, $talib_func:path $(, $param:ident: $ptype:ty)*) => {
586 #[derive(Debug, Clone)]
587 #[allow(non_camel_case_types)]
588 pub struct $name {
589 $( pub $param: $ptype, )*
590 history_high: Vec<f64>,
591 history_low: Vec<f64>,
592 history_close: Vec<f64>,
593 }
594
595 impl $name {
596 pub fn new($( $param: $ptype ),*) -> Self {
597 Self {
598 $( $param, )*
599 history_high: Vec::new(),
600 history_low: Vec::new(),
601 history_close: Vec::new(),
602 }
603 }
604 }
605
606 impl $crate::traits::Next<(f64, f64, f64)> for $name {
607 type Output = (f64, f64);
608
609 fn next(&mut self, (high, low, close): (f64, f64, f64)) -> Self::Output {
610 self.history_high.push(high);
611 self.history_low.push(low);
612 self.history_close.push(close);
613 if let Ok((res1, res2)) = $talib_func(&self.history_high, &self.history_low, &self.history_close, $( self.$param.clone() ),*) {
614 (*res1.last().unwrap_or(&f64::NAN), *res2.last().unwrap_or(&f64::NAN))
615 } else {
616 (f64::NAN, f64::NAN)
617 }
618 }
619
620 fn next_batch(&mut self, inputs: &[(f64, f64, f64)]) -> Vec<Self::Output>
621 where
622 (f64, f64, f64): Copy,
623 {
624 self.history_high.clear();
625 self.history_low.clear();
626 self.history_close.clear();
627 for &(h, l, c) in inputs {
628 self.history_high.push(h);
629 self.history_low.push(l);
630 self.history_close.push(c);
631 }
632 if let Ok((r1, r2)) = $talib_func(
633 &self.history_high,
634 &self.history_low,
635 &self.history_close,
636 $( self.$param.clone() ),*
637 ) {
638 r1.into_iter().zip(r2).map(|(a, b)| (a, b)).collect()
639 } else {
640 vec![(f64::NAN, f64::NAN); inputs.len()]
641 }
642 }
643 }
644 };
645}
646
647#[macro_export]
648macro_rules! talib_4_in_1_out {
649 ($name:ident, $talib_func:path $(, $param:ident: $ptype:ty)*) => {
650 #[derive(Debug, Clone)]
651 #[allow(non_camel_case_types)]
652 pub struct $name {
653 $( pub $param: $ptype, )*
654 history_1: Vec<f64>,
655 history_2: Vec<f64>,
656 history_3: Vec<f64>,
657 history_4: Vec<f64>,
658 }
659
660 impl $name {
661 pub fn new($( $param: $ptype ),*) -> Self {
662 Self {
663 $( $param, )*
664 history_1: Vec::new(),
665 history_2: Vec::new(),
666 history_3: Vec::new(),
667 history_4: Vec::new(),
668 }
669 }
670 }
671
672 impl $crate::traits::Next<(f64, f64, f64, f64)> for $name {
673 type Output = f64;
674
675 fn next(&mut self, (in1, in2, in3, in4): (f64, f64, f64, f64)) -> Self::Output {
676 self.history_1.push(in1);
677 self.history_2.push(in2);
678 self.history_3.push(in3);
679 self.history_4.push(in4);
680 let res = $talib_func(&self.history_1, &self.history_2, &self.history_3, &self.history_4, $( self.$param.clone() ),*).unwrap_or_default();
681 *res.last().unwrap_or(&f64::NAN)
682 }
683
684 fn next_batch(&mut self, inputs: &[(f64, f64, f64, f64)]) -> Vec<Self::Output>
685 where
686 (f64, f64, f64, f64): Copy,
687 {
688 self.history_1.clear();
689 self.history_2.clear();
690 self.history_3.clear();
691 self.history_4.clear();
692 for &(a, b, c, d) in inputs {
693 self.history_1.push(a);
694 self.history_2.push(b);
695 self.history_3.push(c);
696 self.history_4.push(d);
697 }
698 $talib_func(
699 &self.history_1,
700 &self.history_2,
701 &self.history_3,
702 &self.history_4,
703 $( self.$param.clone() ),*
704 )
705 .unwrap_or_default()
706 }
707 }
708 };
709}