信号原语参考指南
信号原语(Signal Primitives)是用于生成交易信号的组件,它们接收一个或多个时间序列作为输入,并输出布尔型时间序列(true/false)。这些组件可以组合成复杂的交易条件。
信号原语基础
所有信号原语都实现了evaluate方法,该方法接收输入时间序列并返回布尔结果。信号原语可以:
- 评估单个时间点(返回单个布尔值)
- 评估整个时间序列(返回布尔型Series)
可用信号原语
比较类信号
⚠️ 重要警告:输入顺序至关重要
对于所有比较类信号(尤其是LessThan和GreaterThan),输入参数的顺序会直接影响比较结果。 当涉及常量与变量的比较时,必须将常量放在左侧,变量放在右侧,以确保执行预期的比较。
错误示例(常见错误!):
// 本意是 rsi < 70,但实际执行的是 70 < rsi
{
"type": "LessThan",
"inputs": [
{ "ref": "rsi" },
{ "type": "Constant", "value": 70 }
]
}正确示例:
// 正确执行 rsi < 70
{
"type": "LessThan",
"inputs": [
{ "type": "Constant", "value": 70 },
{ "ref": "rsi" }
]
}
GreaterThan 和 LessThan (替代 Comparison)
推荐使用 GreaterThan 和 LessThan 替代通用的 Comparison,它们提供更明确的语义和更好的性能。
{
"id": "price_above_ma",
"type": "GreaterThan",
"epsilon": 0.01,
"inputs": [
{ "column": "Close" },
{ "ref": "ma_indicator" }
]
}
参数:
epsilon: 用于处理浮点比较精度问题的小值(默认: 0)
注意事项:
- 比较两个时间序列时,会使用epsilon值作为精度缓冲
- 输入顺序至关重要,请参考下面的 GreaterThan 和 LessThan 部分
GreaterThan (大于)
检查第一个输入是否大于第二个输入。输入顺序至关重要!
{
"id": "price_gt_ma",
"type": "GreaterThan",
"epsilon": 0.01,
"inputs": [
{ "column": "Close" }, // 要检查的值放第一位
{ "ref": "ma_indicator" } // 与之比较的值放第二位
]
}
常量比较的正确写法:
{
"id": "rsi_overbought",
"type": "GreaterThan",
"epsilon": 0.5,
"inputs": [
{ "ref": "rsi_indicator" }, // 变量放第一位
{ "ref": "upper_threshold" } // 引用常量指标而不是直接使用value
]
}
参数:
epsilon: 浮点数比较精度参数(可选,默认为0)。当比较 a > b 时,实际比较为 a > (b + epsilon)。- 例如:当阈值为70,epsilon为0.01时,只有值大于70.01才会返回true
- 适用于处理边界条件和浮点数精度问题
注意事项:
- 无论是否使用 epsilon,输入的顺序都是决定性的
- 对于
GreaterThan(a, b),执行的是a > (b + epsilon) - 推荐使用常量指标(如
upper_threshold)而不是直接使用value属性
LessThan (小于)
检查第一个输入是否小于第二个输入。输入顺序至关重要!
{
"id": "price_lt_ma",
"type": "LessThan",
"epsilon": 0.01,
"inputs": [
{ "column": "Close" }, // 要检查的值放第一位
{ "ref": "ma_indicator" } // 与之比较的值放第二位
]
}
常量比较的正确写法:
{
"id": "rsi_not_overbought",
"type": "LessThan",
"epsilon": 0.5,
"inputs": [
{ "ref": "rsi_indicator" }, // 变量放第一位
{ "ref": "upper_threshold" } // 引用常量指标而不是直接使用value
]
}
参数:
epsilon: 浮点数比较精度参数(可选,默认为0)。当比较 a < b 时,实际比较为 a < (b - epsilon)。- 例如:当阈值为70,epsilon为0.01时,只有值小于69.99才会返回true
- 适用于处理RSI等指标的边界条件和浮点数精度问题
注意事项:
- 无论是否使用 epsilon,输入的顺序都是决定性的
- 对于
LessThan(a, b),执行的是a < (b - epsilon) - 推荐使用常量指标(如
lower_threshold)而不是直接使用value属性
InRange (在范围内)
检查输入值是否在指定范围内。
{
"id": "rsi_neutral",
"type": "InRange",
"params": {
"lower_inclusive": true,
"upper_inclusive": true
},
"inputs": [
{ "ref": "rsi_indicator" },
{ "ref": "lower_bound" },
{ "ref": "upper_bound" }
]
}
参数:
lower_inclusive: 是否包含下界(默认: true)upper_inclusive: 是否包含上界(默认: true)
注意事项:
- 需要三个输入: 评估值, 下界, 上界
- 适合检测指标是否在特定区间内(如RSI在30-70之间)
交叉类信号
Crossover (上穿)
检测第一个输入是否向上穿越第二个输入。
{
"id": "price_cross_above_ma",
"type": "Crossover",
"params": { "mode": "simple" },
"inputs": [
{ "column": "Close" },
{ "ref": "ma_indicator" }
]
}
参数:
mode: 交叉检测模式,可选值:simple: 简单交叉检测(默认)confirmed: 要求确认(连续两个周期)
注意事项:
- 只在实际发生穿越的那一个时间点返回true
- 穿越后的后续时间点返回false,直到发生新的穿越
- 适合用作买入/卖出触发信号
Crossunder (下穿)
检测第一个输入是否向下穿越第二个输入。
{
"id": "price_cross_below_ma",
"type": "Crossunder",
"params": { "mode": "simple" },
"inputs": [
{ "column": "Close" },
{ "ref": "ma_indicator" }
]
}
参数:
mode: 交叉检测模式,可选值:simple: 简单交叉检测(默认)confirmed: 要求确认(连续两个周期)
注意事项:
- 只在实际发生穿越的那一个时间点返回true
- 穿越后的后续时间点返回false,直到发生新的穿越
- 适合用作买入/卖出触发信号
逻辑运算符类
And (逻辑与)
要求所有输入信号同时为true。支持嵌套信号和内联常量。
基本用法:
{
"id": "buy_condition",
"type": "And",
"inputs": [
{ "ref": "price_above_ma" },
{ "ref": "rsi_oversold" }
]
}
嵌套信号示例:
{
"id": "buy_condition_core",
"type": "And",
"inputs": [
{ "ref": "macd_cross_signal" },
{
"type": "GreaterThan",
"inputs": [
{ "column": "Volume" },
{ "ref": "volume_ma" }
],
"params": {
"threshold": 1.5
}
}
]
}
内联常量支持:
{
"id": "enhanced_buy",
"type": "And",
"inputs": [
{ "ref": "buy_condition_core" },
{
"type": "LessThan",
"inputs": [
{ "ref": "volume_ratio" },
{ "type": "Constant", "value": 3 }
]
}
]
}
Or (逻辑或)
当任一输入信号为true时返回true。
{
"id": "sell_condition",
"type": "Or",
"inputs": [
{ "ref": "stop_loss_hit" },
{ "ref": "take_profit_hit" }
]
}
Not (逻辑非)
对输入信号取反。
{
"id": "not_overbought",
"type": "Not",
"inputs": [
{ "ref": "rsi_overbought" }
]
}
逻辑运算符新特性:
- 嵌套信号支持: And/Or可以接受嵌套的信号定义作为输入
- 内联常量: 嵌套信号中支持
{"type": "Constant", "value": N}格式 - 灵活组合: 可以混合使用信号引用和嵌套定义
注意事项:
- 增强了NaN处理逻辑
- 适合需要排除特定条件的场景
- 嵌套信号会自动评估,无需预先定义ID
模式识别类
Streak (连续模式)
检测连续满足条件的模式。注意:Streak 使用"回溯标记"语义,即标记整个符合条件的连续序列,而非延迟触发。
{
"id": "consecutive_up_days",
"type": "Streak",
"params": {
"match_type": "true",
"min_length": 3,
"max_length": 5
},
"inputs": [
{ "ref": "daily_gain" }
]
}
参数:
match_type: 匹配类型,可选值:"true"(默认): 检测连续的 True 值"false": 检测连续的 False 值"any": 检测任意连续相同的值(不区分 True/False)
min_length: 最小连续长度(默认: 2,必须大于0)max_length: 最大连续长度(可选,如指定则必须大于等于min_length)
行为说明:
Streak 采用"回溯标记"(retrospective marking)语义:
- 整序列标记: 当检测到符合条件的连续序列时,会标记该序列中的所有位置(从第一天开始),而非仅标记第 N 天
- max_length 截断: 如果连续序列超过
max_length,只标记前max_length个位置 - 批量处理: 作为无状态原语,Streak 一次性处理整个时间序列
示例:
假设输入序列为 [F, T, T, T, T, F],配置 min_length=3, max_length=null, match_type="true":
- 结果:
[F, T, T, T, T, F]— 标记所有 4 个连续 True 位置
假设输入序列为 [F, T, T, T, T, T, F],配置 min_length=3, max_length=3:
- 结果:
[F, T, T, T, F, F, F]— 只标记前 3 个位置
注意事项:
- 适合检测连续上涨/下跌或其他持续模式
- 不适合用于"等待 N 天后再触发"的延迟信号场景(因为是回溯标记而非延迟触发)
- 如需延迟触发语义,请使用
Lag原语组合实现(见下文)
时序类
Lag (时序位移)
将时间序列按指定周期位移,用于实现延迟确认、历史数据引用等场景。这是实现"连续 N 天确认后触发"逻辑的核心原语。
{
"id": "yesterday_condition",
"type": "Lag",
"params": {
"periods": 1,
"fill_value": 0
},
"inputs": [
{ "ref": "today_condition" }
]
}
参数:
periods: 位移周期数(默认: 1,大于等于0)。正数表示向后看(获取过去的值)fill_value: 填充值(可选)。位移产生的空值用此填充。布尔序列建议用 0 (False) 或 1 (True)
典型用法 - 连续 2 天确认:
{
"signals": [
{
"id": "condition_today",
"type": "LessThan",
"inputs": [
{ "ref": "some_indicator" },
{ "ref": "threshold" }
]
},
{
"id": "condition_yesterday",
"type": "Lag",
"params": { "periods": 1, "fill_value": 0 },
"inputs": [{ "ref": "condition_today" }]
},
{
"id": "confirmed_signal",
"type": "And",
"inputs": [
{ "ref": "condition_today" },
{ "ref": "condition_yesterday" }
]
}
]
}
执行逻辑:
日期 condition_today condition_yesterday confirmed_signal
Day 1 True False (filled) False ← 第1天不触发
Day 2 True True (from Day1) True ← 连续2天,触发!
Day 3 True True (from Day2) True
Day 4 False True (from Day3) False
注意事项:
- Lag 是无状态原语,符合声明式配置的设计原则
- 与
And组合可实现任意 N 天确认逻辑 fill_value对于布尔信号很重要,建议显式设置为 0
数学运算类
🆕 新功能:纯数学运算模式
数学运算类信号现在支持两种工作模式:
- 比较模式(默认):执行数学运算后与阈值比较,返回布尔结果
- 纯数学模式:设置
return_calculation=true时,直接返回数学运算结果
PercentChange (百分比变化)
计算时间序列的百分比变化,并与阈值或另一时间序列比较。
{
"id": "price_up_5percent",
"type": "PercentChange",
"params": {
"period": 5,
"threshold": 5.0,
"comparison": "greater"
},
"inputs": [
{ "column": "Close" }
]
}
参数:
period: 计算变化的周期(默认: 1)threshold: 比较阈值(可选)comparison: 比较类型(默认: "greater")
注意事项:
- 可与阈值比较或与另一时间序列比较
- 适合检测价格动量或大幅波动
Add (加法)
将两个或多个时间序列相加。支持比较模式和纯数学运算模式。
比较模式示例(默认行为):
{
"id": "combined_gt_threshold",
"type": "Add",
"params": {
"threshold": 100,
"comparison": "greater"
},
"inputs": [
{ "ref": "indicator1" },
{ "ref": "indicator2" }
]
}
纯数学运算模式示例:
{
"id": "combined_indicator",
"type": "Add",
"params": {
"return_calculation": true
},
"inputs": [
{ "ref": "indicator1" },
{ "ref": "indicator2" },
{ "ref": "indicator3" }
]
}
参数:
return_calculation: 是否返回计算结果而非比较结果(默认: false)threshold: 比较阈值(仅在比较模式下使用)comparison: 比较类型(仅在比较模式下使用,默认: "greater")absolute: 是否对结果取绝对值(默认: false) 内联常量支持:
{
"id": "indicator_plus_constant",
"type": "Add",
"params": {
"return_calculation": true
},
"inputs": [
{ "ref": "base_indicator" },
{ "type": "Constant", "value": 10 }
]
}
Subtract (减法)
从第一个时间序列中减去第二个及后续时间序列(按从左到右顺序)。
纯数学运算示例:
{
"id": "indicator_difference",
"type": "Subtract",
"params": {
"return_calculation": true
},
"inputs": [
{ "ref": "indicator1" },
{ "ref": "indicator2" }
]
}
多操作数示例(左到右计算:(a - b) - c):
{
"id": "sequential_subtract",
"type": "Subtract",
"params": {
"return_calculation": true
},
"inputs": [
{ "ref": "base_value" },
{ "ref": "adjustment1" },
{ "type": "Constant", "value": 5 }
]
}
Multiply (乘法)
将两个或多个时间序列相乘(支持多操作数)。
纯数学运算示例:
{
"id": "weighted_indicator",
"type": "Multiply",
"params": {
"return_calculation": true
},
"inputs": [
{ "ref": "indicator" },
{ "ref": "weight" }
]
}
多操作数乘法示例:
{
"id": "signal_strength",
"type": "Multiply",
"params": {
"return_calculation": true
},
"inputs": [
{ "ref": "macd_atr_ratio" },
{ "ref": "ma_close_ratio" },
{ "type": "Constant", "value": 1.0 }
]
}
Divide (除法)
将第一个时间序列除以第二个及后续时间序列(按从左到右顺序)。
纯数学运算示例:
{
"id": "indicator_ratio",
"type": "Divide",
"params": {
"return_calculation": true
},
"inputs": [
{ "ref": "indicator1" },
{ "ref": "indicator2" }
]
}
多操作数示例(左到右计算:(a / b) / c):
{
"id": "normalized_ratio",
"type": "Divide",
"params": {
"return_calculation": true
},
"inputs": [
{ "column": "Volume" },
{ "ref": "volume_ma" },
{ "type": "Constant", "value": 1000 }
]
}
数学运算类通用参数:
return_calculation: 是否返回纯数学计算结果(默认: false)true: 返回数值结果,支持多操作数按从左到右计算false: 执行运算后与阈值比较,返回布尔结果
threshold: 比较阈值(仅在比较模式下生效)comparison: 比较类型("greater", "less", "equal"等,仅在比较模式下生效)absolute: 是否对运算结果取绝对值(默认: false) 重要特性:
- 向后兼容: 默认行为保持不变,现有配置无需修改
- 多操作数支持: 纯数学模式支持2个以上输入,按从左到右顺序计算
- 内联常量: 支持
{"type": "Constant", "value": N}格式的内联常量 - 除零处理: Divide操作自动处理除零情况,返回NaN
策略切换类
StockBondSwitch (股债切换)
⚠️ 智能资产轮动信号
这是一个专门为多资产轮动策略设计的智能信号原语,它能够自动识别当前正在评估的标的, 并根据标的在投资组合中的位置(约定:第一个=股票类资产,第二个=债券类资产)以及市场条件 返回相应的买入信号。
根据市场条件信号为不同资产生成互补的买入信号,实现股债轮动策略。
{
"id": "stock_bond_buy",
"type": "StockBondSwitch",
"params": {
"default_to_stock": true
},
"inputs": [
{ "ref": "market_trend_up" }
]
}
工作原理:
该原语能够智能识别当前正在评估的标的和投资组合中的所有标的, 根据标的在投资组合中的位置和市场条件,为不同标的返回互补的买入信号:
| 条件信号 | 股票ETF(位置0) | 债券ETF(位置1) |
|---|---|---|
True | True (买入) | False (不买) |
False | False (不买) | True (买入) |
配置约定:
- symbols[0]: 股票ETF(如510300、SPY等)
- symbols[1]: 债券ETF(如511260、TLT等)
参数:
default_to_stock: 当条件信号中包含NaN值时的默认填充行为(默认: true)true: NaN填充为True(偏向股票)false: NaN填充为False(偏向债券)
返回值:
- 返回布尔型
pd.Series,表示当前标的是否应该买入 - 对于股票ETF:条件为True时返回True,条件为False时返回False
- 对于债券ETF:条件为False时返回True,条件为True时返回False
完整配置示例:
{
"market_indicators": {
"indicators": [
{
"code": "000300.SH"
}
],
"transformers": [
{
"name": "hs300_raw",
"type": "IdentityTransformer",
"params": {
"indicator": "000300.SH",
"field": "Close"
}
},
{
"name": "hs300_ma200",
"type": "MovingAverageTransformer",
"params": {
"indicator": "000300.SH",
"window": 200,
"method": "simple",
"field": "Close"
}
}
]
},
"trade_strategy": {
"indicators": [],
"signals": [
{
"id": "market_trend_up",
"type": "GreaterThan",
"inputs": [
{
"market": "000300.SH",
"transformer": "hs300_raw"
},
{
"market": "000300.SH",
"transformer": "hs300_ma200"
}
]
},
{
"id": "stock_bond_buy",
"type": "StockBondSwitch",
"params": {
"default_to_stock": true
},
"inputs": [
{
"ref": "market_trend_up"
}
]
},
{
"id": "stock_bond_sell",
"type": "Not",
"inputs": [
{
"ref": "stock_bond_buy"
}
]
}
],
"outputs": {
"buy_signal": "stock_bond_buy",
"sell_signal": "stock_bond_sell"
}
}
}
技术特点:
-
智能识别: 自动识别当前正在评估的标的和投资组合配置
-
上下文感知: 能够获取完整的投资组合标的列表和当前标的信息
-
安全机制:
- 无法获取投资组合信息时默认不产生买入信号
- 投资组合标的少于2个时不产生买入信号
- 当前标的不在前两个位置时不产生买入信号
注意事项:
- 这是一个标准的信号原语,返回布尔型Series,与其他信号原语完全兼容
- 必须配合
CompositeStrategy使用,不能用于单标的策略 - 卖出信号通常使用
Not原语对买入信号取反 - 适用于任何两资产轮动策略(不仅限于股债)
使用场景:
- 股债轮动(股票ETF ↔ 债券ETF)
- 风险开关策略(风险资产 ↔ 避险资产)
- 趋势跟踪(趋势资产 ↔ 现金等价物)
- 动量轮动(高动量资产 ↔ 低动量资产)
权重控制原语
权重控制原语用于动态调整仓位大小,输出 0.0-1.0 之间的目标权重值。这些原语与交易信号配合使用,实现基于市场条件的灵活仓位管理。
核心概念
target_weight(目标权重):表示某个标的应占总资产的目标比例,取值范围 0.0-1.0。
- 0.0:空仓(完全不持有)
- 0.3:轻仓(持有30%)
- 0.6:中仓(持有60%)
- 1.0:满仓(全仓持有)
执行语义
重要理解:target_weight 表示在交易信号触发时使用的目标权重,而非实时维护的目标权重:
- ✅ 买入信号(B)触发时:按 target_weight 建仓
- ✅ 卖出信号(S)触发且 target_weight > 0 时:调整到 target_weight(部分卖出)
- ❌ 持有期间(H) target_weight 变化:不触发自动调整
设计理由:
- 避免因指标波动产生过度交易
- 职责分离:信号控制时机,权重控制规模
- 符合主动策略的标准实践
ConditionalWeight (条件权重)
根据布尔条件选择不同的目标权重(离散权重调整)。
{
"id": "rsi_based_weight",
"type": "ConditionalWeight",
"inputs": [
{ "ref": "rsi_overbought" }
],
"params": {
"true_weight": 0.5,
"false_weight": 1.0
}
}
参数:
true_weight: 条件为 true 时的目标权重,范围 [0, 1]false_weight: 条件为 false 时的目标权重,范围 [0, 1]
输入:
- 单个布尔条件序列 (pd.Series of bool)
输出:
- 权重序列 (pd.Series of float),值为
true_weight或false_weight
使用场景:
- RSI超买超卖调仓:RSI > 70 时半仓,RSI 正常时满仓
- PE/PB估值调仓:估值过高时减仓,估值正常时满仓
- 波动率调仓:高波动时减仓,低波动时加仓
- 任何基于条件的离散权重调整
完整示例:
{
"indicators": [
{
"id": "rsi",
"type": "RSI",
"params": { "period": 14 }
},
{
"id": "sma_short",
"type": "SMA",
"params": { "period": 20 }
},
{
"id": "sma_long",
"type": "SMA",
"params": { "period": 60 }
}
],
"signals": [
{
"id": "rsi_overbought",
"type": "GreaterThan",
"inputs": [
{ "ref": "rsi" },
{ "type": "Constant", "value": 70 }
]
},
{
"id": "buy_signal",
"type": "CrossAbove",
"inputs": [
{ "ref": "sma_short" },
{ "ref": "sma_long" }
]
},
{
"id": "sell_signal",
"type": "CrossBelow",
"inputs": [
{ "ref": "sma_short" },
{ "ref": "sma_long" }
]
},
{
"id": "dynamic_weight",
"type": "ConditionalWeight",
"inputs": [{ "ref": "rsi_overbought" }],
"params": {
"true_weight": 0.5,
"false_weight": 1.0
}
}
],
"outputs": {
"buy_signal": "buy_signal",
"sell_signal": "sell_signal",
"target_weight": "dynamic_weight"
}
}
执行效果:
- 当 SMA20 上穿 SMA60 触发买入信号时:
- 如果 RSI > 70(超买):按 50% 仓位建仓
- 如果 RSI ≤ 70(正常):按 100% 仓位建仓
- 持有期间 RSI 变化不会触发交易
- 只有在新的买入/卖出信号触发时,才会使用当时的 target_weight
LinearScaleWeight (线性缩放权重)
将指标值线性映射到权重范围(连续权重调整)。
{
"id": "rsi_smooth_weight",
"type": "LinearScaleWeight",
"inputs": [
{ "ref": "rsi" }
],
"params": {
"min_indicator": 30,
"max_indicator": 70,
"min_weight": 1.0,
"max_weight": 0.3,
"clip": true
}
}
参数:
min_indicator: 指标最小值max_indicator: 指标最大值min_weight: 映射到的最小权重,范围 [0, 1]max_weight: 映射到的最大权重,范围 [0, 1]clip: 是否裁剪超出范围的值(默认: true)
输入:
- 单个数值指标序列 (pd.Series of float)
输出:
- 权重序列 (pd.Series of float),值在 [min_weight, max_weight] 范围内
映射公式:
当 indicator 在 [min_indicator, max_indicator] 范围内时,权重按以下公式线性映射:
weight = min_weight + (indicator - min_indicator) / (max_indicator - min_indicator) * (max_weight - min_weight)
当 clip=true 时,超出范围的值会被裁剪到 [min_weight, max_weight]。
使用场景:
- RSI平滑调仓:RSI 从 30 到 70,仓位从 100% 平滑降到 30%
- PE估值调仓:PE 从 15 到 30,仓位从 100% 平滑降到 30%
- 波动率调仓:ATR比率从 0.7 到 1.8,仓位从 100% 平滑降到 30%
- 任何需要连续调整权重的场景
完整示例:
{
"indicators": [
{ "id": "rsi", "type": "RSI", "params": { "period": 14 } },
{ "id": "sma_short", "type": "SMA", "params": { "period": 20 } },
{ "id": "sma_long", "type": "SMA", "params": { "period": 60 } }
],
"signals": [
{
"id": "buy_signal",
"type": "CrossAbove",
"inputs": [{ "ref": "sma_short" }, { "ref": "sma_long" }]
},
{
"id": "sell_signal",
"type": "CrossBelow",
"inputs": [{ "ref": "sma_short" }, { "ref": "sma_long" }]
},
{
"id": "smooth_weight",
"type": "LinearScaleWeight",
"inputs": [{ "ref": "rsi" }],
"params": {
"min_indicator": 30,
"max_indicator": 70,
"min_weight": 1.0,
"max_weight": 0.3,
"clip": true
}
}
],
"outputs": {
"buy_signal": "buy_signal",
"sell_signal": "sell_signal",
"target_weight": "smooth_weight"
}
}
执行效果:
- RSI = 30(超卖)→ target_weight = 1.0(满仓)
- RSI = 50(中性)→ target_weight = 0.65(65%仓位)
- RSI = 70(超买)→ target_weight = 0.3(30%仓位)
当买入信号触发时,根据当时的 RSI 值决定建仓比例。
权重原语配置要求
使用权重原语时,需要配合 RebalancingCapitalStrategy 资金策略:
{
"capital_strategy": {
"name": "RebalancingCapitalStrategy",
"params": {
"initial_capital": 100000
}
}
}
如果使用其他资金策略(如 PercentCapitalStrategy),target_weight 将被忽略,策略将按照固定比例交易。
应用场景
1. 估值驱动的动态仓位
根据估值指标(PE/PB)动态调整仓位:
{
"id": "pe_weight",
"type": "LinearScaleWeight",
"inputs": [{ "ref": "pe_ratio" }],
"params": {
"min_indicator": 15,
"max_indicator": 30,
"min_weight": 1.0,
"max_weight": 0.3,
"clip": true
}
}
2. 波动率风险控制
根据市场波动率调整风险敞口:
{
"id": "vix_weight",
"type": "LinearScaleWeight",
"inputs": [{ "ref": "vix" }],
"params": {
"min_indicator": 15,
"max_indicator": 30,
"min_weight": 1.0,
"max_weight": 0.3,
"clip": true
}
}
3. 技术指标组合
结合多个权重原语:
{
"signals": [
{
"id": "rsi_weight",
"type": "LinearScaleWeight",
"inputs": [{ "ref": "rsi" }],
"params": {
"min_indicator": 30,
"max_indicator": 70,
"min_weight": 1.0,
"max_weight": 0.4
}
},
{
"id": "atr_weight",
"type": "LinearScaleWeight",
"inputs": [{ "ref": "atr_ratio" }],
"params": {
"min_indicator": 0.7,
"max_indicator": 1.8,
"min_weight": 1.0,
"max_weight": 0.3
}
},
{
"id": "weight_sum",
"type": "Add",
"params": { "return_calculation": true },
"inputs": [{ "ref": "rsi_weight" }, { "ref": "atr_weight" }]
},
{
"id": "combined_weight",
"type": "Multiply",
"params": { "return_calculation": true },
"inputs": [
{ "ref": "weight_sum" },
{ "type": "Constant", "value": 0.5 }
]
}
],
"outputs": {
"buy_signal": "buy_condition",
"sell_signal": "sell_condition",
"target_weight": "combined_weight"
}
}
相关资源
信号组合最佳实践
-
构建复合条件:
- 使用
And、Or组合多个信号 - 使用
Not反转信号 - 例如:
And(CrossAbove(RSI, 30), GreaterThan(Close, SMA))
- 使用
-
交叉事件vs状态:
- 交叉事件(CrossAbove/CrossBelow)只在穿越发生时为true
- 状态比较(GreaterThan/LessThan)只要条件满足就一直为true
- 明确了解这一区别对避免频繁交易很重要
-
过滤假信号:
- 使用Streak要求信号持续一定时间
- 结合多个指标确认信号
- 使用趋势过滤器(如价格高于均线)
-
信号命名和组织:
- 使用清晰的ID命名每个信号组件
- 从简单到复杂逐步构建信号
- 先定义基本条件,再组合成复杂条件
-
动态仓位控制:
- 权重原语应该输出到
target_weight字段 - 必须配合
RebalancingCapitalStrategy使用 - 考虑交易成本,避免频繁小幅调仓
- 权重变化只在交易信号触发时生效
- 权重原语应该输出到
常见错误和解决方案
-
过度频繁的信号:
- 问题: 使用状态比较(如GreaterThan)作为买入信号
- 解决: 使用CrossAbove/CrossBelow检测交叉事件
-
信号缺失:
- 问题: 输入时间序列有NaN值
- 解决: 确保指标计算有足够的历史数据
-
精度问题:
- 问题: 浮点比较导致不稳定的结果
- 解决: 在Comparison中使用epsilon参数
-
逻辑错误:
- 问题: 混淆And/Or逻辑
- 解决: 仔细验证复合条件的预期行为
-
动态仓位不生效:
- 问题: 使用了
PercentCapitalStrategy而非RebalancingCapitalStrategy - 解决: 检查资金策略配置,确保使用正确的策略类型
- 问题: 使用了
-
仓位频繁调整:
- 问题: 期望 target_weight 变化时自动调仓
- 解决: 理解执行语义,权重只在交易信号触发时生效