use super::*;
use crate::error::TaError;
use crate::indicator::indicator;
indicator! {
fn cdl_3blackcrows(open: &[f64], high: &[f64], low: &[f64], close: &[f64]) -> Vec<f64> with cdl_3blackcrows_with_output init zero;
}
pub fn cdl_3blackcrows_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_3blackcrows_with_output: out length must equal input length".into(),
));
}
check_ohlc(open, high, low, close, "cdl_3blackcrows")?;
let n = open.len();
let lookback = SHADOW_VERY_SHORT.avg_period + 3; if n <= lookback {
return Ok(());
}
let mut sum_avg_vs_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_vs_0 = lookback - 0 - 10;
let mut sum_avg_vs_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_vs_1 = lookback - 1 - 10;
let mut sum_avg_vs_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_vs_2 = lookback - 2 - 10;
let mut i = lookback;
while i < n {
let cur_avg_vs_0 = high_low_range(high[i], low[i]);
let val_avg_vs_0 = sum_avg_vs_0 / 10 as f64 * 0.1;
let cur_avg_vs_1 = high_low_range(high[i - 1], low[i - 1]);
let val_avg_vs_1 = sum_avg_vs_1 / 10 as f64 * 0.1;
let cur_avg_vs_2 = high_low_range(high[i - 2], low[i - 2]);
let val_avg_vs_2 = sum_avg_vs_2 / 10 as f64 * 0.1;
out[i] = if candle_color(open[i - 3], close[i - 3]) == 1.0 && candle_color(open[i - 2], close[i - 2]) == -1.0 && lower_shadow(open[i - 2], low[i - 2], close[i - 2])
< val_avg_vs_2 && candle_color(open[i - 1], close[i - 1]) == -1.0 && lower_shadow(open[i - 1], low[i - 1], close[i - 1])
< val_avg_vs_1
&& candle_color(open[i], close[i]) == -1.0 && lower_shadow(open[i], low[i], close[i]) < val_avg_vs_0
&& open[i - 1] < open[i - 2]
&& open[i - 1] > close[i - 2] && open[i] < open[i - 1]
&& open[i] > close[i - 1] && high[i - 3] > close[i - 2] && close[i - 2] > close[i - 1]
&& close[i - 1] > close[i]
{
-100.0
} else {
0.0
};
sum_avg_vs_0 += cur_avg_vs_0 - high_low_range(high[trail_avg_vs_0], low[trail_avg_vs_0]);
trail_avg_vs_0 += 1;
sum_avg_vs_1 += cur_avg_vs_1 - high_low_range(high[trail_avg_vs_1], low[trail_avg_vs_1]);
trail_avg_vs_1 += 1;
sum_avg_vs_2 += cur_avg_vs_2 - high_low_range(high[trail_avg_vs_2], low[trail_avg_vs_2]);
trail_avg_vs_2 += 1;
i += 1;
}
Ok(())
}
indicator! {
fn cdl_3inside(open: &[f64], high: &[f64], low: &[f64], close: &[f64]) -> Vec<f64> with cdl_3inside_with_output init zero;
}
pub fn cdl_3inside_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_3inside_with_output: out length must equal input length".into(),
));
}
check_ohlc(open, high, low, close, "cdl_3inside")?;
let n = open.len();
let lookback = BODY_SHORT.avg_period.max(BODY_LONG.avg_period) + 2; if n <= lookback {
return Ok(());
}
let mut sum_avg_body_long = {
let mut s = lookback - 2 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 2) {
acc += real_body(open[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_body_long = lookback - 2 - 10;
let mut sum_avg_body_short = {
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_short = lookback - 1 - 10;
let mut i = lookback;
while i < n {
let cur_avg_body_long = real_body(open[i - 2], close[i - 2]);
let val_avg_body_long = sum_avg_body_long / 10 as f64 * 1.0;
let cur_avg_body_short = real_body(open[i - 1], close[i - 1]);
let val_avg_body_short = sum_avg_body_short / 10 as f64 * 1.0;
out[i] = if real_body(open[i - 2], close[i - 2]) > val_avg_body_long && real_body(open[i - 1], close[i - 1]) <= val_avg_body_short && open[i - 1].max(close[i - 1]) < open[i - 2].max(close[i - 2]) && open[i - 1].min(close[i - 1]) > open[i - 2].min(close[i - 2])
&& ((candle_color(open[i - 2], close[i - 2]) == 1.0
&& candle_color(open[i], close[i]) == -1.0
&& close[i] < open[i - 2])
|| (candle_color(open[i - 2], close[i - 2]) == -1.0
&& candle_color(open[i], close[i]) == 1.0
&& close[i] > open[i - 2]))
{
-candle_color(open[i - 2], close[i - 2]) * 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_3linestrike(open: &[f64], high: &[f64], low: &[f64], close: &[f64]) -> Vec<f64> with cdl_3linestrike_with_output init zero;
}
pub fn cdl_3linestrike_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_3linestrike_with_output: out length must equal input length".into(),
));
}
check_ohlc(open, high, low, close, "cdl_3linestrike")?;
let n = open.len();
let lookback = NEAR.avg_period + 3; if n <= lookback {
return Ok(());
}
let mut sum_avg_near_3 = {
let mut s = lookback - 3 - 5;
let mut acc = 0.0_f64;
while s < (lookback - 3) {
acc += high_low_range(high[s], low[s]);
s += 1;
}
acc
};
let mut trail_avg_near_3 = lookback - 3 - 5;
let mut sum_avg_near_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_near_2 = lookback - 2 - 5;
let mut i = lookback;
while i < n {
let cur_avg_near_3 = high_low_range(high[i - 3], low[i - 3]);
let val_avg_near_3 = sum_avg_near_3 / 5 as f64 * 0.2;
let cur_avg_near_2 = high_low_range(high[i - 2], low[i - 2]);
let val_avg_near_2 = sum_avg_near_2 / 5 as f64 * 0.2;
out[i] = if candle_color(open[i - 3], close[i - 3]) == candle_color(open[i - 2], close[i - 2])
&& candle_color(open[i - 2], close[i - 2]) == candle_color(open[i - 1], close[i - 1])
&& candle_color(open[i], close[i]) == -candle_color(open[i - 1], close[i - 1]) && open[i - 2] >= open[i - 3].min(close[i - 3]) - val_avg_near_3
&& open[i - 2] <= open[i - 3].max(close[i - 3]) + val_avg_near_3
&& open[i - 1] >= open[i - 2].min(close[i - 2]) - val_avg_near_2
&& open[i - 1] <= open[i - 2].max(close[i - 2]) + val_avg_near_2
&& ((candle_color(open[i - 1], close[i - 1]) == 1.0
&& close[i - 1] > close[i - 2]
&& close[i - 2] > close[i - 3] && open[i] > close[i - 1] && close[i] < open[i - 3]) || (candle_color(open[i - 1], close[i - 1]) == -1.0
&& close[i - 1] < close[i - 2]
&& close[i - 2] < close[i - 3] && open[i] < close[i - 1] && close[i] > open[i - 3]))
{
candle_color(open[i - 1], close[i - 1]) * 100.0
} else {
0.0
};
sum_avg_near_3 +=
cur_avg_near_3 - high_low_range(high[trail_avg_near_3], low[trail_avg_near_3]);
trail_avg_near_3 += 1;
sum_avg_near_2 +=
cur_avg_near_2 - high_low_range(high[trail_avg_near_2], low[trail_avg_near_2]);
trail_avg_near_2 += 1;
i += 1;
}
Ok(())
}
indicator! {
fn cdl_3outside(open: &[f64], high: &[f64], low: &[f64], close: &[f64]) -> Vec<f64> with cdl_3outside_with_output init zero;
}
pub fn cdl_3outside_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_3outside_with_output: out length must equal input length".into(),
));
}
check_ohlc(open, high, low, close, "cdl_3outside")?;
let n = open.len();
let lookback = 3; if n <= lookback {
return Ok(());
}
let mut i = lookback;
while i < n {
if (candle_color(open[i - 1], close[i - 1]) == 1.0
&& candle_color(open[i - 2], close[i - 2]) == -1.0 && close[i - 1] > open[i - 2]
&& open[i - 1] < close[i - 2]
&& close[i] > close[i - 1]) || (candle_color(open[i - 1], close[i - 1]) == -1.0
&& candle_color(open[i - 2], close[i - 2]) == 1.0 && open[i - 1] > close[i - 2]
&& close[i - 1] < open[i - 2]
&& close[i] < close[i - 1])
{
out[i] = candle_color(open[i - 1], close[i - 1]) * 100.0;
} else {
out[i] = 0.0;
}
i += 1;
}
Ok(())
}
indicator! {
fn cdl_3starsinsouth(open: &[f64], high: &[f64], low: &[f64], close: &[f64]) -> Vec<f64> with cdl_3starsinsouth_with_output init zero;
}
pub fn cdl_3starsinsouth_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_3starsinsouth_with_output: out length must equal input length".into(),
));
}
check_ohlc(open, high, low, close, "cdl_3starsinsouth")?;
let n = open.len();
let lookback = [
SHADOW_VERY_SHORT.avg_period.max(SHADOW_LONG.avg_period),
BODY_LONG.avg_period.max(BODY_SHORT.avg_period),
]
.iter()
.max()
.copied()
.unwrap()
+ 2; if n <= lookback {
return Ok(());
}
let mut sum_avg_body_long = {
let mut s = lookback - 2 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 2) {
acc += real_body(open[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_body_long = lookback - 2 - 10;
let mut sum_avg_shadow_long = {
let mut s = lookback - 2 - 0;
let mut acc = 0.0_f64;
while s < (lookback - 2) {
acc += real_body(open[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_shadow_long = lookback - 2 - 0;
let mut sum_avg_vs_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_vs_1 = lookback - 1 - 10;
let mut sum_avg_vs_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_vs_0 = lookback - 0 - 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 - 2], close[i - 2]);
let val_avg_body_long = sum_avg_body_long / 10 as f64 * 1.0;
let cur_avg_shadow_long = real_body(open[i - 2], close[i - 2]);
let val_avg_shadow_long = cur_avg_shadow_long * 1.0;
let cur_avg_vs_1 = high_low_range(high[i - 1], low[i - 1]);
let val_avg_vs_1 = sum_avg_vs_1 / 10 as f64 * 0.1;
let cur_avg_vs_0 = high_low_range(high[i], low[i]);
let val_avg_vs_0 = sum_avg_vs_0 / 10 as f64 * 0.1;
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 - 2], close[i - 2]) == -1.0 && candle_color(open[i - 1], close[i - 1]) == -1.0 && candle_color(open[i], close[i]) == -1.0 && real_body(open[i - 2], close[i - 2]) > val_avg_body_long
&& lower_shadow(open[i - 2], low[i - 2], close[i - 2])
> val_avg_shadow_long
&& real_body(open[i - 1], close[i - 1]) < real_body(open[i - 2], close[i - 2]) && open[i - 1] > close[i - 2]
&& open[i - 1] <= high[i - 2] && low[i - 1] < close[i - 2] && low[i - 1] >= low[i - 2] && lower_shadow(open[i - 1], low[i - 1], close[i - 1])
> val_avg_vs_1
&& cur_avg_body_short < val_avg_body_short
&& lower_shadow(open[i], low[i], close[i]) < val_avg_vs_0
&& upper_shadow(open[i], high[i], close[i]) < val_avg_vs_0
&& low[i] > low[i - 1]
&& high[i] < high[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_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_vs_1 += cur_avg_vs_1 - high_low_range(high[trail_avg_vs_1], low[trail_avg_vs_1]);
trail_avg_vs_1 += 1;
sum_avg_vs_0 += cur_avg_vs_0 - high_low_range(high[trail_avg_vs_0], low[trail_avg_vs_0]);
trail_avg_vs_0 += 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_3whitesoldiers(open: &[f64], high: &[f64], low: &[f64], close: &[f64]) -> Vec<f64> with cdl_3whitesoldiers_with_output init zero;
}
pub fn cdl_3whitesoldiers_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_3whitesoldiers_with_output: out length must equal input length".into(),
));
}
check_ohlc(open, high, low, close, "cdl_3whitesoldiers")?;
let n = open.len();
let lookback = [
SHADOW_VERY_SHORT.avg_period.max(BODY_SHORT.avg_period),
FAR.avg_period.max(NEAR.avg_period),
]
.iter()
.max()
.copied()
.unwrap()
+ 2; if n <= lookback {
return Ok(());
}
let mut sum_avg_vs_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_vs_2 = lookback - 2 - 10;
let mut sum_avg_vs_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_vs_1 = lookback - 1 - 10;
let mut sum_avg_vs_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_vs_0 = lookback - 0 - 10;
let mut sum_avg_near_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_near_2 = lookback - 2 - 5;
let mut sum_avg_near_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_near_1 = lookback - 1 - 5;
let mut sum_avg_far_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_far_2 = lookback - 2 - 5;
let mut sum_avg_far_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_far_1 = lookback - 1 - 5;
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_vs_2 = high_low_range(high[i - 2], low[i - 2]);
let val_avg_vs_2 = sum_avg_vs_2 / 10 as f64 * 0.1;
let cur_avg_vs_1 = high_low_range(high[i - 1], low[i - 1]);
let val_avg_vs_1 = sum_avg_vs_1 / 10 as f64 * 0.1;
let cur_avg_vs_0 = high_low_range(high[i], low[i]);
let val_avg_vs_0 = sum_avg_vs_0 / 10 as f64 * 0.1;
let cur_avg_near_2 = high_low_range(high[i - 2], low[i - 2]);
let val_avg_near_2 = sum_avg_near_2 / 5 as f64 * 0.2;
let cur_avg_near_1 = high_low_range(high[i - 1], low[i - 1]);
let val_avg_near_1 = sum_avg_near_1 / 5 as f64 * 0.2;
let cur_avg_far_2 = high_low_range(high[i - 2], low[i - 2]);
let val_avg_far_2 = sum_avg_far_2 / 5 as f64 * 0.6;
let cur_avg_far_1 = high_low_range(high[i - 1], low[i - 1]);
let val_avg_far_1 = sum_avg_far_1 / 5 as f64 * 0.6;
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 - 2], close[i - 2]) == 1.0 && upper_shadow(open[i - 2], high[i - 2], close[i - 2])
< val_avg_vs_2 && candle_color(open[i - 1], close[i - 1]) == 1.0 && upper_shadow(open[i - 1], high[i - 1], close[i - 1])
< val_avg_vs_1
&& candle_color(open[i], close[i]) == 1.0 && upper_shadow(open[i], high[i], close[i]) < val_avg_vs_0
&& close[i] > close[i - 1]
&& close[i - 1] > close[i - 2] && open[i - 1] > open[i - 2] && open[i - 1] <= close[i - 2] + val_avg_near_2
&& open[i] > open[i - 1] && open[i] <= close[i - 1] + val_avg_near_1
&& real_body(open[i - 1], close[i - 1])
> real_body(open[i - 2], close[i - 2]) - val_avg_far_2 && cur_avg_body_short
> real_body(open[i - 1], close[i - 1]) - val_avg_far_1 && cur_avg_body_short > val_avg_body_short
{
100.0
} else {
0.0
};
sum_avg_vs_2 += cur_avg_vs_2 - high_low_range(high[trail_avg_vs_2], low[trail_avg_vs_2]);
trail_avg_vs_2 += 1;
sum_avg_vs_1 += cur_avg_vs_1 - high_low_range(high[trail_avg_vs_1], low[trail_avg_vs_1]);
trail_avg_vs_1 += 1;
sum_avg_vs_0 += cur_avg_vs_0 - high_low_range(high[trail_avg_vs_0], low[trail_avg_vs_0]);
trail_avg_vs_0 += 1;
sum_avg_near_2 +=
cur_avg_near_2 - high_low_range(high[trail_avg_near_2], low[trail_avg_near_2]);
trail_avg_near_2 += 1;
sum_avg_near_1 +=
cur_avg_near_1 - high_low_range(high[trail_avg_near_1], low[trail_avg_near_1]);
trail_avg_near_1 += 1;
sum_avg_far_2 +=
cur_avg_far_2 - high_low_range(high[trail_avg_far_2], low[trail_avg_far_2]);
trail_avg_far_2 += 1;
sum_avg_far_1 +=
cur_avg_far_1 - high_low_range(high[trail_avg_far_1], low[trail_avg_far_1]);
trail_avg_far_1 += 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_abandonedbaby(open: &[f64], high: &[f64], low: &[f64], close: &[f64]) -> Vec<f64> with cdl_abandonedbaby_with_output init zero;
}
pub fn cdl_abandonedbaby_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_abandonedbaby_with_output: out length must equal input length".into(),
));
}
check_ohlc(open, high, low, close, "cdl_abandonedbaby")?;
let n = open.len();
let lookback = [
BODY_DOJI.avg_period.max(BODY_LONG.avg_period),
BODY_SHORT.avg_period,
]
.iter()
.max()
.copied()
.unwrap()
+ 2; let penetration: f64 = 0.3; if n <= lookback {
return Ok(());
}
let mut sum_avg_body_long = {
let mut s = lookback - 2 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 2) {
acc += real_body(open[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_body_long = lookback - 2 - 10;
let mut sum_avg_body_doji = {
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_body_doji = 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 - 2], close[i - 2]);
let val_avg_body_long = sum_avg_body_long / 10 as f64 * 1.0;
let cur_avg_body_doji = high_low_range(high[i - 1], low[i - 1]);
let val_avg_body_doji = sum_avg_body_doji / 10 as f64 * 0.1;
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 real_body(open[i - 2], close[i - 2]) > val_avg_body_long && real_body(open[i - 1], close[i - 1]) <= val_avg_body_doji && cur_avg_body_short > val_avg_body_short && ((candle_color(open[i - 2], close[i - 2]) == 1.0 && candle_color(open[i], close[i]) == -1.0 && close[i] < close[i - 2] - real_body(open[i - 2], close[i - 2]) * penetration
&& candle_gap_up(low[i - 1], high[i - 2]) && candle_gap_down(high[i], low[i - 1])) || (candle_color(open[i - 2], close[i - 2]) == -1.0 && candle_color(open[i], close[i]) == 1.0 && close[i] > close[i - 2] + real_body(open[i - 2], close[i - 2]) * penetration
&& candle_gap_down(high[i - 1], low[i - 2]) && candle_gap_up(low[i], high[i - 1])))
{
candle_color(open[i], close[i]) * 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_doji +=
cur_avg_body_doji - high_low_range(high[trail_avg_body_doji], low[trail_avg_body_doji]);
trail_avg_body_doji += 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_advanceblock(open: &[f64], high: &[f64], low: &[f64], close: &[f64]) -> Vec<f64> with cdl_advanceblock_with_output init zero;
}
pub fn cdl_advanceblock_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_advanceblock_with_output: out length must equal input length".into(),
));
}
check_ohlc(open, high, low, close, "cdl_advanceblock")?;
let n = open.len();
let lookback = [
SHADOW_LONG.avg_period.max(SHADOW_SHORT.avg_period),
FAR.avg_period.max(NEAR.avg_period),
BODY_LONG.avg_period,
]
.iter()
.max()
.copied()
.unwrap()
+ 2; if n <= lookback {
return Ok(());
}
let mut sum_avg_shadow_short_2 = {
let mut s = lookback - 2 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 2) {
acc += upper_shadow(open[s], high[s], close[s])
+ lower_shadow(open[s], low[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_shadow_short_2 = lookback - 2 - 10;
let mut sum_avg_shadow_short_1 = {
let mut s = lookback - 1 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 1) {
acc += upper_shadow(open[s], high[s], close[s])
+ lower_shadow(open[s], low[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_shadow_short_1 = lookback - 1 - 10;
let mut sum_avg_shadow_short_0 = {
let mut s = lookback - 0 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 0) {
acc += upper_shadow(open[s], high[s], close[s])
+ lower_shadow(open[s], low[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_shadow_short_0 = lookback - 0 - 10;
let mut sum_avg_shadow_long_1 = {
let mut s = lookback - 1 - 0;
let mut acc = 0.0_f64;
while s < (lookback - 1) {
acc += real_body(open[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_shadow_long_1 = lookback - 1 - 0;
let mut sum_avg_shadow_long_0 = {
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_0 = lookback - 0 - 0;
let mut sum_avg_near_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_near_2 = lookback - 2 - 5;
let mut sum_avg_near_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_near_1 = lookback - 1 - 5;
let mut sum_avg_far_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_far_2 = lookback - 2 - 5;
let mut sum_avg_far_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_far_1 = lookback - 1 - 5;
let mut sum_avg_body_long = {
let mut s = lookback - 2 - 10;
let mut acc = 0.0_f64;
while s < (lookback - 2) {
acc += real_body(open[s], close[s]);
s += 1;
}
acc
};
let mut trail_avg_body_long = lookback - 2 - 10;
let mut i = lookback;
while i < n {
let cur_avg_shadow_short_2 = upper_shadow(open[i - 2], high[i - 2], close[i - 2])
+ lower_shadow(open[i - 2], low[i - 2], close[i - 2]);
let val_avg_shadow_short_2 = sum_avg_shadow_short_2 / 10 as f64 * 1.0 / 2.0;
let cur_avg_shadow_short_1 = upper_shadow(open[i - 1], high[i - 1], close[i - 1])
+ lower_shadow(open[i - 1], low[i - 1], close[i - 1]);
let val_avg_shadow_short_1 = sum_avg_shadow_short_1 / 10 as f64 * 1.0 / 2.0;
let cur_avg_shadow_short_0 =
upper_shadow(open[i], high[i], close[i]) + lower_shadow(open[i], low[i], close[i]);
let val_avg_shadow_short_0 = sum_avg_shadow_short_0 / 10 as f64 * 1.0 / 2.0;
let cur_avg_shadow_long_1 = real_body(open[i - 1], close[i - 1]);
let _val_avg_shadow_long_1 = cur_avg_shadow_long_1 * 1.0;
let cur_avg_shadow_long_0 = real_body(open[i], close[i]);
let val_avg_shadow_long_0 = cur_avg_shadow_long_0 * 1.0;
let cur_avg_near_2 = high_low_range(high[i - 2], low[i - 2]);
let val_avg_near_2 = sum_avg_near_2 / 5 as f64 * 0.2;
let cur_avg_near_1 = high_low_range(high[i - 1], low[i - 1]);
let val_avg_near_1 = sum_avg_near_1 / 5 as f64 * 0.2;
let cur_avg_far_2 = high_low_range(high[i - 2], low[i - 2]);
let val_avg_far_2 = sum_avg_far_2 / 5 as f64 * 0.6;
let cur_avg_far_1 = high_low_range(high[i - 1], low[i - 1]);
let val_avg_far_1 = sum_avg_far_1 / 5 as f64 * 0.6;
let cur_avg_body_long = real_body(open[i - 2], close[i - 2]);
let val_avg_body_long = sum_avg_body_long / 10 as f64 * 1.0;
out[i] = if candle_color(open[i - 2], close[i - 2]) == 1.0 && candle_color(open[i - 1], close[i - 1]) == 1.0 && candle_color(open[i], close[i]) == 1.0 && close[i] > close[i - 1]
&& close[i - 1] > close[i - 2] && open[i - 1] > open[i - 2] && open[i - 1] <= close[i - 2] + val_avg_near_2
&& open[i] > open[i - 1] && open[i] <= close[i - 1] + val_avg_near_1
&& real_body(open[i - 2], close[i - 2]) > val_avg_body_long && upper_shadow(open[i - 2], high[i - 2], close[i - 2])
< val_avg_shadow_short_2 && ((real_body(open[i - 1], close[i - 1])
< real_body(open[i - 2], close[i - 2]) - val_avg_far_2
&& cur_avg_shadow_long_0
< real_body(open[i - 1], close[i - 1])
+ val_avg_near_1) || (cur_avg_shadow_long_0
< real_body(open[i - 1], close[i - 1])
- val_avg_far_1) || (cur_avg_shadow_long_0 < real_body(open[i - 1], close[i - 1])
&& real_body(open[i - 1], close[i - 1]) < real_body(open[i - 2], close[i - 2])
&& (upper_shadow(open[i], high[i], close[i])
> val_avg_shadow_short_0
|| upper_shadow(open[i - 1], high[i - 1], close[i - 1])
> val_avg_shadow_short_1))
|| (cur_avg_shadow_long_0 < real_body(open[i - 1], close[i - 1])
&& upper_shadow(open[i], high[i], close[i])
> val_avg_shadow_long_0))
{
-100.0
} else {
0.0
};
sum_avg_shadow_short_2 += cur_avg_shadow_short_2
- (upper_shadow(
open[trail_avg_shadow_short_2],
high[trail_avg_shadow_short_2],
close[trail_avg_shadow_short_2],
) + lower_shadow(
open[trail_avg_shadow_short_2],
low[trail_avg_shadow_short_2],
close[trail_avg_shadow_short_2],
));
trail_avg_shadow_short_2 += 1;
sum_avg_shadow_short_1 += cur_avg_shadow_short_1
- (upper_shadow(
open[trail_avg_shadow_short_1],
high[trail_avg_shadow_short_1],
close[trail_avg_shadow_short_1],
) + lower_shadow(
open[trail_avg_shadow_short_1],
low[trail_avg_shadow_short_1],
close[trail_avg_shadow_short_1],
));
trail_avg_shadow_short_1 += 1;
sum_avg_shadow_short_0 += cur_avg_shadow_short_0
- (upper_shadow(
open[trail_avg_shadow_short_0],
high[trail_avg_shadow_short_0],
close[trail_avg_shadow_short_0],
) + lower_shadow(
open[trail_avg_shadow_short_0],
low[trail_avg_shadow_short_0],
close[trail_avg_shadow_short_0],
));
trail_avg_shadow_short_0 += 1;
sum_avg_shadow_long_1 += cur_avg_shadow_long_1
- real_body(
open[trail_avg_shadow_long_1],
close[trail_avg_shadow_long_1],
);
trail_avg_shadow_long_1 += 1;
sum_avg_shadow_long_0 += cur_avg_shadow_long_0
- real_body(
open[trail_avg_shadow_long_0],
close[trail_avg_shadow_long_0],
);
trail_avg_shadow_long_0 += 1;
sum_avg_near_2 +=
cur_avg_near_2 - high_low_range(high[trail_avg_near_2], low[trail_avg_near_2]);
trail_avg_near_2 += 1;
sum_avg_near_1 +=
cur_avg_near_1 - high_low_range(high[trail_avg_near_1], low[trail_avg_near_1]);
trail_avg_near_1 += 1;
sum_avg_far_2 +=
cur_avg_far_2 - high_low_range(high[trail_avg_far_2], low[trail_avg_far_2]);
trail_avg_far_2 += 1;
sum_avg_far_1 +=
cur_avg_far_1 - high_low_range(high[trail_avg_far_1], low[trail_avg_far_1]);
trail_avg_far_1 += 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(())
}