Files
2026-07-09 05:08:16 +08:00

8.4 KiB
Raw Permalink Blame History

当然可以,RaptorBT 是开源的 Rust 项目,结构很清晰。让我先看看现有指标的实现模式: The user is asking about modifying the RaptorBT source code to add custom indicators. Let me look at the existing indicator implementation to understand the pattern, then explain how to add a new indicator.

现在看看 lib.rs 里的模块注册:

好,现在我对整个代码结构非常清楚了。下面给你完整的说明:


添加自定义指标的完整流程

RaptorBT 的指标架构非常清晰,添加一个新指标需要改 3 个文件,我以添加 CCICommodity Channel Index 为例演示:

第 1 步:在 Rust 里实现指标逻辑

momentum.rs 中添加函数(或新建文件都行,这里选 momentum.rs 因为 CCI 属于动量类):

/// Commodity Channel Index (CCI).
///
/// # Arguments
/// * `high` - High prices
/// * `low` - Low prices
/// * `close` - Close prices
/// * `period` - Lookback period (default: 20)
///
/// # Returns
/// Vector of CCI values (NaN for warmup period)
pub fn cci(high: &[f64], low: &[f64], close: &[f64], period: usize) -> Result<Vec<f64>> {
    if period == 0 {
        return Err(RaptorError::invalid_parameter("CCI period must be > 0"));
    }
    let n = close.len();
    if n != high.len() || n != low.len() {
        return Err(RaptorError::length_mismatch(n, high.len()));
    }

    let mut result = vec![f64::NAN; n];
    if period >= n {
        return Ok(result);
    }

    // Typical Price
    let tp: Vec<f64> = (0..n).map(|i| (high[i] + low[i] + close[i]) / 3.0).collect();

    // SMA of Typical Price + Mean Deviation
    for i in (period - 1)..n {
        let start = i + 1 - period;
        let tp_sma: f64 = tp[start..=i].iter().sum::<f64>() / period as f64;
        let mean_dev: f64 = tp[start..=i].iter().map(|x| (x - tp_sma).abs()).sum::<f64>() / period as f64;

        if mean_dev > f64::EPSILON {
            result[i] = (tp[i] - tp_sma) / (0.015 * mean_dev);
        } else {
            result[i] = 0.0;
        }
    }

    Ok(result)
}

第 2 步:在 mod.rs 导出

mod.rspub use momentum::... 行加上 cci

pub use momentum::{cci, macd, rsi, stochastic, MacdResult, StochasticResult};

第 3 步:在 bindings.rs 添加 Python 绑定

bindings.rs 的指标函数区域添加:

/// Commodity Channel Index.
#[pyfunction]
pub fn cci<'py>(
    py: Python<'py>,
    high: PyReadonlyArray1<f64>,
    low: PyReadonlyArray1<f64>,
    close: PyReadonlyArray1<f64>,
    period: usize,
) -> PyResult<&'py PyArray1<f64>> {
    let h = numpy_to_vec_f64(high);
    let l = numpy_to_vec_f64(low);
    let c = numpy_to_vec_f64(close);
    let result = indicators::momentum::cci(&h, &l, &c, period)
        .map_err(|e| pyo3::exceptions::PyValueError::new_err(e.to_string()))?;
    Ok(vec_to_numpy_f64(py, result))
}

第 4 步:在 lib.rs 注册

lib.rs 的指标注册区添加:

m.add_function(wrap_pyfunction!(python::bindings::cci, m)?)?;

第 5 步:编译 & 使用

maturin develop --release

然后 Python 里就能用了:

cci = raptorbt.cci(high, low, close, period=20)

总结:3 文件修改清单

文件 改什么 位置
src/indicators/momentum.rs(或新文件) 实现 pub fn cci(...) -> Result<Vec<f64>> 和 rsi/macd 同级
src/indicators/mod.rs pub use momentum::cci 导出行
src/python/bindings.rs 添加 #[pyfunction] pub fn cci<...> 指标函数区
src/lib.rs m.add_function(wrap_pyfunction!(...::cci, m)?) 指标注册区

