1use polars::prelude::*;
2use pyo3_polars::derive::polars_expr;
3use serde::Deserialize;
4
5use quantwave_core::traits::Next;
6
7#[derive(Deserialize)]
8pub struct SinglePeriodKwargs {
9 pub timeperiod: usize,
10}
11
12#[polars_expr(output_type=Float64)]
13fn acos(inputs: &[Series]) -> PolarsResult<Series> {
14 let s = inputs[0].f64()?;
15 let mut indicator = quantwave_core::ACOS::new();
16 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
17 Some(v) if !v.is_nan() => Some(indicator.next(v)),
18 Some(_) => Some(f64::NAN),
19 None => None,
20 }).collect();
21 Ok(out.into_series())
22}
23
24#[polars_expr(output_type=Float64)]
25fn asin(inputs: &[Series]) -> PolarsResult<Series> {
26 let s = inputs[0].f64()?;
27 let mut indicator = quantwave_core::ASIN::new();
28 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
29 Some(v) if !v.is_nan() => Some(indicator.next(v)),
30 Some(_) => Some(f64::NAN),
31 None => None,
32 }).collect();
33 Ok(out.into_series())
34}
35
36#[polars_expr(output_type=Float64)]
37fn atan(inputs: &[Series]) -> PolarsResult<Series> {
38 let s = inputs[0].f64()?;
39 let mut indicator = quantwave_core::ATAN::new();
40 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
41 Some(v) if !v.is_nan() => Some(indicator.next(v)),
42 Some(_) => Some(f64::NAN),
43 None => None,
44 }).collect();
45 Ok(out.into_series())
46}
47
48#[polars_expr(output_type=Float64)]
49fn ceil(inputs: &[Series]) -> PolarsResult<Series> {
50 let s = inputs[0].f64()?;
51 let mut indicator = quantwave_core::CEIL::new();
52 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
53 Some(v) if !v.is_nan() => Some(indicator.next(v)),
54 Some(_) => Some(f64::NAN),
55 None => None,
56 }).collect();
57 Ok(out.into_series())
58}
59
60#[polars_expr(output_type=Float64)]
61fn cos(inputs: &[Series]) -> PolarsResult<Series> {
62 let s = inputs[0].f64()?;
63 let mut indicator = quantwave_core::COS::new();
64 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
65 Some(v) if !v.is_nan() => Some(indicator.next(v)),
66 Some(_) => Some(f64::NAN),
67 None => None,
68 }).collect();
69 Ok(out.into_series())
70}
71
72#[polars_expr(output_type=Float64)]
73fn cosh(inputs: &[Series]) -> PolarsResult<Series> {
74 let s = inputs[0].f64()?;
75 let mut indicator = quantwave_core::COSH::new();
76 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
77 Some(v) if !v.is_nan() => Some(indicator.next(v)),
78 Some(_) => Some(f64::NAN),
79 None => None,
80 }).collect();
81 Ok(out.into_series())
82}
83
84#[polars_expr(output_type=Float64)]
85fn exp(inputs: &[Series]) -> PolarsResult<Series> {
86 let s = inputs[0].f64()?;
87 let mut indicator = quantwave_core::EXP::new();
88 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
89 Some(v) if !v.is_nan() => Some(indicator.next(v)),
90 Some(_) => Some(f64::NAN),
91 None => None,
92 }).collect();
93 Ok(out.into_series())
94}
95
96#[polars_expr(output_type=Float64)]
97fn floor(inputs: &[Series]) -> PolarsResult<Series> {
98 let s = inputs[0].f64()?;
99 let mut indicator = quantwave_core::FLOOR::new();
100 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
101 Some(v) if !v.is_nan() => Some(indicator.next(v)),
102 Some(_) => Some(f64::NAN),
103 None => None,
104 }).collect();
105 Ok(out.into_series())
106}
107
108#[polars_expr(output_type=Float64)]
109fn ln(inputs: &[Series]) -> PolarsResult<Series> {
110 let s = inputs[0].f64()?;
111 let mut indicator = quantwave_core::LN::new();
112 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
113 Some(v) if !v.is_nan() => Some(indicator.next(v)),
114 Some(_) => Some(f64::NAN),
115 None => None,
116 }).collect();
117 Ok(out.into_series())
118}
119
120#[polars_expr(output_type=Float64)]
121fn log10(inputs: &[Series]) -> PolarsResult<Series> {
122 let s = inputs[0].f64()?;
123 let mut indicator = quantwave_core::LOG10::new();
124 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
125 Some(v) if !v.is_nan() => Some(indicator.next(v)),
126 Some(_) => Some(f64::NAN),
127 None => None,
128 }).collect();
129 Ok(out.into_series())
130}
131
132#[polars_expr(output_type=Float64)]
133fn sin(inputs: &[Series]) -> PolarsResult<Series> {
134 let s = inputs[0].f64()?;
135 let mut indicator = quantwave_core::SIN::new();
136 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
137 Some(v) if !v.is_nan() => Some(indicator.next(v)),
138 Some(_) => Some(f64::NAN),
139 None => None,
140 }).collect();
141 Ok(out.into_series())
142}
143
144#[polars_expr(output_type=Float64)]
145fn sinh(inputs: &[Series]) -> PolarsResult<Series> {
146 let s = inputs[0].f64()?;
147 let mut indicator = quantwave_core::SINH::new();
148 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
149 Some(v) if !v.is_nan() => Some(indicator.next(v)),
150 Some(_) => Some(f64::NAN),
151 None => None,
152 }).collect();
153 Ok(out.into_series())
154}
155
156#[polars_expr(output_type=Float64)]
157fn sqrt(inputs: &[Series]) -> PolarsResult<Series> {
158 let s = inputs[0].f64()?;
159 let mut indicator = quantwave_core::SQRT::new();
160 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
161 Some(v) if !v.is_nan() => Some(indicator.next(v)),
162 Some(_) => Some(f64::NAN),
163 None => None,
164 }).collect();
165 Ok(out.into_series())
166}
167
168#[polars_expr(output_type=Float64)]
169fn tan(inputs: &[Series]) -> PolarsResult<Series> {
170 let s = inputs[0].f64()?;
171 let mut indicator = quantwave_core::TAN::new();
172 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
173 Some(v) if !v.is_nan() => Some(indicator.next(v)),
174 Some(_) => Some(f64::NAN),
175 None => None,
176 }).collect();
177 Ok(out.into_series())
178}
179
180#[polars_expr(output_type=Float64)]
181fn tanh(inputs: &[Series]) -> PolarsResult<Series> {
182 let s = inputs[0].f64()?;
183 let mut indicator = quantwave_core::TANH::new();
184 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
185 Some(v) if !v.is_nan() => Some(indicator.next(v)),
186 Some(_) => Some(f64::NAN),
187 None => None,
188 }).collect();
189 Ok(out.into_series())
190}
191
192#[polars_expr(output_type=Float64)]
193fn max(inputs: &[Series], kwargs: SinglePeriodKwargs) -> PolarsResult<Series> {
194 let s = inputs[0].f64()?;
195 let mut indicator = quantwave_core::MAX::new(kwargs.timeperiod);
196 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
197 Some(v) if !v.is_nan() => Some(indicator.next(v)),
198 Some(_) => Some(f64::NAN),
199 None => None,
200 }).collect();
201 Ok(out.into_series())
202}
203
204#[polars_expr(output_type=Float64)]
205fn maxindex(inputs: &[Series], kwargs: SinglePeriodKwargs) -> PolarsResult<Series> {
206 let s = inputs[0].f64()?;
207 let mut indicator = quantwave_core::MAXINDEX::new(kwargs.timeperiod);
208 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
209 Some(v) if !v.is_nan() => Some(indicator.next(v)),
210 Some(_) => Some(f64::NAN),
211 None => None,
212 }).collect();
213 Ok(out.into_series())
214}
215
216#[polars_expr(output_type=Float64)]
217fn min(inputs: &[Series], kwargs: SinglePeriodKwargs) -> PolarsResult<Series> {
218 let s = inputs[0].f64()?;
219 let mut indicator = quantwave_core::MIN::new(kwargs.timeperiod);
220 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
221 Some(v) if !v.is_nan() => Some(indicator.next(v)),
222 Some(_) => Some(f64::NAN),
223 None => None,
224 }).collect();
225 Ok(out.into_series())
226}
227
228#[polars_expr(output_type=Float64)]
229fn minindex(inputs: &[Series], kwargs: SinglePeriodKwargs) -> PolarsResult<Series> {
230 let s = inputs[0].f64()?;
231 let mut indicator = quantwave_core::MININDEX::new(kwargs.timeperiod);
232 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
233 Some(v) if !v.is_nan() => Some(indicator.next(v)),
234 Some(_) => Some(f64::NAN),
235 None => None,
236 }).collect();
237 Ok(out.into_series())
238}
239
240#[polars_expr(output_type=Float64)]
241fn sum(inputs: &[Series], kwargs: SinglePeriodKwargs) -> PolarsResult<Series> {
242 let s = inputs[0].f64()?;
243 let mut indicator = quantwave_core::SUM::new(kwargs.timeperiod);
244 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
245 Some(v) if !v.is_nan() => Some(indicator.next(v)),
246 Some(_) => Some(f64::NAN),
247 None => None,
248 }).collect();
249 Ok(out.into_series())
250}
251
252#[polars_expr(output_type=Float64)]
253fn ta_linearreg(inputs: &[Series], kwargs: SinglePeriodKwargs) -> PolarsResult<Series> {
254 let s = inputs[0].f64()?;
255 let mut indicator = quantwave_core::TaLINEARREG::new(kwargs.timeperiod);
256 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
257 Some(v) if !v.is_nan() => Some(indicator.next(v)),
258 Some(_) => Some(f64::NAN),
259 None => None,
260 }).collect();
261 Ok(out.into_series())
262}
263
264#[polars_expr(output_type=Float64)]
265fn ta_linearreg_angle(inputs: &[Series], kwargs: SinglePeriodKwargs) -> PolarsResult<Series> {
266 let s = inputs[0].f64()?;
267 let mut indicator = quantwave_core::TaLINEARREG_ANGLE::new(kwargs.timeperiod);
268 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
269 Some(v) if !v.is_nan() => Some(indicator.next(v)),
270 Some(_) => Some(f64::NAN),
271 None => None,
272 }).collect();
273 Ok(out.into_series())
274}
275
276#[polars_expr(output_type=Float64)]
277fn ta_linearreg_intercept(inputs: &[Series], kwargs: SinglePeriodKwargs) -> PolarsResult<Series> {
278 let s = inputs[0].f64()?;
279 let mut indicator = quantwave_core::TaLINEARREG_INTERCEPT::new(kwargs.timeperiod);
280 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
281 Some(v) if !v.is_nan() => Some(indicator.next(v)),
282 Some(_) => Some(f64::NAN),
283 None => None,
284 }).collect();
285 Ok(out.into_series())
286}
287
288#[polars_expr(output_type=Float64)]
289fn ta_linearreg_slope(inputs: &[Series], kwargs: SinglePeriodKwargs) -> PolarsResult<Series> {
290 let s = inputs[0].f64()?;
291 let mut indicator = quantwave_core::TaLINEARREG_SLOPE::new(kwargs.timeperiod);
292 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
293 Some(v) if !v.is_nan() => Some(indicator.next(v)),
294 Some(_) => Some(f64::NAN),
295 None => None,
296 }).collect();
297 Ok(out.into_series())
298}
299
300#[polars_expr(output_type=Float64)]
301fn ta_tsf(inputs: &[Series], kwargs: SinglePeriodKwargs) -> PolarsResult<Series> {
302 let s = inputs[0].f64()?;
303 let mut indicator = quantwave_core::TaTSF::new(kwargs.timeperiod);
304 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
305 Some(v) if !v.is_nan() => Some(indicator.next(v)),
306 Some(_) => Some(f64::NAN),
307 None => None,
308 }).collect();
309 Ok(out.into_series())
310}
311
312#[polars_expr(output_type=Float64)]
313fn wma(inputs: &[Series], kwargs: SinglePeriodKwargs) -> PolarsResult<Series> {
314 let s = inputs[0].f64()?;
315 let mut indicator = quantwave_core::WMA::new(kwargs.timeperiod);
316 let out: Float64Chunked = s.into_iter().map(|opt_v| match opt_v {
317 Some(v) if !v.is_nan() => Some(indicator.next(v)),
318 Some(_) => Some(f64::NAN),
319 None => None,
320 }).collect();
321 Ok(out.into_series())
322}
323
324#[polars_expr(output_type=Float64)]
325fn add(inputs: &[Series]) -> PolarsResult<Series> {
326 let in1 = inputs[0].f64()?;
327 let in2 = inputs[1].f64()?;
328 let mut indicator = quantwave_core::ADD::new();
329 let out: Float64Chunked = in1.into_iter().zip(in2.into_iter()).map(|(v1, v2)| match (v1, v2) {
330 (Some(a), Some(b)) if !a.is_nan() && !b.is_nan() => Some(indicator.next((a, b))),
331 (Some(_), Some(_)) => Some(f64::NAN),
332 _ => None,
333 }).collect();
334 Ok(out.into_series())
335}
336
337#[polars_expr(output_type=Float64)]
338fn div(inputs: &[Series]) -> PolarsResult<Series> {
339 let in1 = inputs[0].f64()?;
340 let in2 = inputs[1].f64()?;
341 let mut indicator = quantwave_core::DIV::new();
342 let out: Float64Chunked = in1.into_iter().zip(in2.into_iter()).map(|(v1, v2)| match (v1, v2) {
343 (Some(a), Some(b)) if !a.is_nan() && !b.is_nan() => Some(indicator.next((a, b))),
344 (Some(_), Some(_)) => Some(f64::NAN),
345 _ => None,
346 }).collect();
347 Ok(out.into_series())
348}
349
350#[polars_expr(output_type=Float64)]
351fn mult(inputs: &[Series]) -> PolarsResult<Series> {
352 let in1 = inputs[0].f64()?;
353 let in2 = inputs[1].f64()?;
354 let mut indicator = quantwave_core::MULT::new();
355 let out: Float64Chunked = in1.into_iter().zip(in2.into_iter()).map(|(v1, v2)| match (v1, v2) {
356 (Some(a), Some(b)) if !a.is_nan() && !b.is_nan() => Some(indicator.next((a, b))),
357 (Some(_), Some(_)) => Some(f64::NAN),
358 _ => None,
359 }).collect();
360 Ok(out.into_series())
361}
362
363#[polars_expr(output_type=Float64)]
364fn obv(inputs: &[Series]) -> PolarsResult<Series> {
365 let in1 = inputs[0].f64()?;
366 let in2 = inputs[1].f64()?;
367 let mut indicator = quantwave_core::OBV::new();
368 let out: Float64Chunked = in1.into_iter().zip(in2.into_iter()).map(|(v1, v2)| match (v1, v2) {
369 (Some(a), Some(b)) if !a.is_nan() && !b.is_nan() => Some(indicator.next((a, b))),
370 (Some(_), Some(_)) => Some(f64::NAN),
371 _ => None,
372 }).collect();
373 Ok(out.into_series())
374}
375
376#[polars_expr(output_type=Float64)]
377fn sub(inputs: &[Series]) -> PolarsResult<Series> {
378 let in1 = inputs[0].f64()?;
379 let in2 = inputs[1].f64()?;
380 let mut indicator = quantwave_core::SUB::new();
381 let out: Float64Chunked = in1.into_iter().zip(in2.into_iter()).map(|(v1, v2)| match (v1, v2) {
382 (Some(a), Some(b)) if !a.is_nan() && !b.is_nan() => Some(indicator.next((a, b))),
383 (Some(_), Some(_)) => Some(f64::NAN),
384 _ => None,
385 }).collect();
386 Ok(out.into_series())
387}
388
389#[polars_expr(output_type=Float64)]
390fn ta_beta(inputs: &[Series], kwargs: SinglePeriodKwargs) -> PolarsResult<Series> {
391 let in1 = inputs[0].f64()?;
392 let in2 = inputs[1].f64()?;
393 let mut indicator = quantwave_core::TaBETA::new(kwargs.timeperiod);
394 let out: Float64Chunked = in1.into_iter().zip(in2.into_iter()).map(|(v1, v2)| match (v1, v2) {
395 (Some(a), Some(b)) if !a.is_nan() && !b.is_nan() => Some(indicator.next((a, b))),
396 (Some(_), Some(_)) => Some(f64::NAN),
397 _ => None,
398 }).collect();
399 Ok(out.into_series())
400}
401
402#[polars_expr(output_type=Float64)]
403fn ta_correl(inputs: &[Series], kwargs: SinglePeriodKwargs) -> PolarsResult<Series> {
404 let in1 = inputs[0].f64()?;
405 let in2 = inputs[1].f64()?;
406 let mut indicator = quantwave_core::TaCORREL::new(kwargs.timeperiod);
407 let out: Float64Chunked = in1.into_iter().zip(in2.into_iter()).map(|(v1, v2)| match (v1, v2) {
408 (Some(a), Some(b)) if !a.is_nan() && !b.is_nan() => Some(indicator.next((a, b))),
409 (Some(_), Some(_)) => Some(f64::NAN),
410 _ => None,
411 }).collect();
412 Ok(out.into_series())
413}
414
415#[polars_expr(output_type=Float64)]
416fn ta_trange(inputs: &[Series]) -> PolarsResult<Series> {
417 let in1 = inputs[0].f64()?;
418 let in2 = inputs[1].f64()?;
419 let in3 = inputs[2].f64()?;
420 let mut indicator = quantwave_core::TaTRANGE::new();
421 let out: Float64Chunked = in1.into_iter().zip(in2.into_iter()).zip(in3.into_iter()).map(|((v1, v2), v3)| match (v1, v2, v3) {
422 (Some(a), Some(b), Some(c)) if !a.is_nan() && !b.is_nan() && !c.is_nan() => Some(indicator.next((a, b, c))),
423 (Some(_), Some(_), Some(_)) => Some(f64::NAN),
424 _ => None,
425 }).collect();
426 Ok(out.into_series())
427}
428
429#[polars_expr(output_type=Float64)]
430fn ta_atr(inputs: &[Series], kwargs: SinglePeriodKwargs) -> PolarsResult<Series> {
431 let in1 = inputs[0].f64()?;
432 let in2 = inputs[1].f64()?;
433 let in3 = inputs[2].f64()?;
434 let mut indicator = quantwave_core::TaATR::new(kwargs.timeperiod);
435 let out: Float64Chunked = in1.into_iter().zip(in2.into_iter()).zip(in3.into_iter()).map(|((v1, v2), v3)| match (v1, v2, v3) {
436 (Some(a), Some(b), Some(c)) if !a.is_nan() && !b.is_nan() && !c.is_nan() => Some(indicator.next((a, b, c))),
437 (Some(_), Some(_), Some(_)) => Some(f64::NAN),
438 _ => None,
439 }).collect();
440 Ok(out.into_series())
441}
442
443#[polars_expr(output_type=Float64)]
444fn ta_natr(inputs: &[Series], kwargs: SinglePeriodKwargs) -> PolarsResult<Series> {
445 let in1 = inputs[0].f64()?;
446 let in2 = inputs[1].f64()?;
447 let in3 = inputs[2].f64()?;
448 let mut indicator = quantwave_core::TaNATR::new(kwargs.timeperiod);
449 let out: Float64Chunked = in1.into_iter().zip(in2.into_iter()).zip(in3.into_iter()).map(|((v1, v2), v3)| match (v1, v2, v3) {
450 (Some(a), Some(b), Some(c)) if !a.is_nan() && !b.is_nan() && !c.is_nan() => Some(indicator.next((a, b, c))),
451 (Some(_), Some(_), Some(_)) => Some(f64::NAN),
452 _ => None,
453 }).collect();
454 Ok(out.into_series())
455}
456
457#[polars_expr(output_type=Float64)]
458fn bop(inputs: &[Series]) -> PolarsResult<Series> {
459 let open = inputs[0].f64()?;
460 let high = inputs[1].f64()?;
461 let low = inputs[2].f64()?;
462 let close = inputs[3].f64()?;
463 let mut indicator = quantwave_core::BOP::new();
464 let out: Float64Chunked = open.into_iter()
465 .zip(high.into_iter())
466 .zip(low.into_iter())
467 .zip(close.into_iter())
468 .map(|(((o, h), l), c)| match (o, h, l, c) {
469 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
470 Some(indicator.next((o_, h_, l_, c_)) as f64),
471 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
472 _ => None,
473 }).collect();
474 Ok(out.into_series())
475}
476
477#[polars_expr(output_type=Float64)]
478fn cdl_2crows(inputs: &[Series]) -> PolarsResult<Series> {
479 let open = inputs[0].f64()?;
480 let high = inputs[1].f64()?;
481 let low = inputs[2].f64()?;
482 let close = inputs[3].f64()?;
483 let mut indicator = quantwave_core::CDL2CROWS::new();
484 let out: Float64Chunked = open.into_iter()
485 .zip(high.into_iter())
486 .zip(low.into_iter())
487 .zip(close.into_iter())
488 .map(|(((o, h), l), c)| match (o, h, l, c) {
489 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
490 Some(indicator.next((o_, h_, l_, c_)) as f64),
491 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
492 _ => None,
493 }).collect();
494 Ok(out.into_series())
495}
496
497#[polars_expr(output_type=Float64)]
498fn cdl_3blackcrows(inputs: &[Series]) -> PolarsResult<Series> {
499 let open = inputs[0].f64()?;
500 let high = inputs[1].f64()?;
501 let low = inputs[2].f64()?;
502 let close = inputs[3].f64()?;
503 let mut indicator = quantwave_core::CDL3BLACKCROWS::new();
504 let out: Float64Chunked = open.into_iter()
505 .zip(high.into_iter())
506 .zip(low.into_iter())
507 .zip(close.into_iter())
508 .map(|(((o, h), l), c)| match (o, h, l, c) {
509 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
510 Some(indicator.next((o_, h_, l_, c_)) as f64),
511 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
512 _ => None,
513 }).collect();
514 Ok(out.into_series())
515}
516
517#[polars_expr(output_type=Float64)]
518fn cdl_3inside(inputs: &[Series]) -> PolarsResult<Series> {
519 let open = inputs[0].f64()?;
520 let high = inputs[1].f64()?;
521 let low = inputs[2].f64()?;
522 let close = inputs[3].f64()?;
523 let mut indicator = quantwave_core::CDL3INSIDE::new();
524 let out: Float64Chunked = open.into_iter()
525 .zip(high.into_iter())
526 .zip(low.into_iter())
527 .zip(close.into_iter())
528 .map(|(((o, h), l), c)| match (o, h, l, c) {
529 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
530 Some(indicator.next((o_, h_, l_, c_)) as f64),
531 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
532 _ => None,
533 }).collect();
534 Ok(out.into_series())
535}
536
537#[polars_expr(output_type=Float64)]
538fn cdl_3linestrike(inputs: &[Series]) -> PolarsResult<Series> {
539 let open = inputs[0].f64()?;
540 let high = inputs[1].f64()?;
541 let low = inputs[2].f64()?;
542 let close = inputs[3].f64()?;
543 let mut indicator = quantwave_core::CDL3LINESTRIKE::new();
544 let out: Float64Chunked = open.into_iter()
545 .zip(high.into_iter())
546 .zip(low.into_iter())
547 .zip(close.into_iter())
548 .map(|(((o, h), l), c)| match (o, h, l, c) {
549 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
550 Some(indicator.next((o_, h_, l_, c_)) as f64),
551 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
552 _ => None,
553 }).collect();
554 Ok(out.into_series())
555}
556
557#[polars_expr(output_type=Float64)]
558fn cdl_3outside(inputs: &[Series]) -> PolarsResult<Series> {
559 let open = inputs[0].f64()?;
560 let high = inputs[1].f64()?;
561 let low = inputs[2].f64()?;
562 let close = inputs[3].f64()?;
563 let mut indicator = quantwave_core::CDL3OUTSIDE::new();
564 let out: Float64Chunked = open.into_iter()
565 .zip(high.into_iter())
566 .zip(low.into_iter())
567 .zip(close.into_iter())
568 .map(|(((o, h), l), c)| match (o, h, l, c) {
569 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
570 Some(indicator.next((o_, h_, l_, c_)) as f64),
571 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
572 _ => None,
573 }).collect();
574 Ok(out.into_series())
575}
576
577#[polars_expr(output_type=Float64)]
578fn cdl_3starsinsouth(inputs: &[Series]) -> PolarsResult<Series> {
579 let open = inputs[0].f64()?;
580 let high = inputs[1].f64()?;
581 let low = inputs[2].f64()?;
582 let close = inputs[3].f64()?;
583 let mut indicator = quantwave_core::CDL3STARSINSOUTH::new();
584 let out: Float64Chunked = open.into_iter()
585 .zip(high.into_iter())
586 .zip(low.into_iter())
587 .zip(close.into_iter())
588 .map(|(((o, h), l), c)| match (o, h, l, c) {
589 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
590 Some(indicator.next((o_, h_, l_, c_)) as f64),
591 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
592 _ => None,
593 }).collect();
594 Ok(out.into_series())
595}
596
597#[polars_expr(output_type=Float64)]
598fn cdl_3whitesoldiers(inputs: &[Series]) -> PolarsResult<Series> {
599 let open = inputs[0].f64()?;
600 let high = inputs[1].f64()?;
601 let low = inputs[2].f64()?;
602 let close = inputs[3].f64()?;
603 let mut indicator = quantwave_core::CDL3WHITESOLDIERS::new();
604 let out: Float64Chunked = open.into_iter()
605 .zip(high.into_iter())
606 .zip(low.into_iter())
607 .zip(close.into_iter())
608 .map(|(((o, h), l), c)| match (o, h, l, c) {
609 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
610 Some(indicator.next((o_, h_, l_, c_)) as f64),
611 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
612 _ => None,
613 }).collect();
614 Ok(out.into_series())
615}
616
617#[polars_expr(output_type=Float64)]
618fn cdl_abandonedbaby(inputs: &[Series]) -> PolarsResult<Series> {
619 let open = inputs[0].f64()?;
620 let high = inputs[1].f64()?;
621 let low = inputs[2].f64()?;
622 let close = inputs[3].f64()?;
623 let mut indicator = quantwave_core::CDLABANDONEDBABY::new();
624 let out: Float64Chunked = open.into_iter()
625 .zip(high.into_iter())
626 .zip(low.into_iter())
627 .zip(close.into_iter())
628 .map(|(((o, h), l), c)| match (o, h, l, c) {
629 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
630 Some(indicator.next((o_, h_, l_, c_)) as f64),
631 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
632 _ => None,
633 }).collect();
634 Ok(out.into_series())
635}
636
637#[polars_expr(output_type=Float64)]
638fn cdl_advanceblock(inputs: &[Series]) -> PolarsResult<Series> {
639 let open = inputs[0].f64()?;
640 let high = inputs[1].f64()?;
641 let low = inputs[2].f64()?;
642 let close = inputs[3].f64()?;
643 let mut indicator = quantwave_core::CDLADVANCEBLOCK::new();
644 let out: Float64Chunked = open.into_iter()
645 .zip(high.into_iter())
646 .zip(low.into_iter())
647 .zip(close.into_iter())
648 .map(|(((o, h), l), c)| match (o, h, l, c) {
649 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
650 Some(indicator.next((o_, h_, l_, c_)) as f64),
651 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
652 _ => None,
653 }).collect();
654 Ok(out.into_series())
655}
656
657#[polars_expr(output_type=Float64)]
658fn cdl_belthold(inputs: &[Series]) -> PolarsResult<Series> {
659 let open = inputs[0].f64()?;
660 let high = inputs[1].f64()?;
661 let low = inputs[2].f64()?;
662 let close = inputs[3].f64()?;
663 let mut indicator = quantwave_core::CDLBELTHOLD::new();
664 let out: Float64Chunked = open.into_iter()
665 .zip(high.into_iter())
666 .zip(low.into_iter())
667 .zip(close.into_iter())
668 .map(|(((o, h), l), c)| match (o, h, l, c) {
669 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
670 Some(indicator.next((o_, h_, l_, c_)) as f64),
671 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
672 _ => None,
673 }).collect();
674 Ok(out.into_series())
675}
676
677#[polars_expr(output_type=Float64)]
678fn cdl_breakaway(inputs: &[Series]) -> PolarsResult<Series> {
679 let open = inputs[0].f64()?;
680 let high = inputs[1].f64()?;
681 let low = inputs[2].f64()?;
682 let close = inputs[3].f64()?;
683 let mut indicator = quantwave_core::CDLBREAKAWAY::new();
684 let out: Float64Chunked = open.into_iter()
685 .zip(high.into_iter())
686 .zip(low.into_iter())
687 .zip(close.into_iter())
688 .map(|(((o, h), l), c)| match (o, h, l, c) {
689 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
690 Some(indicator.next((o_, h_, l_, c_)) as f64),
691 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
692 _ => None,
693 }).collect();
694 Ok(out.into_series())
695}
696
697#[polars_expr(output_type=Float64)]
698fn cdl_closingmarubozu(inputs: &[Series]) -> PolarsResult<Series> {
699 let open = inputs[0].f64()?;
700 let high = inputs[1].f64()?;
701 let low = inputs[2].f64()?;
702 let close = inputs[3].f64()?;
703 let mut indicator = quantwave_core::CDLCLOSINGMARUBOZU::new();
704 let out: Float64Chunked = open.into_iter()
705 .zip(high.into_iter())
706 .zip(low.into_iter())
707 .zip(close.into_iter())
708 .map(|(((o, h), l), c)| match (o, h, l, c) {
709 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
710 Some(indicator.next((o_, h_, l_, c_)) as f64),
711 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
712 _ => None,
713 }).collect();
714 Ok(out.into_series())
715}
716
717#[polars_expr(output_type=Float64)]
718fn cdl_concealbabyswall(inputs: &[Series]) -> PolarsResult<Series> {
719 let open = inputs[0].f64()?;
720 let high = inputs[1].f64()?;
721 let low = inputs[2].f64()?;
722 let close = inputs[3].f64()?;
723 let mut indicator = quantwave_core::CDLCONCEALBABYSWALL::new();
724 let out: Float64Chunked = open.into_iter()
725 .zip(high.into_iter())
726 .zip(low.into_iter())
727 .zip(close.into_iter())
728 .map(|(((o, h), l), c)| match (o, h, l, c) {
729 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
730 Some(indicator.next((o_, h_, l_, c_)) as f64),
731 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
732 _ => None,
733 }).collect();
734 Ok(out.into_series())
735}
736
737#[polars_expr(output_type=Float64)]
738fn cdl_counterattack(inputs: &[Series]) -> PolarsResult<Series> {
739 let open = inputs[0].f64()?;
740 let high = inputs[1].f64()?;
741 let low = inputs[2].f64()?;
742 let close = inputs[3].f64()?;
743 let mut indicator = quantwave_core::CDLCOUNTERATTACK::new();
744 let out: Float64Chunked = open.into_iter()
745 .zip(high.into_iter())
746 .zip(low.into_iter())
747 .zip(close.into_iter())
748 .map(|(((o, h), l), c)| match (o, h, l, c) {
749 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
750 Some(indicator.next((o_, h_, l_, c_)) as f64),
751 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
752 _ => None,
753 }).collect();
754 Ok(out.into_series())
755}
756
757#[polars_expr(output_type=Float64)]
758fn cdl_darkcloudcover(inputs: &[Series]) -> PolarsResult<Series> {
759 let open = inputs[0].f64()?;
760 let high = inputs[1].f64()?;
761 let low = inputs[2].f64()?;
762 let close = inputs[3].f64()?;
763 let mut indicator = quantwave_core::CDLDARKCLOUDCOVER::new();
764 let out: Float64Chunked = open.into_iter()
765 .zip(high.into_iter())
766 .zip(low.into_iter())
767 .zip(close.into_iter())
768 .map(|(((o, h), l), c)| match (o, h, l, c) {
769 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
770 Some(indicator.next((o_, h_, l_, c_)) as f64),
771 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
772 _ => None,
773 }).collect();
774 Ok(out.into_series())
775}
776
777#[polars_expr(output_type=Float64)]
778fn cdl_doji(inputs: &[Series]) -> PolarsResult<Series> {
779 let open = inputs[0].f64()?;
780 let high = inputs[1].f64()?;
781 let low = inputs[2].f64()?;
782 let close = inputs[3].f64()?;
783 let mut indicator = quantwave_core::CDLDOJI::new();
784 let out: Float64Chunked = open.into_iter()
785 .zip(high.into_iter())
786 .zip(low.into_iter())
787 .zip(close.into_iter())
788 .map(|(((o, h), l), c)| match (o, h, l, c) {
789 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
790 Some(indicator.next((o_, h_, l_, c_)) as f64),
791 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
792 _ => None,
793 }).collect();
794 Ok(out.into_series())
795}
796
797#[polars_expr(output_type=Float64)]
798fn cdl_dojistar(inputs: &[Series]) -> PolarsResult<Series> {
799 let open = inputs[0].f64()?;
800 let high = inputs[1].f64()?;
801 let low = inputs[2].f64()?;
802 let close = inputs[3].f64()?;
803 let mut indicator = quantwave_core::CDLDOJISTAR::new();
804 let out: Float64Chunked = open.into_iter()
805 .zip(high.into_iter())
806 .zip(low.into_iter())
807 .zip(close.into_iter())
808 .map(|(((o, h), l), c)| match (o, h, l, c) {
809 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
810 Some(indicator.next((o_, h_, l_, c_)) as f64),
811 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
812 _ => None,
813 }).collect();
814 Ok(out.into_series())
815}
816
817#[polars_expr(output_type=Float64)]
818fn cdl_dragonflydoji(inputs: &[Series]) -> PolarsResult<Series> {
819 let open = inputs[0].f64()?;
820 let high = inputs[1].f64()?;
821 let low = inputs[2].f64()?;
822 let close = inputs[3].f64()?;
823 let mut indicator = quantwave_core::CDLDRAGONFLYDOJI::new();
824 let out: Float64Chunked = open.into_iter()
825 .zip(high.into_iter())
826 .zip(low.into_iter())
827 .zip(close.into_iter())
828 .map(|(((o, h), l), c)| match (o, h, l, c) {
829 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
830 Some(indicator.next((o_, h_, l_, c_)) as f64),
831 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
832 _ => None,
833 }).collect();
834 Ok(out.into_series())
835}
836
837#[polars_expr(output_type=Float64)]
838fn cdl_engulfing(inputs: &[Series]) -> PolarsResult<Series> {
839 let open = inputs[0].f64()?;
840 let high = inputs[1].f64()?;
841 let low = inputs[2].f64()?;
842 let close = inputs[3].f64()?;
843 let mut indicator = quantwave_core::CDLENGULFING::new();
844 let out: Float64Chunked = open.into_iter()
845 .zip(high.into_iter())
846 .zip(low.into_iter())
847 .zip(close.into_iter())
848 .map(|(((o, h), l), c)| match (o, h, l, c) {
849 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
850 Some(indicator.next((o_, h_, l_, c_)) as f64),
851 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
852 _ => None,
853 }).collect();
854 Ok(out.into_series())
855}
856
857#[polars_expr(output_type=Float64)]
858fn cdl_eveningdojistar(inputs: &[Series]) -> PolarsResult<Series> {
859 let open = inputs[0].f64()?;
860 let high = inputs[1].f64()?;
861 let low = inputs[2].f64()?;
862 let close = inputs[3].f64()?;
863 let mut indicator = quantwave_core::CDLEVENINGDOJISTAR::new();
864 let out: Float64Chunked = open.into_iter()
865 .zip(high.into_iter())
866 .zip(low.into_iter())
867 .zip(close.into_iter())
868 .map(|(((o, h), l), c)| match (o, h, l, c) {
869 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
870 Some(indicator.next((o_, h_, l_, c_)) as f64),
871 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
872 _ => None,
873 }).collect();
874 Ok(out.into_series())
875}
876
877#[polars_expr(output_type=Float64)]
878fn cdl_eveningstar(inputs: &[Series]) -> PolarsResult<Series> {
879 let open = inputs[0].f64()?;
880 let high = inputs[1].f64()?;
881 let low = inputs[2].f64()?;
882 let close = inputs[3].f64()?;
883 let mut indicator = quantwave_core::CDLEVENINGSTAR::new();
884 let out: Float64Chunked = open.into_iter()
885 .zip(high.into_iter())
886 .zip(low.into_iter())
887 .zip(close.into_iter())
888 .map(|(((o, h), l), c)| match (o, h, l, c) {
889 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
890 Some(indicator.next((o_, h_, l_, c_)) as f64),
891 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
892 _ => None,
893 }).collect();
894 Ok(out.into_series())
895}
896
897#[polars_expr(output_type=Float64)]
898fn cdl_gapsidesidewhite(inputs: &[Series]) -> PolarsResult<Series> {
899 let open = inputs[0].f64()?;
900 let high = inputs[1].f64()?;
901 let low = inputs[2].f64()?;
902 let close = inputs[3].f64()?;
903 let mut indicator = quantwave_core::CDLGAPSIDESIDEWHITE::new();
904 let out: Float64Chunked = open.into_iter()
905 .zip(high.into_iter())
906 .zip(low.into_iter())
907 .zip(close.into_iter())
908 .map(|(((o, h), l), c)| match (o, h, l, c) {
909 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
910 Some(indicator.next((o_, h_, l_, c_)) as f64),
911 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
912 _ => None,
913 }).collect();
914 Ok(out.into_series())
915}
916
917#[polars_expr(output_type=Float64)]
918fn cdl_gravestonedoji(inputs: &[Series]) -> PolarsResult<Series> {
919 let open = inputs[0].f64()?;
920 let high = inputs[1].f64()?;
921 let low = inputs[2].f64()?;
922 let close = inputs[3].f64()?;
923 let mut indicator = quantwave_core::CDLGRAVESTONEDOJI::new();
924 let out: Float64Chunked = open.into_iter()
925 .zip(high.into_iter())
926 .zip(low.into_iter())
927 .zip(close.into_iter())
928 .map(|(((o, h), l), c)| match (o, h, l, c) {
929 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
930 Some(indicator.next((o_, h_, l_, c_)) as f64),
931 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
932 _ => None,
933 }).collect();
934 Ok(out.into_series())
935}
936
937#[polars_expr(output_type=Float64)]
938fn cdl_hammer(inputs: &[Series]) -> PolarsResult<Series> {
939 let open = inputs[0].f64()?;
940 let high = inputs[1].f64()?;
941 let low = inputs[2].f64()?;
942 let close = inputs[3].f64()?;
943 let mut indicator = quantwave_core::CDLHAMMER::new();
944 let out: Float64Chunked = open.into_iter()
945 .zip(high.into_iter())
946 .zip(low.into_iter())
947 .zip(close.into_iter())
948 .map(|(((o, h), l), c)| match (o, h, l, c) {
949 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
950 Some(indicator.next((o_, h_, l_, c_)) as f64),
951 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
952 _ => None,
953 }).collect();
954 Ok(out.into_series())
955}
956
957#[polars_expr(output_type=Float64)]
958fn cdl_hangingman(inputs: &[Series]) -> PolarsResult<Series> {
959 let open = inputs[0].f64()?;
960 let high = inputs[1].f64()?;
961 let low = inputs[2].f64()?;
962 let close = inputs[3].f64()?;
963 let mut indicator = quantwave_core::CDLHANGINGMAN::new();
964 let out: Float64Chunked = open.into_iter()
965 .zip(high.into_iter())
966 .zip(low.into_iter())
967 .zip(close.into_iter())
968 .map(|(((o, h), l), c)| match (o, h, l, c) {
969 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
970 Some(indicator.next((o_, h_, l_, c_)) as f64),
971 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
972 _ => None,
973 }).collect();
974 Ok(out.into_series())
975}
976
977#[polars_expr(output_type=Float64)]
978fn cdl_harami(inputs: &[Series]) -> PolarsResult<Series> {
979 let open = inputs[0].f64()?;
980 let high = inputs[1].f64()?;
981 let low = inputs[2].f64()?;
982 let close = inputs[3].f64()?;
983 let mut indicator = quantwave_core::CDLHARAMI::new();
984 let out: Float64Chunked = open.into_iter()
985 .zip(high.into_iter())
986 .zip(low.into_iter())
987 .zip(close.into_iter())
988 .map(|(((o, h), l), c)| match (o, h, l, c) {
989 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
990 Some(indicator.next((o_, h_, l_, c_)) as f64),
991 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
992 _ => None,
993 }).collect();
994 Ok(out.into_series())
995}
996
997#[polars_expr(output_type=Float64)]
998fn cdl_haramicross(inputs: &[Series]) -> PolarsResult<Series> {
999 let open = inputs[0].f64()?;
1000 let high = inputs[1].f64()?;
1001 let low = inputs[2].f64()?;
1002 let close = inputs[3].f64()?;
1003 let mut indicator = quantwave_core::CDLHARAMICROSS::new();
1004 let out: Float64Chunked = open.into_iter()
1005 .zip(high.into_iter())
1006 .zip(low.into_iter())
1007 .zip(close.into_iter())
1008 .map(|(((o, h), l), c)| match (o, h, l, c) {
1009 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1010 Some(indicator.next((o_, h_, l_, c_)) as f64),
1011 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1012 _ => None,
1013 }).collect();
1014 Ok(out.into_series())
1015}
1016
1017#[polars_expr(output_type=Float64)]
1018fn cdl_highwave(inputs: &[Series]) -> PolarsResult<Series> {
1019 let open = inputs[0].f64()?;
1020 let high = inputs[1].f64()?;
1021 let low = inputs[2].f64()?;
1022 let close = inputs[3].f64()?;
1023 let mut indicator = quantwave_core::CDLHIGHWAVE::new();
1024 let out: Float64Chunked = open.into_iter()
1025 .zip(high.into_iter())
1026 .zip(low.into_iter())
1027 .zip(close.into_iter())
1028 .map(|(((o, h), l), c)| match (o, h, l, c) {
1029 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1030 Some(indicator.next((o_, h_, l_, c_)) as f64),
1031 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1032 _ => None,
1033 }).collect();
1034 Ok(out.into_series())
1035}
1036
1037#[polars_expr(output_type=Float64)]
1038fn cdl_hikkake(inputs: &[Series]) -> PolarsResult<Series> {
1039 let open = inputs[0].f64()?;
1040 let high = inputs[1].f64()?;
1041 let low = inputs[2].f64()?;
1042 let close = inputs[3].f64()?;
1043 let mut indicator = quantwave_core::CDLHIKKAKE::new();
1044 let out: Float64Chunked = open.into_iter()
1045 .zip(high.into_iter())
1046 .zip(low.into_iter())
1047 .zip(close.into_iter())
1048 .map(|(((o, h), l), c)| match (o, h, l, c) {
1049 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1050 Some(indicator.next((o_, h_, l_, c_)) as f64),
1051 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1052 _ => None,
1053 }).collect();
1054 Ok(out.into_series())
1055}
1056
1057#[polars_expr(output_type=Float64)]
1058fn cdl_hikkakemod(inputs: &[Series]) -> PolarsResult<Series> {
1059 let open = inputs[0].f64()?;
1060 let high = inputs[1].f64()?;
1061 let low = inputs[2].f64()?;
1062 let close = inputs[3].f64()?;
1063 let mut indicator = quantwave_core::CDLHIKKAKEMOD::new();
1064 let out: Float64Chunked = open.into_iter()
1065 .zip(high.into_iter())
1066 .zip(low.into_iter())
1067 .zip(close.into_iter())
1068 .map(|(((o, h), l), c)| match (o, h, l, c) {
1069 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1070 Some(indicator.next((o_, h_, l_, c_)) as f64),
1071 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1072 _ => None,
1073 }).collect();
1074 Ok(out.into_series())
1075}
1076
1077#[polars_expr(output_type=Float64)]
1078fn cdl_homingpigeon(inputs: &[Series]) -> PolarsResult<Series> {
1079 let open = inputs[0].f64()?;
1080 let high = inputs[1].f64()?;
1081 let low = inputs[2].f64()?;
1082 let close = inputs[3].f64()?;
1083 let mut indicator = quantwave_core::CDLHOMINGPIGEON::new();
1084 let out: Float64Chunked = open.into_iter()
1085 .zip(high.into_iter())
1086 .zip(low.into_iter())
1087 .zip(close.into_iter())
1088 .map(|(((o, h), l), c)| match (o, h, l, c) {
1089 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1090 Some(indicator.next((o_, h_, l_, c_)) as f64),
1091 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1092 _ => None,
1093 }).collect();
1094 Ok(out.into_series())
1095}
1096
1097#[polars_expr(output_type=Float64)]
1098fn cdl_identical3crows(inputs: &[Series]) -> PolarsResult<Series> {
1099 let open = inputs[0].f64()?;
1100 let high = inputs[1].f64()?;
1101 let low = inputs[2].f64()?;
1102 let close = inputs[3].f64()?;
1103 let mut indicator = quantwave_core::CDLIDENTICAL3CROWS::new();
1104 let out: Float64Chunked = open.into_iter()
1105 .zip(high.into_iter())
1106 .zip(low.into_iter())
1107 .zip(close.into_iter())
1108 .map(|(((o, h), l), c)| match (o, h, l, c) {
1109 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1110 Some(indicator.next((o_, h_, l_, c_)) as f64),
1111 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1112 _ => None,
1113 }).collect();
1114 Ok(out.into_series())
1115}
1116
1117#[polars_expr(output_type=Float64)]
1118fn cdl_inneck(inputs: &[Series]) -> PolarsResult<Series> {
1119 let open = inputs[0].f64()?;
1120 let high = inputs[1].f64()?;
1121 let low = inputs[2].f64()?;
1122 let close = inputs[3].f64()?;
1123 let mut indicator = quantwave_core::CDLINNECK::new();
1124 let out: Float64Chunked = open.into_iter()
1125 .zip(high.into_iter())
1126 .zip(low.into_iter())
1127 .zip(close.into_iter())
1128 .map(|(((o, h), l), c)| match (o, h, l, c) {
1129 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1130 Some(indicator.next((o_, h_, l_, c_)) as f64),
1131 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1132 _ => None,
1133 }).collect();
1134 Ok(out.into_series())
1135}
1136
1137#[polars_expr(output_type=Float64)]
1138fn cdl_invertedhammer(inputs: &[Series]) -> PolarsResult<Series> {
1139 let open = inputs[0].f64()?;
1140 let high = inputs[1].f64()?;
1141 let low = inputs[2].f64()?;
1142 let close = inputs[3].f64()?;
1143 let mut indicator = quantwave_core::CDLINVERTEDHAMMER::new();
1144 let out: Float64Chunked = open.into_iter()
1145 .zip(high.into_iter())
1146 .zip(low.into_iter())
1147 .zip(close.into_iter())
1148 .map(|(((o, h), l), c)| match (o, h, l, c) {
1149 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1150 Some(indicator.next((o_, h_, l_, c_)) as f64),
1151 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1152 _ => None,
1153 }).collect();
1154 Ok(out.into_series())
1155}
1156
1157#[polars_expr(output_type=Float64)]
1158fn cdl_kicking(inputs: &[Series]) -> PolarsResult<Series> {
1159 let open = inputs[0].f64()?;
1160 let high = inputs[1].f64()?;
1161 let low = inputs[2].f64()?;
1162 let close = inputs[3].f64()?;
1163 let mut indicator = quantwave_core::CDLKICKING::new();
1164 let out: Float64Chunked = open.into_iter()
1165 .zip(high.into_iter())
1166 .zip(low.into_iter())
1167 .zip(close.into_iter())
1168 .map(|(((o, h), l), c)| match (o, h, l, c) {
1169 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1170 Some(indicator.next((o_, h_, l_, c_)) as f64),
1171 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1172 _ => None,
1173 }).collect();
1174 Ok(out.into_series())
1175}
1176
1177#[polars_expr(output_type=Float64)]
1178fn cdl_kickingbylength(inputs: &[Series]) -> PolarsResult<Series> {
1179 let open = inputs[0].f64()?;
1180 let high = inputs[1].f64()?;
1181 let low = inputs[2].f64()?;
1182 let close = inputs[3].f64()?;
1183 let mut indicator = quantwave_core::CDLKICKINGBYLENGTH::new();
1184 let out: Float64Chunked = open.into_iter()
1185 .zip(high.into_iter())
1186 .zip(low.into_iter())
1187 .zip(close.into_iter())
1188 .map(|(((o, h), l), c)| match (o, h, l, c) {
1189 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1190 Some(indicator.next((o_, h_, l_, c_)) as f64),
1191 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1192 _ => None,
1193 }).collect();
1194 Ok(out.into_series())
1195}
1196
1197#[polars_expr(output_type=Float64)]
1198fn cdl_ladderbottom(inputs: &[Series]) -> PolarsResult<Series> {
1199 let open = inputs[0].f64()?;
1200 let high = inputs[1].f64()?;
1201 let low = inputs[2].f64()?;
1202 let close = inputs[3].f64()?;
1203 let mut indicator = quantwave_core::CDLLADDERBOTTOM::new();
1204 let out: Float64Chunked = open.into_iter()
1205 .zip(high.into_iter())
1206 .zip(low.into_iter())
1207 .zip(close.into_iter())
1208 .map(|(((o, h), l), c)| match (o, h, l, c) {
1209 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1210 Some(indicator.next((o_, h_, l_, c_)) as f64),
1211 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1212 _ => None,
1213 }).collect();
1214 Ok(out.into_series())
1215}
1216
1217#[polars_expr(output_type=Float64)]
1218fn cdl_longleggeddoji(inputs: &[Series]) -> PolarsResult<Series> {
1219 let open = inputs[0].f64()?;
1220 let high = inputs[1].f64()?;
1221 let low = inputs[2].f64()?;
1222 let close = inputs[3].f64()?;
1223 let mut indicator = quantwave_core::CDLLONGLEGGEDDOJI::new();
1224 let out: Float64Chunked = open.into_iter()
1225 .zip(high.into_iter())
1226 .zip(low.into_iter())
1227 .zip(close.into_iter())
1228 .map(|(((o, h), l), c)| match (o, h, l, c) {
1229 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1230 Some(indicator.next((o_, h_, l_, c_)) as f64),
1231 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1232 _ => None,
1233 }).collect();
1234 Ok(out.into_series())
1235}
1236
1237#[polars_expr(output_type=Float64)]
1238fn cdl_longline(inputs: &[Series]) -> PolarsResult<Series> {
1239 let open = inputs[0].f64()?;
1240 let high = inputs[1].f64()?;
1241 let low = inputs[2].f64()?;
1242 let close = inputs[3].f64()?;
1243 let mut indicator = quantwave_core::CDLLONGLINE::new();
1244 let out: Float64Chunked = open.into_iter()
1245 .zip(high.into_iter())
1246 .zip(low.into_iter())
1247 .zip(close.into_iter())
1248 .map(|(((o, h), l), c)| match (o, h, l, c) {
1249 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1250 Some(indicator.next((o_, h_, l_, c_)) as f64),
1251 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1252 _ => None,
1253 }).collect();
1254 Ok(out.into_series())
1255}
1256
1257#[polars_expr(output_type=Float64)]
1258fn cdl_marubozu(inputs: &[Series]) -> PolarsResult<Series> {
1259 let open = inputs[0].f64()?;
1260 let high = inputs[1].f64()?;
1261 let low = inputs[2].f64()?;
1262 let close = inputs[3].f64()?;
1263 let mut indicator = quantwave_core::CDLMARUBOZU::new();
1264 let out: Float64Chunked = open.into_iter()
1265 .zip(high.into_iter())
1266 .zip(low.into_iter())
1267 .zip(close.into_iter())
1268 .map(|(((o, h), l), c)| match (o, h, l, c) {
1269 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1270 Some(indicator.next((o_, h_, l_, c_)) as f64),
1271 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1272 _ => None,
1273 }).collect();
1274 Ok(out.into_series())
1275}
1276
1277#[polars_expr(output_type=Float64)]
1278fn cdl_matchinglow(inputs: &[Series]) -> PolarsResult<Series> {
1279 let open = inputs[0].f64()?;
1280 let high = inputs[1].f64()?;
1281 let low = inputs[2].f64()?;
1282 let close = inputs[3].f64()?;
1283 let mut indicator = quantwave_core::CDLMATCHINGLOW::new();
1284 let out: Float64Chunked = open.into_iter()
1285 .zip(high.into_iter())
1286 .zip(low.into_iter())
1287 .zip(close.into_iter())
1288 .map(|(((o, h), l), c)| match (o, h, l, c) {
1289 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1290 Some(indicator.next((o_, h_, l_, c_)) as f64),
1291 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1292 _ => None,
1293 }).collect();
1294 Ok(out.into_series())
1295}
1296
1297#[polars_expr(output_type=Float64)]
1298fn cdl_mathold(inputs: &[Series]) -> PolarsResult<Series> {
1299 let open = inputs[0].f64()?;
1300 let high = inputs[1].f64()?;
1301 let low = inputs[2].f64()?;
1302 let close = inputs[3].f64()?;
1303 let mut indicator = quantwave_core::CDLMATHOLD::new();
1304 let out: Float64Chunked = open.into_iter()
1305 .zip(high.into_iter())
1306 .zip(low.into_iter())
1307 .zip(close.into_iter())
1308 .map(|(((o, h), l), c)| match (o, h, l, c) {
1309 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1310 Some(indicator.next((o_, h_, l_, c_)) as f64),
1311 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1312 _ => None,
1313 }).collect();
1314 Ok(out.into_series())
1315}
1316
1317#[polars_expr(output_type=Float64)]
1318fn cdl_morningdojistar(inputs: &[Series]) -> PolarsResult<Series> {
1319 let open = inputs[0].f64()?;
1320 let high = inputs[1].f64()?;
1321 let low = inputs[2].f64()?;
1322 let close = inputs[3].f64()?;
1323 let mut indicator = quantwave_core::CDLMORNINGDOJISTAR::new();
1324 let out: Float64Chunked = open.into_iter()
1325 .zip(high.into_iter())
1326 .zip(low.into_iter())
1327 .zip(close.into_iter())
1328 .map(|(((o, h), l), c)| match (o, h, l, c) {
1329 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1330 Some(indicator.next((o_, h_, l_, c_)) as f64),
1331 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1332 _ => None,
1333 }).collect();
1334 Ok(out.into_series())
1335}
1336
1337#[polars_expr(output_type=Float64)]
1338fn cdl_morningstar(inputs: &[Series]) -> PolarsResult<Series> {
1339 let open = inputs[0].f64()?;
1340 let high = inputs[1].f64()?;
1341 let low = inputs[2].f64()?;
1342 let close = inputs[3].f64()?;
1343 let mut indicator = quantwave_core::CDLMORNINGSTAR::new();
1344 let out: Float64Chunked = open.into_iter()
1345 .zip(high.into_iter())
1346 .zip(low.into_iter())
1347 .zip(close.into_iter())
1348 .map(|(((o, h), l), c)| match (o, h, l, c) {
1349 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1350 Some(indicator.next((o_, h_, l_, c_)) as f64),
1351 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1352 _ => None,
1353 }).collect();
1354 Ok(out.into_series())
1355}
1356
1357#[polars_expr(output_type=Float64)]
1358fn cdl_onneck(inputs: &[Series]) -> PolarsResult<Series> {
1359 let open = inputs[0].f64()?;
1360 let high = inputs[1].f64()?;
1361 let low = inputs[2].f64()?;
1362 let close = inputs[3].f64()?;
1363 let mut indicator = quantwave_core::CDLONNECK::new();
1364 let out: Float64Chunked = open.into_iter()
1365 .zip(high.into_iter())
1366 .zip(low.into_iter())
1367 .zip(close.into_iter())
1368 .map(|(((o, h), l), c)| match (o, h, l, c) {
1369 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1370 Some(indicator.next((o_, h_, l_, c_)) as f64),
1371 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1372 _ => None,
1373 }).collect();
1374 Ok(out.into_series())
1375}
1376
1377#[polars_expr(output_type=Float64)]
1378fn cdl_piercing(inputs: &[Series]) -> PolarsResult<Series> {
1379 let open = inputs[0].f64()?;
1380 let high = inputs[1].f64()?;
1381 let low = inputs[2].f64()?;
1382 let close = inputs[3].f64()?;
1383 let mut indicator = quantwave_core::CDLPIERCING::new();
1384 let out: Float64Chunked = open.into_iter()
1385 .zip(high.into_iter())
1386 .zip(low.into_iter())
1387 .zip(close.into_iter())
1388 .map(|(((o, h), l), c)| match (o, h, l, c) {
1389 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1390 Some(indicator.next((o_, h_, l_, c_)) as f64),
1391 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1392 _ => None,
1393 }).collect();
1394 Ok(out.into_series())
1395}
1396
1397#[polars_expr(output_type=Float64)]
1398fn cdl_rickshawman(inputs: &[Series]) -> PolarsResult<Series> {
1399 let open = inputs[0].f64()?;
1400 let high = inputs[1].f64()?;
1401 let low = inputs[2].f64()?;
1402 let close = inputs[3].f64()?;
1403 let mut indicator = quantwave_core::CDLRICKSHAWMAN::new();
1404 let out: Float64Chunked = open.into_iter()
1405 .zip(high.into_iter())
1406 .zip(low.into_iter())
1407 .zip(close.into_iter())
1408 .map(|(((o, h), l), c)| match (o, h, l, c) {
1409 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1410 Some(indicator.next((o_, h_, l_, c_)) as f64),
1411 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1412 _ => None,
1413 }).collect();
1414 Ok(out.into_series())
1415}
1416
1417#[polars_expr(output_type=Float64)]
1418fn cdl_risefall3methods(inputs: &[Series]) -> PolarsResult<Series> {
1419 let open = inputs[0].f64()?;
1420 let high = inputs[1].f64()?;
1421 let low = inputs[2].f64()?;
1422 let close = inputs[3].f64()?;
1423 let mut indicator = quantwave_core::CDLRISEFALL3METHODS::new();
1424 let out: Float64Chunked = open.into_iter()
1425 .zip(high.into_iter())
1426 .zip(low.into_iter())
1427 .zip(close.into_iter())
1428 .map(|(((o, h), l), c)| match (o, h, l, c) {
1429 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1430 Some(indicator.next((o_, h_, l_, c_)) as f64),
1431 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1432 _ => None,
1433 }).collect();
1434 Ok(out.into_series())
1435}
1436
1437#[polars_expr(output_type=Float64)]
1438fn cdl_separatinglines(inputs: &[Series]) -> PolarsResult<Series> {
1439 let open = inputs[0].f64()?;
1440 let high = inputs[1].f64()?;
1441 let low = inputs[2].f64()?;
1442 let close = inputs[3].f64()?;
1443 let mut indicator = quantwave_core::CDLSEPARATINGLINES::new();
1444 let out: Float64Chunked = open.into_iter()
1445 .zip(high.into_iter())
1446 .zip(low.into_iter())
1447 .zip(close.into_iter())
1448 .map(|(((o, h), l), c)| match (o, h, l, c) {
1449 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1450 Some(indicator.next((o_, h_, l_, c_)) as f64),
1451 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1452 _ => None,
1453 }).collect();
1454 Ok(out.into_series())
1455}
1456
1457#[polars_expr(output_type=Float64)]
1458fn cdl_shootingstar(inputs: &[Series]) -> PolarsResult<Series> {
1459 let open = inputs[0].f64()?;
1460 let high = inputs[1].f64()?;
1461 let low = inputs[2].f64()?;
1462 let close = inputs[3].f64()?;
1463 let mut indicator = quantwave_core::CDLSHOOTINGSTAR::new();
1464 let out: Float64Chunked = open.into_iter()
1465 .zip(high.into_iter())
1466 .zip(low.into_iter())
1467 .zip(close.into_iter())
1468 .map(|(((o, h), l), c)| match (o, h, l, c) {
1469 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1470 Some(indicator.next((o_, h_, l_, c_)) as f64),
1471 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1472 _ => None,
1473 }).collect();
1474 Ok(out.into_series())
1475}
1476
1477#[polars_expr(output_type=Float64)]
1478fn cdl_shortline(inputs: &[Series]) -> PolarsResult<Series> {
1479 let open = inputs[0].f64()?;
1480 let high = inputs[1].f64()?;
1481 let low = inputs[2].f64()?;
1482 let close = inputs[3].f64()?;
1483 let mut indicator = quantwave_core::CDLSHORTLINE::new();
1484 let out: Float64Chunked = open.into_iter()
1485 .zip(high.into_iter())
1486 .zip(low.into_iter())
1487 .zip(close.into_iter())
1488 .map(|(((o, h), l), c)| match (o, h, l, c) {
1489 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1490 Some(indicator.next((o_, h_, l_, c_)) as f64),
1491 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1492 _ => None,
1493 }).collect();
1494 Ok(out.into_series())
1495}
1496
1497#[polars_expr(output_type=Float64)]
1498fn cdl_spinningtop(inputs: &[Series]) -> PolarsResult<Series> {
1499 let open = inputs[0].f64()?;
1500 let high = inputs[1].f64()?;
1501 let low = inputs[2].f64()?;
1502 let close = inputs[3].f64()?;
1503 let mut indicator = quantwave_core::CDLSPINNINGTOP::new();
1504 let out: Float64Chunked = open.into_iter()
1505 .zip(high.into_iter())
1506 .zip(low.into_iter())
1507 .zip(close.into_iter())
1508 .map(|(((o, h), l), c)| match (o, h, l, c) {
1509 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1510 Some(indicator.next((o_, h_, l_, c_)) as f64),
1511 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1512 _ => None,
1513 }).collect();
1514 Ok(out.into_series())
1515}
1516
1517#[polars_expr(output_type=Float64)]
1518fn cdl_stalledpattern(inputs: &[Series]) -> PolarsResult<Series> {
1519 let open = inputs[0].f64()?;
1520 let high = inputs[1].f64()?;
1521 let low = inputs[2].f64()?;
1522 let close = inputs[3].f64()?;
1523 let mut indicator = quantwave_core::CDLSTALLEDPATTERN::new();
1524 let out: Float64Chunked = open.into_iter()
1525 .zip(high.into_iter())
1526 .zip(low.into_iter())
1527 .zip(close.into_iter())
1528 .map(|(((o, h), l), c)| match (o, h, l, c) {
1529 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1530 Some(indicator.next((o_, h_, l_, c_)) as f64),
1531 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1532 _ => None,
1533 }).collect();
1534 Ok(out.into_series())
1535}
1536
1537#[polars_expr(output_type=Float64)]
1538fn cdl_sticksandwich(inputs: &[Series]) -> PolarsResult<Series> {
1539 let open = inputs[0].f64()?;
1540 let high = inputs[1].f64()?;
1541 let low = inputs[2].f64()?;
1542 let close = inputs[3].f64()?;
1543 let mut indicator = quantwave_core::CDLSTICKSANDWICH::new();
1544 let out: Float64Chunked = open.into_iter()
1545 .zip(high.into_iter())
1546 .zip(low.into_iter())
1547 .zip(close.into_iter())
1548 .map(|(((o, h), l), c)| match (o, h, l, c) {
1549 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1550 Some(indicator.next((o_, h_, l_, c_)) as f64),
1551 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1552 _ => None,
1553 }).collect();
1554 Ok(out.into_series())
1555}
1556
1557#[polars_expr(output_type=Float64)]
1558fn cdl_takuri(inputs: &[Series]) -> PolarsResult<Series> {
1559 let open = inputs[0].f64()?;
1560 let high = inputs[1].f64()?;
1561 let low = inputs[2].f64()?;
1562 let close = inputs[3].f64()?;
1563 let mut indicator = quantwave_core::CDLTAKURI::new();
1564 let out: Float64Chunked = open.into_iter()
1565 .zip(high.into_iter())
1566 .zip(low.into_iter())
1567 .zip(close.into_iter())
1568 .map(|(((o, h), l), c)| match (o, h, l, c) {
1569 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1570 Some(indicator.next((o_, h_, l_, c_)) as f64),
1571 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1572 _ => None,
1573 }).collect();
1574 Ok(out.into_series())
1575}
1576
1577#[polars_expr(output_type=Float64)]
1578fn cdl_tasukigap(inputs: &[Series]) -> PolarsResult<Series> {
1579 let open = inputs[0].f64()?;
1580 let high = inputs[1].f64()?;
1581 let low = inputs[2].f64()?;
1582 let close = inputs[3].f64()?;
1583 let mut indicator = quantwave_core::CDLTASUKIGAP::new();
1584 let out: Float64Chunked = open.into_iter()
1585 .zip(high.into_iter())
1586 .zip(low.into_iter())
1587 .zip(close.into_iter())
1588 .map(|(((o, h), l), c)| match (o, h, l, c) {
1589 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1590 Some(indicator.next((o_, h_, l_, c_)) as f64),
1591 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1592 _ => None,
1593 }).collect();
1594 Ok(out.into_series())
1595}
1596
1597#[polars_expr(output_type=Float64)]
1598fn cdl_thrusting(inputs: &[Series]) -> PolarsResult<Series> {
1599 let open = inputs[0].f64()?;
1600 let high = inputs[1].f64()?;
1601 let low = inputs[2].f64()?;
1602 let close = inputs[3].f64()?;
1603 let mut indicator = quantwave_core::CDLTHRUSTING::new();
1604 let out: Float64Chunked = open.into_iter()
1605 .zip(high.into_iter())
1606 .zip(low.into_iter())
1607 .zip(close.into_iter())
1608 .map(|(((o, h), l), c)| match (o, h, l, c) {
1609 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1610 Some(indicator.next((o_, h_, l_, c_)) as f64),
1611 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1612 _ => None,
1613 }).collect();
1614 Ok(out.into_series())
1615}
1616
1617#[polars_expr(output_type=Float64)]
1618fn cdl_tristar(inputs: &[Series]) -> PolarsResult<Series> {
1619 let open = inputs[0].f64()?;
1620 let high = inputs[1].f64()?;
1621 let low = inputs[2].f64()?;
1622 let close = inputs[3].f64()?;
1623 let mut indicator = quantwave_core::CDLTRISTAR::new();
1624 let out: Float64Chunked = open.into_iter()
1625 .zip(high.into_iter())
1626 .zip(low.into_iter())
1627 .zip(close.into_iter())
1628 .map(|(((o, h), l), c)| match (o, h, l, c) {
1629 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1630 Some(indicator.next((o_, h_, l_, c_)) as f64),
1631 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1632 _ => None,
1633 }).collect();
1634 Ok(out.into_series())
1635}
1636
1637#[polars_expr(output_type=Float64)]
1638fn cdl_unique3river(inputs: &[Series]) -> PolarsResult<Series> {
1639 let open = inputs[0].f64()?;
1640 let high = inputs[1].f64()?;
1641 let low = inputs[2].f64()?;
1642 let close = inputs[3].f64()?;
1643 let mut indicator = quantwave_core::CDLUNIQUE3RIVER::new();
1644 let out: Float64Chunked = open.into_iter()
1645 .zip(high.into_iter())
1646 .zip(low.into_iter())
1647 .zip(close.into_iter())
1648 .map(|(((o, h), l), c)| match (o, h, l, c) {
1649 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1650 Some(indicator.next((o_, h_, l_, c_)) as f64),
1651 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1652 _ => None,
1653 }).collect();
1654 Ok(out.into_series())
1655}
1656
1657#[polars_expr(output_type=Float64)]
1658fn cdl_upsidegap2crows(inputs: &[Series]) -> PolarsResult<Series> {
1659 let open = inputs[0].f64()?;
1660 let high = inputs[1].f64()?;
1661 let low = inputs[2].f64()?;
1662 let close = inputs[3].f64()?;
1663 let mut indicator = quantwave_core::CDLUPSIDEGAP2CROWS::new();
1664 let out: Float64Chunked = open.into_iter()
1665 .zip(high.into_iter())
1666 .zip(low.into_iter())
1667 .zip(close.into_iter())
1668 .map(|(((o, h), l), c)| match (o, h, l, c) {
1669 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1670 Some(indicator.next((o_, h_, l_, c_)) as f64),
1671 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1672 _ => None,
1673 }).collect();
1674 Ok(out.into_series())
1675}
1676
1677#[polars_expr(output_type=Float64)]
1678fn cdl_xsidegap3methods(inputs: &[Series]) -> PolarsResult<Series> {
1679 let open = inputs[0].f64()?;
1680 let high = inputs[1].f64()?;
1681 let low = inputs[2].f64()?;
1682 let close = inputs[3].f64()?;
1683 let mut indicator = quantwave_core::CDLXSIDEGAP3METHODS::new();
1684 let out: Float64Chunked = open.into_iter()
1685 .zip(high.into_iter())
1686 .zip(low.into_iter())
1687 .zip(close.into_iter())
1688 .map(|(((o, h), l), c)| match (o, h, l, c) {
1689 (Some(o_), Some(h_), Some(l_), Some(c_)) if !o_.is_nan() && !h_.is_nan() && !l_.is_nan() && !c_.is_nan() =>
1690 Some(indicator.next((o_, h_, l_, c_)) as f64),
1691 (Some(_), Some(_), Some(_), Some(_)) => Some(f64::NAN),
1692 _ => None,
1693 }).collect();
1694 Ok(out.into_series())
1695}