use crate::candle_indicators::{
candle_patterns::CandlePattern,
pattern_test::EmaState,
registry::CandleBits,
types::{CandleInfo, ForecastType},
};
use tulip_rs_macros::pattern_template;
use super::{FIRST, SECOND};
pub fn info() -> CandleInfo {
CandleInfo {
name: "bullishharami",
full_name: "Bullish Harami",
forecast: ForecastType::BullishReversal,
extended_pattern: Some(CandlePattern::ThreeInsideUp),
bars: 2,
japanese_name: "Harami",
}
}
#[pattern_template(
name = "BullishHarami",
forecast = "BullishReversal",
prev_bar(trend = "DOWN"),
bar(
colour = "RED",
fill = "FILL",
line_height = "LONG",
candle_type = "Basic(BlackCandle | LongBlackCandle) Marubozu(OpeningBlackMarubozu | ClosingBlackMarubozu | BlackMarubozu)"
),
bar(
colour = "GREEN",
fill = "HALLOW",
candle_type = "!Doji(FourPriceDoji)",
inside_prev = "BODY"
)
)]
pub fn calc(
inputs: (&[f64], &[f64], &[f64], &[f64]),
_state: &EmaState,
bars: &[CandleBits],
) -> bool {
let (_, _, low, _) = inputs;
if low[FIRST] == low[SECOND] {
return false;
}
let second_mandatory = bars[SECOND].mandatory;
let is_doji = (second_mandatory & CandleBits::DOJI) != 0
|| (second_mandatory & CandleBits::LONG_LEGGED_DOJI) != 0
|| (second_mandatory & CandleBits::DRAGONFLY_DOJI) != 0
|| (second_mandatory & CandleBits::GRAVESTONE_DOJI) != 0;
if is_doji {
let high_in_prev_body =
bars[SECOND].lazy_value & (1u16 << CandleBits::HIGH_IN_PREV_BODY_BIT) != 0;
let low_in_prev_body =
bars[SECOND].lazy_value & (1u16 << CandleBits::LOW_IN_PREV_BODY_BIT) != 0;
if high_in_prev_body && low_in_prev_body {
return false;
}
}
true
}