use super::*;
use crate::error::TaError;
use crate::indicator::indicator;
indicator! {
fn cdl_homingpigeon(open: &[f64], high: &[f64], low: &[f64], close: &[f64]) -> Vec<f64> with cdl_homingpigeon_with_output init zero;
}
pub fn cdl_homingpigeon_with_output(
open: &[f64],
high: &[f64],
low: &[f64],
close: &[f64],
out: &mut [f64],
) -> Result<(), TaError> {
if out.len() != open.len() {
return Err(TaError::BadParam(
"cdl_homingpigeon_with_output: out length must equal input length".into(),
));
}
check_ohlc(open, high, low, close, "cdl_homingpigeon")?;
let n = open.len();
let lookback = BODY_SHORT.avg_period.max(BODY_LONG.avg_period) + 1; if n <= lookback {
return Ok(());
}
let mut sum_avg_body_long = {
let mut s = lookback - 1 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 1) {
acc += real_body(open[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_body_long = lookback - 1 - 10;
let mut sum_avg_body_short = {
let mut s = lookback - 0 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 0) {
acc += real_body(open[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_body_short = lookback - 0 - 10;
let mut i = lookback;
while i < n {
let cur_avg_body_long = real_body(open[i - 1], close[i - 1]);
let val_avg_body_long = sum_avg_body_long / 10 as f64 * 1.0;
let cur_avg_body_short = real_body(open[i], close[i]);
let val_avg_body_short = sum_avg_body_short / 10 as f64 * 1.0;
out[i] = if candle_color(open[i - 1], close[i - 1]) == -1.0 && candle_color(open[i], close[i]) == -1.0 && cur_avg_body_long > val_avg_body_long && cur_avg_body_short <= val_avg_body_short && open[i] < open[i - 1] && close[i] > close[i - 1]
{
100.0
} else {
0.0
};
sum_avg_body_long +=
cur_avg_body_long - real_body(open[trail_avg_body_long], close[trail_avg_body_long]);
trail_avg_body_long += 1;
sum_avg_body_short +=
cur_avg_body_short - real_body(open[trail_avg_body_short], close[trail_avg_body_short]);
trail_avg_body_short += 1;
i += 1;
}
Ok(())
}
indicator! {
fn cdl_identical3crows(open: &[f64], high: &[f64], low: &[f64], close: &[f64]) -> Vec<f64> with cdl_identical3crows_with_output init zero;
}
pub fn cdl_identical3crows_with_output(
open: &[f64],
high: &[f64],
low: &[f64],
close: &[f64],
out: &mut [f64],
) -> Result<(), TaError> {
if out.len() != open.len() {
return Err(TaError::BadParam(
"cdl_identical3crows_with_output: out length must equal input length".into(),
));
}
check_ohlc(open, high, low, close, "cdl_identical3crows")?;
let n = open.len();
let lookback = SHADOW_VERY_SHORT.avg_period.max(EQUAL.avg_period) + 2; if n <= lookback {
return Ok(());
}
let mut sum_avg_sv_2 = {
let mut s = lookback - 2 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 2) {
acc += high_low_range(high[s], low[s]);
s += 1;
}
acc
};
let mut trail_avg_sv_2 = lookback - 2 - 10;
let mut sum_avg_sv_1 = {
let mut s = lookback - 1 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 1) {
acc += high_low_range(high[s], low[s]);
s += 1;
}
acc
};
let mut trail_avg_sv_1 = lookback - 1 - 10;
let mut sum_avg_sv_0 = {
let mut s = lookback - 0 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 0) {
acc += high_low_range(high[s], low[s]);
s += 1;
}
acc
};
let mut trail_avg_sv_0 = lookback - 0 - 10;
let mut sum_avg_eq_2 = {
let mut s = lookback - 2 - 5;
let mut acc = 0.0_f64;
while s < (lookback - 2) {
acc += high_low_range(high[s], low[s]);
s += 1;
}
acc
};
let mut trail_avg_eq_2 = lookback - 2 - 5;
let mut sum_avg_eq_1 = {
let mut s = lookback - 1 - 5;
let mut acc = 0.0_f64;
while s < (lookback - 1) {
acc += high_low_range(high[s], low[s]);
s += 1;
}
acc
};
let mut trail_avg_eq_1 = lookback - 1 - 5;
let mut i = lookback;
while i < n {
let cur_avg_sv_2 = high_low_range(high[i - 2], low[i - 2]);
let val_avg_sv_2 = sum_avg_sv_2 / 10 as f64 * 0.1;
let cur_avg_sv_1 = high_low_range(high[i - 1], low[i - 1]);
let val_avg_sv_1 = sum_avg_sv_1 / 10 as f64 * 0.1;
let cur_avg_sv_0 = high_low_range(high[i], low[i]);
let val_avg_sv_0 = sum_avg_sv_0 / 10 as f64 * 0.1;
let cur_avg_eq_2 = high_low_range(high[i - 2], low[i - 2]);
let val_avg_eq_2 = sum_avg_eq_2 / 5 as f64 * 0.05;
let cur_avg_eq_1 = high_low_range(high[i - 1], low[i - 1]);
let val_avg_eq_1 = sum_avg_eq_1 / 5 as f64 * 0.05;
out[i] = if candle_color(open[i - 2], close[i - 2]) == -1.0 && lower_shadow(open[i - 2], low[i - 2], close[i - 2])
< val_avg_sv_2 && candle_color(open[i - 1], close[i - 1]) == -1.0 && lower_shadow(open[i - 1], low[i - 1], close[i - 1])
< val_avg_sv_1 && candle_color(open[i], close[i]) == -1.0 && lower_shadow(open[i], low[i], close[i])
< val_avg_sv_0 && close[i - 2] > close[i - 1] && close[i - 1] > close[i]
&& open[i - 1] <= close[i - 2] + val_avg_eq_2 && open[i - 1] >= close[i - 2] - val_avg_eq_2
&& open[i] <= close[i - 1] + val_avg_eq_1 && open[i] >= close[i - 1] - val_avg_eq_1
{
-100.0
} else {
0.0
};
sum_avg_sv_2 += cur_avg_sv_2 - high_low_range(high[trail_avg_sv_2], low[trail_avg_sv_2]);
trail_avg_sv_2 += 1;
sum_avg_sv_1 += cur_avg_sv_1 - high_low_range(high[trail_avg_sv_1], low[trail_avg_sv_1]);
trail_avg_sv_1 += 1;
sum_avg_sv_0 += cur_avg_sv_0 - high_low_range(high[trail_avg_sv_0], low[trail_avg_sv_0]);
trail_avg_sv_0 += 1;
sum_avg_eq_2 += cur_avg_eq_2 - high_low_range(high[trail_avg_eq_2], low[trail_avg_eq_2]);
trail_avg_eq_2 += 1;
sum_avg_eq_1 += cur_avg_eq_1 - high_low_range(high[trail_avg_eq_1], low[trail_avg_eq_1]);
trail_avg_eq_1 += 1;
i += 1;
}
Ok(())
}
indicator! {
fn cdl_inneck(open: &[f64], high: &[f64], low: &[f64], close: &[f64]) -> Vec<f64> with cdl_inneck_with_output init zero;
}
pub fn cdl_inneck_with_output(
open: &[f64],
high: &[f64],
low: &[f64],
close: &[f64],
out: &mut [f64],
) -> Result<(), TaError> {
if out.len() != open.len() {
return Err(TaError::BadParam(
"cdl_inneck_with_output: out length must equal input length".into(),
));
}
check_ohlc(open, high, low, close, "cdl_inneck")?;
let n = open.len();
let lookback = EQUAL.avg_period.max(BODY_LONG.avg_period) + 1; if n <= lookback {
return Ok(());
}
let mut sum_avg_equal = {
let mut s = lookback - 1 - 5;
let mut acc = 0.0_f64;
while s < (lookback - 1) {
acc += high_low_range(high[s], low[s]);
s += 1;
}
acc
};
let mut trail_avg_equal = lookback - 1 - 5;
let mut sum_avg_body_long = {
let mut s = lookback - 1 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 1) {
acc += real_body(open[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_body_long = lookback - 1 - 10;
let mut i = lookback;
while i < n {
let cur_avg_equal = high_low_range(high[i - 1], low[i - 1]);
let val_avg_equal = sum_avg_equal / 5 as f64 * 0.05;
let cur_avg_body_long = real_body(open[i - 1], close[i - 1]);
let val_avg_body_long = sum_avg_body_long / 10 as f64 * 1.0;
out[i] = if candle_color(open[i - 1], close[i - 1]) == -1.0 && real_body(open[i - 1], close[i - 1]) > val_avg_body_long && candle_color(open[i], close[i]) == 1.0 && open[i] < low[i - 1] && close[i] <= close[i - 1] + val_avg_equal && close[i] >= close[i - 1]
{
-100.0
} else {
0.0
};
sum_avg_equal +=
cur_avg_equal - high_low_range(high[trail_avg_equal], low[trail_avg_equal]);
trail_avg_equal += 1;
sum_avg_body_long +=
cur_avg_body_long - real_body(open[trail_avg_body_long], close[trail_avg_body_long]);
trail_avg_body_long += 1;
i += 1;
}
Ok(())
}
indicator! {
fn cdl_invertedhammer(open: &[f64], high: &[f64], low: &[f64], close: &[f64]) -> Vec<f64> with cdl_invertedhammer_with_output init zero;
}
pub fn cdl_invertedhammer_with_output(
open: &[f64],
high: &[f64],
low: &[f64],
close: &[f64],
out: &mut [f64],
) -> Result<(), TaError> {
if out.len() != open.len() {
return Err(TaError::BadParam(
"cdl_invertedhammer_with_output: out length must equal input length".into(),
));
}
check_ohlc(open, high, low, close, "cdl_invertedhammer")?;
let n = open.len();
let lookback = [
BODY_SHORT.avg_period,
SHADOW_LONG.avg_period,
SHADOW_VERY_SHORT.avg_period,
]
.iter()
.max()
.copied()
.unwrap()
+ 1; if n <= lookback {
return Ok(());
}
let mut sum_avg_body = {
let mut s = lookback - 0 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 0) {
acc += real_body(open[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_body = lookback - 0 - 10;
let mut sum_avg_shadow_long = {
let mut s = lookback - 0 - 0;
let mut acc = 0.0_f64;
while s < (lookback - 0) {
acc += real_body(open[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_shadow_long = lookback - 0 - 0;
let mut sum_avg_shadow_vshort = {
let mut s = lookback - 0 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 0) {
acc += high_low_range(high[s], low[s]);
s += 1;
}
acc
};
let mut trail_avg_shadow_vshort = lookback - 0 - 10;
let mut i = lookback;
while i < n {
let cur_avg_body = real_body(open[i], close[i]);
let val_avg_body = sum_avg_body / 10 as f64 * 1.0;
let cur_avg_shadow_long = real_body(open[i], close[i]);
let val_avg_shadow_long = cur_avg_shadow_long * 1.0;
let cur_avg_shadow_vshort = high_low_range(high[i], low[i]);
let val_avg_shadow_vshort = sum_avg_shadow_vshort / 10 as f64 * 0.1;
out[i] = if real_body(open[i], close[i]) < val_avg_body && upper_shadow(open[i], high[i], close[i]) > val_avg_shadow_long && lower_shadow(open[i], low[i], close[i]) < val_avg_shadow_vshort && real_body_gap_down(open[i], close[i], open[i - 1], close[i - 1])
{
100.0
} else {
0.0
};
sum_avg_body += cur_avg_body - real_body(open[trail_avg_body], close[trail_avg_body]);
trail_avg_body += 1;
sum_avg_shadow_long += cur_avg_shadow_long
- real_body(open[trail_avg_shadow_long], close[trail_avg_shadow_long]);
trail_avg_shadow_long += 1;
sum_avg_shadow_vshort += cur_avg_shadow_vshort
- high_low_range(high[trail_avg_shadow_vshort], low[trail_avg_shadow_vshort]);
trail_avg_shadow_vshort += 1;
i += 1;
}
Ok(())
}
indicator! {
fn cdl_kicking(open: &[f64], high: &[f64], low: &[f64], close: &[f64]) -> Vec<f64> with cdl_kicking_with_output init zero;
}
pub fn cdl_kicking_with_output(
open: &[f64],
high: &[f64],
low: &[f64],
close: &[f64],
out: &mut [f64],
) -> Result<(), TaError> {
if out.len() != open.len() {
return Err(TaError::BadParam(
"cdl_kicking_with_output: out length must equal input length".into(),
));
}
check_ohlc(open, high, low, close, "cdl_kicking")?;
let n = open.len();
let lookback = SHADOW_VERY_SHORT.avg_period.max(BODY_LONG.avg_period) + 1; if n <= lookback {
return Ok(());
}
let mut sum_avg_body_1 = {
let mut s = lookback - 1 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 1) {
acc += real_body(open[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_body_1 = lookback - 1 - 10;
let mut sum_avg_body_0 = {
let mut s = lookback - 0 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 0) {
acc += real_body(open[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_body_0 = lookback - 0 - 10;
let mut sum_avg_sv_1 = {
let mut s = lookback - 1 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 1) {
acc += high_low_range(high[s], low[s]);
s += 1;
}
acc
};
let mut trail_avg_sv_1 = lookback - 1 - 10;
let mut sum_avg_sv_0 = {
let mut s = lookback - 0 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 0) {
acc += high_low_range(high[s], low[s]);
s += 1;
}
acc
};
let mut trail_avg_sv_0 = lookback - 0 - 10;
let mut i = lookback;
while i < n {
let cur_avg_body_1 = real_body(open[i - 1], close[i - 1]);
let val_avg_body_1 = sum_avg_body_1 / 10 as f64 * 1.0;
let cur_avg_body_0 = real_body(open[i], close[i]);
let val_avg_body_0 = sum_avg_body_0 / 10 as f64 * 1.0;
let cur_avg_sv_1 = high_low_range(high[i - 1], low[i - 1]);
let val_avg_sv_1 = sum_avg_sv_1 / 10 as f64 * 0.1;
let cur_avg_sv_0 = high_low_range(high[i], low[i]);
let val_avg_sv_0 = sum_avg_sv_0 / 10 as f64 * 0.1;
let c_prev = candle_color(open[i - 1], close[i - 1]);
let c_cur = candle_color(open[i], close[i]);
out[i] = if c_prev == -c_cur && real_body(open[i - 1], close[i - 1]) > val_avg_body_1
&& upper_shadow(open[i - 1], high[i - 1], close[i - 1]) < val_avg_sv_1
&& lower_shadow(open[i - 1], low[i - 1], close[i - 1]) < val_avg_sv_1
&& cur_avg_body_0 > val_avg_body_0
&& upper_shadow(open[i], high[i], close[i]) < val_avg_sv_0
&& lower_shadow(open[i], low[i], close[i]) < val_avg_sv_0
&& (
(c_prev == -1.0 && candle_gap_up(low[i], high[i - 1]))
|| (c_prev == 1.0 && candle_gap_down(high[i], low[i - 1]))
) {
c_cur * 100.0
} else {
0.0
};
sum_avg_body_1 +=
cur_avg_body_1 - real_body(open[trail_avg_body_1], close[trail_avg_body_1]);
trail_avg_body_1 += 1;
sum_avg_body_0 +=
cur_avg_body_0 - real_body(open[trail_avg_body_0], close[trail_avg_body_0]);
trail_avg_body_0 += 1;
sum_avg_sv_1 += cur_avg_sv_1 - high_low_range(high[trail_avg_sv_1], low[trail_avg_sv_1]);
trail_avg_sv_1 += 1;
sum_avg_sv_0 += cur_avg_sv_0 - high_low_range(high[trail_avg_sv_0], low[trail_avg_sv_0]);
trail_avg_sv_0 += 1;
i += 1;
}
Ok(())
}
indicator! {
fn cdl_kickingbylength(open: &[f64], high: &[f64], low: &[f64], close: &[f64]) -> Vec<f64> with cdl_kickingbylength_with_output init zero;
}
pub fn cdl_kickingbylength_with_output(
open: &[f64],
high: &[f64],
low: &[f64],
close: &[f64],
out: &mut [f64],
) -> Result<(), TaError> {
if out.len() != open.len() {
return Err(TaError::BadParam(
"cdl_kickingbylength_with_output: out length must equal input length".into(),
));
}
check_ohlc(open, high, low, close, "cdl_kickingbylength")?;
let n = open.len();
let lookback = SHADOW_VERY_SHORT.avg_period.max(BODY_LONG.avg_period) + 1; if n <= lookback {
return Ok(());
}
let mut sum_avg_body_1 = {
let mut s = lookback - 1 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 1) {
acc += real_body(open[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_body_1 = lookback - 1 - 10;
let mut sum_avg_body_0 = {
let mut s = lookback - 0 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 0) {
acc += real_body(open[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_body_0 = lookback - 0 - 10;
let mut sum_avg_sv_1 = {
let mut s = lookback - 1 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 1) {
acc += high_low_range(high[s], low[s]);
s += 1;
}
acc
};
let mut trail_avg_sv_1 = lookback - 1 - 10;
let mut sum_avg_sv_0 = {
let mut s = lookback - 0 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 0) {
acc += high_low_range(high[s], low[s]);
s += 1;
}
acc
};
let mut trail_avg_sv_0 = lookback - 0 - 10;
let mut i = lookback;
while i < n {
let cur_avg_body_1 = real_body(open[i - 1], close[i - 1]);
let val_avg_body_1 = sum_avg_body_1 / 10 as f64 * 1.0;
let cur_avg_body_0 = real_body(open[i], close[i]);
let val_avg_body_0 = sum_avg_body_0 / 10 as f64 * 1.0;
let cur_avg_sv_1 = high_low_range(high[i - 1], low[i - 1]);
let val_avg_sv_1 = sum_avg_sv_1 / 10 as f64 * 0.1;
let cur_avg_sv_0 = high_low_range(high[i], low[i]);
let val_avg_sv_0 = sum_avg_sv_0 / 10 as f64 * 0.1;
let c_prev = candle_color(open[i - 1], close[i - 1]);
let c_cur = candle_color(open[i], close[i]);
let longer = if cur_avg_body_0 > real_body(open[i - 1], close[i - 1]) {
i
} else {
i - 1
};
out[i] = if c_prev == -c_cur && real_body(open[i - 1], close[i - 1]) > val_avg_body_1
&& upper_shadow(open[i - 1], high[i - 1], close[i - 1]) < val_avg_sv_1
&& lower_shadow(open[i - 1], low[i - 1], close[i - 1]) < val_avg_sv_1
&& cur_avg_body_0 > val_avg_body_0
&& upper_shadow(open[i], high[i], close[i]) < val_avg_sv_0
&& lower_shadow(open[i], low[i], close[i]) < val_avg_sv_0
&& (
(c_prev == -1.0 && candle_gap_up(low[i], high[i - 1]))
|| (c_prev == 1.0 && candle_gap_down(high[i], low[i - 1]))
) {
candle_color(open[longer], close[longer]) * 100.0
} else {
0.0
};
sum_avg_body_1 +=
cur_avg_body_1 - real_body(open[trail_avg_body_1], close[trail_avg_body_1]);
trail_avg_body_1 += 1;
sum_avg_body_0 +=
cur_avg_body_0 - real_body(open[trail_avg_body_0], close[trail_avg_body_0]);
trail_avg_body_0 += 1;
sum_avg_sv_1 += cur_avg_sv_1 - high_low_range(high[trail_avg_sv_1], low[trail_avg_sv_1]);
trail_avg_sv_1 += 1;
sum_avg_sv_0 += cur_avg_sv_0 - high_low_range(high[trail_avg_sv_0], low[trail_avg_sv_0]);
trail_avg_sv_0 += 1;
i += 1;
}
Ok(())
}
indicator! {
fn cdl_ladderbottom(open: &[f64], high: &[f64], low: &[f64], close: &[f64]) -> Vec<f64> with cdl_ladderbottom_with_output init zero;
}
pub fn cdl_ladderbottom_with_output(
open: &[f64],
high: &[f64],
low: &[f64],
close: &[f64],
out: &mut [f64],
) -> Result<(), TaError> {
if out.len() != open.len() {
return Err(TaError::BadParam(
"cdl_ladderbottom_with_output: out length must equal input length".into(),
));
}
check_ohlc(open, high, low, close, "cdl_ladderbottom")?;
let n = open.len();
let lookback = SHADOW_VERY_SHORT.avg_period + 4; if n <= lookback {
return Ok(());
}
let mut sum_avg_sv = {
let mut s = lookback - 1 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 1) {
acc += high_low_range(high[s], low[s]);
s += 1;
}
acc
};
let mut trail_avg_sv = lookback - 1 - 10;
let mut i = lookback;
while i < n {
let cur_avg_sv = high_low_range(high[i - 1], low[i - 1]);
let val_avg_sv = sum_avg_sv / 10 as f64 * 0.1;
out[i] = if candle_color(open[i - 4], close[i - 4]) == -1.0 && candle_color(open[i - 3], close[i - 3]) == -1.0 && candle_color(open[i - 2], close[i - 2]) == -1.0 && open[i - 4] > open[i - 3] && open[i - 3] > open[i - 2]
&& close[i - 4] > close[i - 3] && close[i - 3] > close[i - 2]
&& candle_color(open[i - 1], close[i - 1]) == -1.0 && upper_shadow(open[i - 1], high[i - 1], close[i - 1]) > val_avg_sv
&& candle_color(open[i], close[i]) == 1.0 && open[i] > open[i - 1] && close[i] > high[i - 1]
{
100.0
} else {
0.0
};
sum_avg_sv += cur_avg_sv - high_low_range(high[trail_avg_sv], low[trail_avg_sv]);
trail_avg_sv += 1;
i += 1;
}
Ok(())
}