use motosan_ta_stream::engine::TaEngine;
use motosan_ta_stream::indicator::*;
use motosan_ta_stream::snapshot::{IndicatorValue, TaSnapshot};
use motosan_ta_stream::types::{Bar, Interval};
use crate::technical_analysis::TechnicalIndicators;
use crate::Candle;
pub fn build_default_engine(symbol: &str) -> TaEngine {
TaEngine::new(symbol, Interval::H1)
.add("SMA_20", Sma::new(MaConfig { period: 20 }))
.add("SMA_50", Sma::new(MaConfig { period: 50 }))
.add("EMA_12", Ema::new(MaConfig { period: 12 }))
.add("EMA_20", Ema::new(MaConfig { period: 20 }))
.add("EMA_26", Ema::new(MaConfig { period: 26 }))
.add("EMA_50", Ema::new(MaConfig { period: 50 }))
.add("RSI_14", Rsi::new(RsiConfig { period: 14 }))
.add(
"MACD",
Macd::new(MacdConfig {
fast: 12,
slow: 26,
signal: 9,
}),
)
.add("CCI_20", Cci::new(CciConfig { period: 20 }))
.add(
"WILLIAMS_R_14",
WilliamsR::new(WilliamsRConfig { period: 14 }),
)
.add("ROC_12", Roc::new(RocConfig { period: 12 }))
.add("MFI_14", Mfi::new(MfiConfig { period: 14 }))
.add("ATR_14", Atr::new(AtrConfig { period: 14 }))
.add(
"BB_20",
Bbands::new(BbandsConfig {
period: 20,
std_dev: 2.0,
}),
)
.add("ADX_14", Adx::new(AdxConfig { period: 14 }))
.add(
"KC_20",
Keltner::new(KeltnerConfig {
period: 20,
multiplier: 1.5,
}),
)
.add(
"SUPERTREND",
Supertrend::new(SupertrendConfig {
period: 10,
multiplier: 3.0,
}),
)
.add("DONCHIAN_20", Donchian::new(DonchianConfig { period: 20 }))
.add("DONCHIAN_10", Donchian::new(DonchianConfig { period: 10 }))
.add("VWAP", Vwap::new(VwapConfig { auto_reset: false }))
}
pub fn calculate_snapshot(candles: &[Candle], symbol: &str) -> Option<TaSnapshot> {
let mut engine = build_default_engine(symbol);
let mut last_snapshot = None;
for candle in candles {
let bar = Bar {
time: candle.time as i64 * 1000, open: candle.open,
high: candle.high,
low: candle.low,
close: candle.close,
volume: candle.volume,
is_closed: true,
};
if let Some(snapshot) = engine.feed(&bar) {
last_snapshot = Some(snapshot);
}
}
last_snapshot
}
pub fn get_snapshot_value(snapshot: &TaSnapshot, key: &str) -> Option<f64> {
match snapshot.results.get(key)? {
IndicatorValue::Single(v) => Some(*v),
IndicatorValue::Multi(map) => map
.get("value")
.or_else(|| map.get("line"))
.or_else(|| map.get("adx"))
.or_else(|| map.get("k"))
.copied(),
}
}
pub fn get_snapshot_sub_value(snapshot: &TaSnapshot, key: &str, sub_key: &str) -> Option<f64> {
match snapshot.results.get(key)? {
IndicatorValue::Multi(map) => map.get(sub_key).copied(),
IndicatorValue::Single(v) => {
if sub_key == "value" {
Some(*v)
} else {
None
}
}
}
}
pub fn snapshot_to_indicators(snapshot: &TaSnapshot) -> TechnicalIndicators {
TechnicalIndicators {
sma_20: get_snapshot_value(snapshot, "SMA_20"),
sma_50: get_snapshot_value(snapshot, "SMA_50"),
ema_12: get_snapshot_value(snapshot, "EMA_12"),
ema_20: get_snapshot_value(snapshot, "EMA_20"),
ema_26: get_snapshot_value(snapshot, "EMA_26"),
ema_50: get_snapshot_value(snapshot, "EMA_50"),
rsi_14: get_snapshot_value(snapshot, "RSI_14"),
macd_line: get_snapshot_sub_value(snapshot, "MACD", "macd"),
macd_signal: get_snapshot_sub_value(snapshot, "MACD", "signal"),
macd_histogram: get_snapshot_sub_value(snapshot, "MACD", "histogram"),
bb_upper: get_snapshot_sub_value(snapshot, "BB_20", "upper"),
bb_middle: get_snapshot_sub_value(snapshot, "BB_20", "middle"),
bb_lower: get_snapshot_sub_value(snapshot, "BB_20", "lower"),
atr_14: get_snapshot_value(snapshot, "ATR_14"),
adx_14: get_snapshot_sub_value(snapshot, "ADX_14", "adx"),
stoch_k: None, stoch_d: None,
cci_20: get_snapshot_value(snapshot, "CCI_20"),
williams_r_14: get_snapshot_value(snapshot, "WILLIAMS_R_14"),
obv: None, mfi_14: get_snapshot_value(snapshot, "MFI_14"),
roc_12: get_snapshot_value(snapshot, "ROC_12"),
donchian_upper_20: get_snapshot_sub_value(snapshot, "DONCHIAN_20", "upper"),
donchian_lower_20: get_snapshot_sub_value(snapshot, "DONCHIAN_20", "lower"),
donchian_upper_10: get_snapshot_sub_value(snapshot, "DONCHIAN_10", "upper"),
donchian_lower_10: get_snapshot_sub_value(snapshot, "DONCHIAN_10", "lower"),
close_zscore_20: None, volume_zscore_20: None,
hv_20: None, hv_60: None,
kc_upper_20: get_snapshot_sub_value(snapshot, "KC_20", "upper"),
kc_lower_20: get_snapshot_sub_value(snapshot, "KC_20", "lower"),
supertrend_value: get_snapshot_sub_value(snapshot, "SUPERTREND", "value"),
supertrend_direction: get_snapshot_sub_value(snapshot, "SUPERTREND", "direction"),
vwap: get_snapshot_value(snapshot, "VWAP"),
plus_di_14: get_snapshot_sub_value(snapshot, "ADX_14", "di_plus"),
minus_di_14: get_snapshot_sub_value(snapshot, "ADX_14", "di_minus"),
}
}