use super::container::{指标值, 指标容器};
use super::{布林带, 平滑异同移动平均线, 相对强弱指数, 随机指标};
use crate::config::缠论配置;
use crate::kline::bar::K线;
use std::sync::Arc;
pub struct 指标计算器;
impl 指标计算器 {
pub fn 计算并挂载(当前K线: &K线, 现有序列: &[Arc<K线>], 配置: &缠论配置) {
let prev_guard = 现有序列.last().map(|k| k.指标.read().unwrap());
let prev = prev_guard.as_deref();
if 配置.计算指标 {
Self::_计算MACD组(当前K线, prev, 配置);
Self::_计算RSI组(当前K线, prev, 配置);
Self::_计算KDJ组(当前K线, prev, 配置);
Self::_计算BOLL组(当前K线, prev, 配置);
}
Self::_更新均线(当前K线, 现有序列, 配置);
}
fn _计算MACD组(当前K线: &K线, prev: Option<&指标容器>, 配置: &缠论配置) {
let 计算方式 = &配置.指标计算方式;
for (i, (key, 快, 慢, 信号)) in 配置._解析MACD参数列表().into_iter().enumerate()
{
let val = if let Some(prev_val) = prev.and_then(|p| p.获取(&key)) {
if let 指标值::MACD(prev_macd) = prev_val {
指标值::MACD(平滑异同移动平均线::增量计算(
prev_macd,
super::K线取值(
当前K线.开盘价,
当前K线.高,
当前K线.低,
当前K线.收盘价,
计算方式,
),
当前K线.时间戳,
))
} else {
continue;
}
} else {
指标值::MACD(平滑异同移动平均线::首次计算(
super::K线取值(
当前K线.开盘价,
当前K线.高,
当前K线.低,
当前K线.收盘价,
计算方式,
),
当前K线.时间戳,
快,
慢,
信号,
))
};
当前K线.指标.write().unwrap().设置(&key, val.clone());
if i == 0 {
当前K线.指标.write().unwrap().设置("macd", val);
}
}
}
fn _计算RSI组(当前K线: &K线, prev: Option<&指标容器>, 配置: &缠论配置) {
let 计算方式 = &配置.指标计算方式;
for (i, (key, 周期)) in 配置._解析RSI周期列表().into_iter().enumerate() {
let val = if let Some(prev_val) = prev.and_then(|p| p.获取(&key)) {
if let 指标值::RSI(prev_rsi) = prev_val {
指标值::RSI(相对强弱指数::增量计算(
prev_rsi,
super::K线取值(
当前K线.开盘价,
当前K线.高,
当前K线.低,
当前K线.收盘价,
计算方式,
),
当前K线.时间戳,
))
} else {
continue;
}
} else {
指标值::RSI(相对强弱指数::首次计算(
super::K线取值(
当前K线.开盘价,
当前K线.高,
当前K线.低,
当前K线.收盘价,
计算方式,
),
当前K线.时间戳,
周期,
配置.相对强弱指数_超买阈值,
配置.相对强弱指数_超卖阈值,
Some(配置.相对强弱指数_移动平均线周期),
))
};
当前K线.指标.write().unwrap().设置(&key, val.clone());
if i == 0 {
当前K线.指标.write().unwrap().设置("rsi", val);
}
}
}
fn _计算KDJ组(当前K线: &K线, prev: Option<&指标容器>, 配置: &缠论配置) {
for (i, (key, rsv, k平滑, d平滑)) in 配置._解析KDJ参数列表().into_iter().enumerate()
{
let val = if let Some(prev_val) = prev.and_then(|p| p.获取(&key)) {
if let 指标值::KDJ(prev_kdj) = prev_val {
指标值::KDJ(随机指标::增量计算(
prev_kdj,
当前K线.高,
当前K线.低,
当前K线.收盘价,
当前K线.时间戳,
))
} else {
continue;
}
} else {
指标值::KDJ(随机指标::首次计算(
当前K线.高,
当前K线.低,
当前K线.收盘价,
当前K线.时间戳,
rsv,
k平滑,
d平滑,
配置.随机指标_超买阈值,
配置.随机指标_超卖阈值,
))
};
当前K线.指标.write().unwrap().设置(&key, val.clone());
if i == 0 {
当前K线.指标.write().unwrap().设置("kdj", val);
}
}
}
fn _计算BOLL组(当前K线: &K线, prev: Option<&指标容器>, 配置: &缠论配置) {
let 计算方式 = &配置.指标计算方式;
for (i, (key, 周期, 标准差倍数)) in 配置._解析BOLL参数列表().into_iter().enumerate()
{
let val = if let Some(prev_val) = prev.and_then(|p| p.获取(&key)) {
if let 指标值::BOLL(prev_boll) = prev_val {
指标值::BOLL(布林带::增量计算(
prev_boll,
当前K线.时间戳,
super::K线取值(
当前K线.开盘价,
当前K线.高,
当前K线.低,
当前K线.收盘价,
计算方式,
),
))
} else {
continue;
}
} else {
指标值::BOLL(布林带::首次计算(
当前K线.时间戳,
super::K线取值(
当前K线.开盘价,
当前K线.高,
当前K线.低,
当前K线.收盘价,
计算方式,
),
周期 as usize,
标准差倍数,
))
};
当前K线.指标.write().unwrap().设置(&key, val.clone());
if i == 0 {
当前K线.指标.write().unwrap().设置("boll", val);
}
}
}
fn _更新均线(当前K线: &K线, 现有序列: &[Arc<K线>], 配置: &缠论配置) {
if 配置.均线_类型列表.is_empty() || 配置.均线_周期列表.is_empty() {
return;
}
let 计算方式 = &配置.指标计算方式;
let 当前价 = super::K线取值(
当前K线.开盘价,
当前K线.高,
当前K线.低,
当前K线.收盘价,
计算方式,
);
for ma_type in &配置.均线_类型列表 {
for period in &配置.均线_周期列表 {
let key = format!("{}_{}", ma_type, period);
let 值 = match ma_type.as_str() {
"SMA" => Self::_增量SMA(现有序列, 当前价, *period, 计算方式, &key),
"EMA" => Self::_增量EMA(现有序列, 当前价, *period, 计算方式, &key),
_ => continue,
};
if let Some(均线_map) = 当前K线.指标.write().unwrap().均线_mut() {
均线_map.insert(key, 值);
}
}
}
}
fn _增量SMA(
现有序列: &[Arc<K线>],
当前价: f64,
period: i64,
计算方式: &str,
prev_key: &str,
) -> f64 {
let existing_len = 现有序列.len();
let p = period as usize;
let total_len = existing_len + 1;
if total_len <= p {
let mut sum: f64 = 现有序列[existing_len.saturating_sub(p.saturating_sub(1))..]
.iter()
.map(|k| super::K线取值(k.开盘价, k.高, k.低, k.收盘价, 计算方式))
.sum();
sum += 当前价;
return sum / (total_len as f64).max(1.0);
}
if let Some(prev) = 现有序列.last().and_then(|k| {
let guard = k.指标.read().unwrap();
guard.均线().and_then(|m| m.get(prev_key)).copied()
}) {
let oldest = super::K线取值(
现有序列[existing_len - p].开盘价,
现有序列[existing_len - p].高,
现有序列[existing_len - p].低,
现有序列[existing_len - p].收盘价,
计算方式,
);
return prev + (当前价 - oldest) / period as f64;
}
let mut sum: f64 = 现有序列[existing_len.saturating_sub(p.saturating_sub(1))..]
.iter()
.map(|k| super::K线取值(k.开盘价, k.高, k.低, k.收盘价, 计算方式))
.sum();
sum += 当前价;
sum / (total_len as f64).min(p as f64)
}
fn _增量EMA(
现有序列: &[Arc<K线>],
当前价: f64,
period: i64,
_计算方式: &str,
prev_key: &str,
) -> f64 {
let 前值 = 现有序列.last().and_then(|k| {
let guard = k.指标.read().unwrap();
guard.均线().and_then(|m| m.get(prev_key)).copied()
});
match 前值 {
None => 当前价,
Some(prev) => {
let k = 2.0 / (period as f64 + 1.0);
当前价 * k + prev * (1.0 - k)
}
}
}
}