规律:所有现有指标(sma/ema/rsi/macd/atr/bollinger_bands/adx/vwap/supertrend/stochastic/rolling_min/rolling_max)都是这个模式。你照着抄一个最简单的(比如 sma),改成自己的计算逻辑就行。


添加自定义指标的完整流程

RaptorBT 的指标架构非常清晰,添加一个新指标需要改 3 个文件,我以添加 CCICommodity Channel Index 为例演示:

第 1 步:在 Rust 里实现指标逻辑

momentum.rs 中添加函数(或新建文件都行,这里选 momentum.rs 因为 CCI 属于动量类):

/// Commodity Channel Index (CCI).
///
/// # Arguments
/// * `high` - High prices
/// * `low` - Low prices
/// * `close` - Close prices
/// * `period` - Lookback period (default: 20)
///
/// # Returns
/// Vector of CCI values (NaN for warmup period)
pub fn cci(high: &[f64], low: &[f64], close: &[f64], period: usize) -> Result<Vec<f64>> {
    if period == 0 {
        return Err(RaptorError::invalid_parameter("CCI period must be > 0"));
    }
    let n = close.len();
    if n != high.len() || n != low.len() {
        return Err(RaptorError::length_mismatch(n, high.len()));
    }

    let mut result = vec![f64::NAN; n];
    if period >= n {
        return Ok(result);
    }

    // Typical Price
    let tp: Vec<f64> = (0..n).map(|i| (high[i] + low[i] + close[i]) / 3.0).collect();

    // SMA of Typical Price + Mean Deviation
    for i in (period - 1)..n {
        let start = i + 1 - period;
        let tp_sma: f64 = tp[start..=i].iter().sum::<f64>() / period as f64;
        let mean_dev: f64 = tp[start..=i].iter().map(|x| (x - tp_sma).abs()).sum::<f64>() / period as f64;

        if mean_dev > f64::EPSILON {
            result[i] = (tp[i] - tp_sma) / (0.015 * mean_dev);
        } else {
            result[i] = 0.0;
        }
    }

    Ok(result)
}

第 2 步:在 mod.rs 导出

mod.rspub use momentum::... 行加上 cci

pub use momentum::{cci, macd, rsi, stochastic, MacdResult, StochasticResult};

第 3 步:在 bindings.rs 添加 Python 绑定

bindings.rs 的指标函数区域添加:

/// Commodity Channel Index.
#[pyfunction]
pub fn cci<'py>(
    py: Python<'py>,
    high: PyReadonlyArray1<f64>,
    low: PyReadonlyArray1<f64>,
    close: PyReadonlyArray1<f64>,
    period: usize,
) -> PyResult<&'py PyArray1<f64>> {
    let h = numpy_to_vec_f64(high);
    let l = numpy_to_vec_f64(low);
    let c = numpy_to_vec_f64(close);
    let result = indicators::momentum::cci(&h, &l, &c, period)
        .map_err(|e| pyo3::exceptions::PyValueError::new_err(e.to_string()))?;
    Ok(vec_to_numpy_f64(py, result))
}

第 4 步:在 lib.rs 注册

lib.rs 的指标注册区添加:

m.add_function(wrap_pyfunction!(python::bindings::cci, m)?)?;

第 5 步:编译 & 使用

maturin develop --release

然后 Python 里就能用了:

cci = raptorbt.cci(high, low, close, period=20)

总结:3 文件修改清单

文件 改什么 位置
src/indicators/momentum.rs(或新文件) 实现 pub fn cci(...) -> Result<Vec<f64>> 和 rsi/macd 同级
src/indicators/mod.rs pub use momentum::cci 导出行
src/python/bindings.rs 添加 #[pyfunction] pub fn cci<...> 指标函数区
src/lib.rs m.add_function(wrap_pyfunction!(...::cci, m)?) 指标注册区

规律:所有现有指标(sma/ema/rsi/macd/atr/bollinger_bands/adx/vwap/supertrend/stochastic/rolling_min/rolling_max)都是这个模式。你照着抄一个最简单的(比如 sma),改成自己的计算逻辑就行。