其他
在 openalgo 中基于 Rust-core ta…
当需要为 openalgo 编写可生产使用、O(n) 且可绘图/基准测试的自定义技术指标时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 35/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 39/100 ×0.15
适用场景
在 openalgo 中基于 Rust-特定
解决思路
- 参数:将 `$0` 作为指标名(如 zscore、squeeze、vwap-bands、custom-rsi、mean-reversion),必填;若未提供,先询问用户想构建什么指标。
- 阅读指标专家规则,尤其是 `rules/custom-indicators.md`(NumPy + ta 原语模式与模板)、`rules/performance.md`(Rust core 性能、O(n) 保证、基准测试)、`rules/indicator-catalog.md`(检查 openalgo.ta 中是否已有该指标)。
- 先检查:如果指标已存在于 `openalgo.ta`(100+ 指标),告知用户并展示已有 API。
- 按需创建 `custom_indicators/{indicator_name}/` 目录。
- 创建 `{indicator_name}.py`,包含模块 docstring:`{Indicator Name} — Custom Indicator`、`Description: {what it measures}`、`Category: {trend/momentum/volatility/volume/oscillator}`。
- 在 `{indicator_name}.py` 中导入 `numpy as np`、`pandas as pd`、`from openalgo import ta`。
- 实现 `_compute_{name}(arr: np.ndarray, period: int) -> np.ndarray`:用 `np.full(n, np.nan)` 初始化结果;从 `ta` 原语组合计算(它们运行在 Rust core),例如 `mean = ta.sma(arr, period)`、`std = ta.stdev(arr, period)`;再用 NumPy 数组运算(`np.where`、掩码)组合。
- 实现公共 API `{name}(data, period=20)`:接收收盘价(numpy array、pandas Series 或 list),返回与输入同类型;若 `data` 是 `pd.Series`,保存 `idx = data.index`,对 `data.values.astype(np.float64)` 调用 `_compute_{name}`,返回 `pd.Series(result, index=idx, name='{Name}({period})')`;否则用 `arr = np.asarray(data, dtype=np.float64)` 后调用 `_compute_{name}` 并返回。
- 创建 `chart.py` 用于可视化:用 Plotly 绘制自定义指标;包含 `import os`、`from pathlib import Path`、`from datetime import datetime, timedelta`、`from dotenv import find_dotenv, load_dotenv`、`from openalgo import api, ta`、`import plotly.graph_objects as go`、`from plotly.subplots import make_subplots`、`from {indicator_name} import {name}`;然后获取数据、计算指标、创建图表。
- 创建 `benchmark.py` 做性能测试(无需 warmup——Rust core 从第一次调用就全速运行):导入 `numpy as np`、`time`、`from {indicator_name} import {name}`;对 `size in [10_000, 100_000, 500_000]`,生成 `data = np.random.randn(size).cumsum() + 1000`,用 `time.perf_counter()` 计时调用 `{name}(data, 20)`,计算 `elapsed = (time.perf_counter() - t0) * 1000`,打印 `f'{size:>10,} bars: {elapsed:>8.2f}ms'`。
- NumPy 必须做:尽可能从 `ta` 原语组合,它们运行在 Rust core。
- NumPy 必须做:用 `np.full(n, np.nan)` 初始化输出数组。
- NumPy 必须做:用数组表达式、`np.where`、布尔掩码向量化。
- NumPy 必须做:保护除法:`np.errstate(invalid='ignore', divide='ignore')` 加安全分母掩码。
- NumPy 必须做:遵守原语的 NaN warm-up 周期,在 `~np.isnan(...)` 上掩码。
- NumPy 必须做:所有数值数组用 `float64`。
- NumPy 必须做:只用 O(n) 算法。
- NumPy 不得:绝不重新实现 `openalgo.ta` 中已有的指标。
- NumPy 不得:绝不要在大数组上写逐 bar Python 循环——要向量化。
- NumPy 不得:绝不在没有掩码零/NaN 分母的情况下做除法。
- NumPy 不得:如果指标确实是路径依赖(没有原语覆盖的顺序状态),先检查 `ta.ema` / Wilder 风格原语是否已提供递归;普通 Python 循环是最后手段——保持 O(n) 并记录权衡。
- 可用构建块:`from openalgo import ta`;滚动数学:`ta.sma`、`ta.ema`、`ta.wma`、`ta.stdev`、`ta.highest`、`ta.lowest`;价格行为:`ta.true_range`、`ta.atr`、`ta.change`、`ta.roc`;带/通道:`ta.bbands`、`ta.keltner`、`ta.donchian`;信号:`ta.crossover`、`ta.crossunder`、`ta.exrem`、`ta.rising`、`ta.falling`。
- 常见自定义指标模式:Z-Score = `(value - rolling_mean) / rolling_stdev`;Squeeze = Bollinger inside Keltner channel;VWAP Bands = VWAP + N * rolling stdev of (close - vwap);Momentum Score = Weighted sum of RSI + MACD + ADX conditions;Mean Reversion = Distance from SMA as % + threshold;Range Filter = ATR-based dynamic filter on close;Trend Strength = ADX + directional movement composite。
- 示例用法:`/custom-indicator zscore`、`/custom-indicator squeeze-momentum`、`/custom-indicator vwap-bands`、`/custom-indicator range-filter`。
适用边界 · 注意事项
- 指标已存在于 `openalgo.ta` 时不要重新实现,应直接展示已有 API。
- 没有安装/无法使用 openalgo 及其 Rust-core `ta` 原语时,不能按此技能生成生产级指标。
- 指标是复杂路径依赖且没有现成 ta 原语或 EMA/Wilder 递归可覆盖时,向量化方案不适用;普通 Python 循环只能作为最后手段并需记录权衡。