# 策引原语策略参考文档 (llm.txt)
# Plutus Primitive Strategy Reference for LLMs
#
# 版本: 完整版 (Full Version)
# 大小: ~400KB | Token: ~130-150K
# 适用模型: Gemini 1.5 Pro/Flash (推荐), Claude 3.5 Opus
# 内容: 完整文档 + 详细案例分析
#
# 核心版文档地址: https://docs.myinvestpilot.com/primitives/_llm/llm-core.txt
# 完整版文档地址: https://docs.myinvestpilot.com/primitives/_llm/llm-full.txt
# 在线文档: https://docs.myinvestpilot.com/docs/primitives/ai-assisted-development
# 可视化编辑器: https://www.myinvestpilot.com/primitives-editor/
#
# 生成时间: 2026-01-26T03:24:16.105Z
================================================================================
目录结构
================================================================================
本文档包含以下部分:
【核心参考】
- 快速入门: 原语策略基础概念和JSON结构
- AI辅助开发: 完整的AI辅助策略开发工作流
- 架构概述: 系统设计原则
- 指标原语参考: 所有可用的技术指标 (SMA, EMA, RSI, MACD, ATR, etc.)
- 信号原语参考: 所有可用的信号类型 (比较、交叉、逻辑、数学运算、权重控制)
- 组合模式: 如何组合原语构建复杂策略
【高级功能】
- 市场指标: 使用外部市场数据 (VIX, SPX等) 进行决策
【实战案例】
- 策略示例: 基础到进阶的完整策略配置
- 动态仓位案例: 基于RSI/ATR的动态仓位控制
- 股债轮动案例: 股票债券智能轮动策略优化
- 加密货币案例: 12个加密策略的实战对比
- 信号确认案例: 速度与质量的艰难权衡
【调试与优化】
- 故障排除: 常见问题诊断和解决
- 高级调试: SQL数据分析和策略诊断
- 策略优化: 参数调优和性能提升
- 设计最佳实践: 策略设计原则和反模式
- 架构局限性: 系统限制和解决方案
- 股债轮动、均值回归、杠杆ETF等多种策略案例
【调试与优化】
- 故障排除: 常见问题诊断
- 策略优化: 参数调优指南
- 架构局限性: 系统边界说明
================================================================================
================================================================================
核心参考文档
================================================================================
--------------------------------------------------------------------------------
快速入门 (getting-started.md)
--------------------------------------------------------------------------------
# 原语策略快速入门
本指南旨在帮助您快速上手原语策略系统,通过几个简单的例子,让您了解如何使用原语组件构建交易策略。无需深入了解复杂的编程概念,只需掌握基本的JSON配置格式,您就能创建自己的交易策略。
在开始配置原语策略之前,我们强烈建议您先访问[原语策略可视化编辑器](https://www.myinvestpilot.com/primitives-editor/)。这个直观的可视化工具可以帮助您:
- 以图形化方式构建和编辑策略
- 实时预览策略配置的 JSON 结构
- 快速理解原语组件之间的关系
- 避免手动编写 JSON 时的常见错误
通过可视化编辑器,您可以更轻松地掌握原语策略的配置方法,为后续的策略开发打下坚实基础。
## ⚠️ 重要说明:原语策略配置 vs 完整组合配置
**请注意区分以下两个概念:**
### 原语策略配置
在前端原语策略页面中,您只需要配置:
- `trade_strategy`(必须):包含指标、信号和输出的核心交易逻辑
- `market_indicators`(可选):当trade_strategy中使用市场指标时必须包含
### 完整组合配置
完整的投资组合配置还包含:
- 基本信息(name、code、description等)
- 交易标的(symbols)
- 时间参数(start_date、end_date等)
- 市场参数(currency、market、commission等)
- 资金管理策略(capital_strategy)
> 上面这些组合配置信息在组合创建更新表单就可以录入了
**重要规则:**
- 如果您的`trade_strategy`中使用了市场指标引用(如`{"market": "000300.SH", "transformer": "hs300_raw"}`),则必须在`market_indicators`中定义相应的指标和转换器
- 如果没有定义market_indicators但trade_strategy中引用了市场指标,回测将会失败
- 前端JSON schema只会将market_indicators标记为可选,但实际使用时可能是必须的
## 1. 原语策略系统简介
### 什么是原语策略?
原语策略是一种基于组件化思想的交易策略构建方法。在这个系统中,复杂的交易逻辑被分解为简单、可重用的基本组件(称为"原语"),这些组件可以像乐高积木一样自由组合,构建出各种复杂度的交易策略。
### 原语策略的优势
1. **可组合性**:原语组件可以自由组合,创建无限可能的策略
2. **可测试性**:每个组件都可以单独测试,确保其正确性
3. **可维护性**:当需要修改策略时,只需调整相关组件,而不是重写整个策略
4. **透明性**:策略的每个部分都有明确的功能和输出,便于理解和调试
5. **无需编程**:通过JSON配置文件即可定义策略,无需编写代码
### 原语策略与传统策略的区别
传统的交易策略通常是一段连续的代码,将数据处理、信号生成和交易决策混合在一起。而原语策略将这些功能分解为独立的组件,每个组件负责特定的功能,然后通过配置文件将它们连接起来。
这种方法的主要区别在于:
- **传统策略**:一体化、难以修改部分功能、难以重用代码
- **原语策略**:模块化、易于修改单个功能、组件可重用
### 核心设计原则:无状态
原语系统的核心设计原则是**无状态(Stateless)**:
- 每个原语接收完整的历史时间序列,返回向量化的结果
- 原语不保存跨调用的状态,每次评估都是独立的
- 这保证了可测试性、可组合性和回测的可靠性
这意味着原语策略**只适合无状态的策略**——即策略的每个时间点的决策仅依赖于当前和历史的市场数据,而不依赖于策略自身的"记忆"或累积状态。对于需要复杂状态管理的策略(如多标的轮动、动态仓位管理等),请参考[架构局限性](./advanced/architecture-limitations.md)文档。
## 2. 原语策略的基本组成部分
一个完整的原语策略通常包含以下几个部分:
### 指标组件(Indicators)
指标组件负责计算各种技术指标,如移动平均线、RSI、MACD等。这些组件接收价格数据作为输入,输出计算后的指标值。
例如,一个简单的移动平均线指标组件配置如下:
```json
{
"id": "sma20",
"type": "SMA",
"params": {
"period": 20,
"column": "Close"
}
}
```
### 信号组件(Signals)
信号组件负责根据指标值生成交易信号。它们可以比较不同的指标,检测交叉点,或者应用其他逻辑规则来确定何时买入或卖出。
例如,一个检测价格是否高于移动平均线的信号组件配置如下:
```json
{
"id": "price_above_sma",
"type": "GreaterThan",
"inputs": [
{ "column": "Close" },
{ "ref": "sma20" }
]
}
```
### 逻辑组合(Logic Combinations)
逻辑组合器允许您将多个信号组合在一起,使用AND、OR、NOT等逻辑操作符。这使您可以创建复杂的条件,如"当RSI低于30且价格高于20日均线时买入"。
例如,一个组合两个信号的逻辑组件配置如下:
```json
{
"id": "buy_condition",
"type": "And",
"inputs": [
{ "ref": "rsi_oversold" },
{ "ref": "price_above_sma" }
]
}
```
### 资金管理策略(Capital Strategy)
资金管理策略决定了每次交易投入多少资金。系统提供了几种不同的资金管理策略,可以根据不同的需求选择合适的策略。
例如,一个基于总资产百分比的资金管理策略配置如下:
```json
"capital_strategy": {
"name": "PercentCapitalStrategy",
"params": {
"initial_capital": 100000,
"percents": 20,
"max_positions": null
}
}
```
这个策略会将总资产的20%分配给每个交易标的,`max_positions`参数可以限制最大持仓数量。
## 3. 第一个原语策略:简单移动平均线交叉
让我们从一个简单的策略开始:使用短期移动平均线和长期移动平均线的交叉来生成交易信号。这是一个经典的趋势跟踪策略。
### 策略思路
- 当短期移动平均线(如20日均线)上穿长期移动平均线(如50日均线)时买入
- 当短期移动平均线下穿长期移动平均线时卖出
- 使用SPY(S&P 500 ETF)和QQQ(纳斯达克100 ETF)作为交易标的
### 原语策略配置代码
以下是这个策略的**原语策略配置**(仅包含前端原语策略页面需要的部分):
```json
{
"trade_strategy": {
"indicators": [
{
"id": "sma20",
"type": "SMA",
"params": {
"period": 20,
"column": "Close"
}
},
{
"id": "sma50",
"type": "SMA",
"params": {
"period": 50,
"column": "Close"
}
}
],
"signals": [
{
"id": "sma20_cross_above_sma50",
"type": "Crossover",
"params": { "mode": "simple" },
"inputs": [
{ "ref": "sma20" },
{ "ref": "sma50" }
]
},
{
"id": "sma20_cross_below_sma50",
"type": "Crossunder",
"params": { "mode": "simple" },
"inputs": [
{ "ref": "sma20" },
{ "ref": "sma50" }
]
}
],
"outputs": {
"buy_signal": "sma20_cross_above_sma50",
"sell_signal": "sma20_cross_below_sma50"
}
}
}
```
**说明:** 这个策略不需要`market_indicators`,因为所有指标都基于当前标的的OHLC数据。
### 完整组合配置示例
如果您需要完整的组合配置(用于API调用或完整回测),可以参考以下格式:
```json
{
"name": "简单均线交叉策略",
"code": "simple_ma_cross",
"description": "使用20日均线和50日均线的交叉生成交易信号",
"strategy_definition": {
// 上面的原语策略配置 + 资金管理策略
"capital_strategy": {
"name": "PercentCapitalStrategy",
"params": {
"initial_capital": 100000,
"percents": 20
}
}
},
"symbols": [
{"symbol": "SPY", "name": "S&P 500 ETF"},
{"symbol": "QQQ", "name": "Nasdaq ETF"}
],
"start_date": "2018-01-01",
"currency": "USD",
"market": "US",
"commission": 0.0001,
"update_time": "08:00"
}
```
### 配置解析
让我们逐步解析这个配置:
1. **基本信息**:
- `name`:策略名称
- `code`:策略代码,用于在系统中唯一标识这个策略
- `description`:策略描述
- `symbols`:交易标的列表
- `start_date`:回测起始日期
2. **指标定义**:
- 定义了两个移动平均线指标:20日均线和50日均线
- 每个指标都有一个唯一的ID,用于在后续的信号定义中引用
3. **信号定义**:
- `sma20_cross_above_sma50`:检测20日均线上穿50日均线
- `sma20_cross_below_sma50`:检测20日均线下穿50日均线
- 每个信号通过`inputs`引用之前定义的指标
4. **输出映射**:
- `buy_signal`:将`sma20_cross_above_sma50`信号映射为买入信号
- `sell_signal`:将`sma20_cross_below_sma50`信号映射为卖出信号
5. **资金管理**:
- 使用百分比资金管理策略
- 初始资金10万
- 每个标的分配20%的资金
## 4. 第二个原语策略:RSI超买超卖
接下来,让我们尝试一个基于RSI(相对强弱指数)的策略。RSI是一个常用的动量指标,用于识别市场的超买或超卖状态。
### 策略思路
- 当RSI低于30(超卖状态)时买入
- 当RSI高于70(超买状态)时卖出
- 使用与第一个策略相同的交易标的
### 原语策略配置代码
以下是这个策略的**原语策略配置**:
```json
{
"trade_strategy": {
"indicators": [
{
"id": "rsi",
"type": "RSI",
"params": {
"period": 14,
"column": "Close"
}
},
{
"id": "buy_threshold",
"type": "Constant",
"params": {
"value": 30
}
},
{
"id": "sell_threshold",
"type": "Constant",
"params": {
"value": 70
}
}
],
"signals": [
{
"id": "rsi_oversold",
"type": "LessThan",
"inputs": [
{ "ref": "rsi" },
{ "ref": "buy_threshold" }
]
},
{
"id": "rsi_overbought",
"type": "GreaterThan",
"inputs": [
{ "ref": "rsi" },
{ "ref": "sell_threshold" }
]
}
],
"outputs": {
"buy_signal": "rsi_oversold",
"sell_signal": "rsi_overbought"
}
}
}
```
**说明:** 这个策略同样不需要`market_indicators`,因为只使用了基于当前标的OHLC数据的指标。
### 配置解析
让我们重点解析与第一个策略不同的部分:
1. **RSI指标**:
- 使用14天周期的RSI指标
- RSI是一个范围在0-100之间的指标,通常用于衡量价格动量
2. **常量指标**:
- 定义了两个常量指标:`buy_threshold`(值为30)和`sell_threshold`(值为70)
- 这些常量用于与RSI值进行比较
3. **信号定义**:
- `rsi_oversold`:检测RSI是否低于30(超卖状态)
- `rsi_overbought`:检测RSI是否高于70(超买状态)
- 使用`LessThan`和`GreaterThan`信号类型进行比较
4. **输出映射**:
- `buy_signal`:将`rsi_oversold`信号映射为买入信号
- `sell_signal`:将`rsi_overbought`信号映射为卖出信号
## 5. 组合多个信号:RSI + 移动平均线
现在,让我们尝试组合多个信号,创建一个更复杂的策略。我们将结合RSI和移动平均线,要求同时满足多个条件才生成交易信号。
### 策略思路
- 当RSI低于30(超卖状态)**且**价格高于20日均线时买入
- 当RSI高于70(超买状态)**或**价格低于20日均线时卖出
- 这种组合既考虑了价格动量(RSI),又考虑了价格趋势(移动平均线)
### 原语策略配置代码
```json
{
"trade_strategy": {
"indicators": [
{
"id": "rsi",
"type": "RSI",
"params": {
"period": 14,
"column": "Close"
}
},
{
"id": "sma20",
"type": "SMA",
"params": {
"period": 20,
"column": "Close"
}
},
{
"id": "buy_threshold",
"type": "Constant",
"params": {
"value": 30
}
},
{
"id": "sell_threshold",
"type": "Constant",
"params": {
"value": 70
}
}
],
"signals": [
{
"id": "rsi_oversold",
"type": "LessThan",
"inputs": [
{ "ref": "rsi" },
{ "ref": "buy_threshold" }
]
},
{
"id": "rsi_overbought",
"type": "GreaterThan",
"inputs": [
{ "ref": "rsi" },
{ "ref": "sell_threshold" }
]
},
{
"id": "price_above_sma",
"type": "GreaterThan",
"inputs": [
{ "column": "Close" },
{ "ref": "sma20" }
]
},
{
"id": "price_below_sma",
"type": "LessThan",
"inputs": [
{ "column": "Close" },
{ "ref": "sma20" }
]
},
{
"id": "buy_condition",
"type": "And",
"inputs": [
{ "ref": "rsi_oversold" },
{ "ref": "price_above_sma" }
]
},
{
"id": "sell_condition",
"type": "Or",
"inputs": [
{ "ref": "rsi_overbought" },
{ "ref": "price_below_sma" }
]
}
],
"outputs": {
"buy_signal": "buy_condition",
"sell_signal": "sell_condition"
}
}
}
```
**说明:** 这个策略仍然不需要`market_indicators`,因为所有指标都是基于当前标的的数据。
### 配置解析
这个策略结合了前两个策略的元素,并添加了逻辑组合器。让我们重点解析新增的部分:
1. **信号组合**:
- `buy_condition`:使用`And`逻辑组合器,要求同时满足`rsi_oversold`和`price_above_sma`两个条件
- `sell_condition`:使用`Or`逻辑组合器,只要满足`rsi_overbought`或`price_below_sma`任一条件即可
2. **逻辑组合器的工作原理**:
- `And`组合器:只有当所有输入信号都为真时,输出信号才为真
- `Or`组合器:只要有一个输入信号为真,输出信号就为真
- `Not`组合器(本例未使用):将输入信号的真假值取反
3. **输出映射**:
- `buy_signal`:将组合后的`buy_condition`信号映射为买入信号
- `sell_signal`:将组合后的`sell_condition`信号映射为卖出信号
## 6. 使用市场指标的策略示例
让我们看一个需要使用`market_indicators`的策略示例。这个策略使用沪深300指数的趋势来决定是否买入股票。
### 原语策略配置代码
```json
{
"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": [
{
"id": "rsi",
"type": "RSI",
"params": {
"period": 14,
"column": "Close"
}
},
{
"id": "rsi_threshold",
"type": "Constant",
"params": {
"value": 30
}
}
],
"signals": [
{
"id": "market_trend_up",
"type": "GreaterThan",
"inputs": [
{
"market": "000300.SH",
"transformer": "hs300_raw"
},
{
"market": "000300.SH",
"transformer": "hs300_ma200"
}
]
},
{
"id": "rsi_oversold",
"type": "LessThan",
"inputs": [
{ "ref": "rsi" },
{ "ref": "rsi_threshold" }
]
},
{
"id": "buy_signal",
"type": "And",
"inputs": [
{ "ref": "market_trend_up" },
{ "ref": "rsi_oversold" }
]
}
],
"outputs": {
"buy_signal": "buy_signal",
"sell_signal": "rsi_oversold"
}
}
}
```
**重要说明:**
- 因为`trade_strategy`中使用了市场指标引用(`{"market": "000300.SH", "transformer": "hs300_raw"}`),所以**必须**包含`market_indicators`配置
- 如果缺少`market_indicators`,即使前端校验通过,回测也会失败
- `market_indicators`定义了可用的市场指标及其转换器
## 7. 资金管理策略说明
**注意:** 在原语策略配置中,您不需要配置资金管理策略。资金管理策略是在创建完整组合时设置的。
### 何时需要配置资金管理
资金管理策略在创建完整投资组合时配置,包括:
- 每次交易的资金分配比例
- 最大持仓数量限制
- 定投策略等
在原语策略开发阶段,您专注于交易逻辑,无需关心资金管理细节。
## 8. 调试与优化
在开发原语策略时,您可能会遇到各种问题,如信号不触发、交易过于频繁、配置错误等。
### 获取详细帮助
由于调试和故障排除涉及的内容较为复杂,我们为您准备了两个专门的详细指南:
#### 📚 入门级故障排除
**[策略原语系统故障排除指南](/docs/primitives/troubleshooting)**
适合初学者,涵盖:
- 常见配置错误及解决方案
- 数据和信号问题诊断
- 策略行为异常排查
- 性能优化技巧
- 系统调试方法
- 组件使用陷阱避免
#### 🔬 高级信号分析
**[原语组件高级故障排除指南](/docs/primitives/advanced/troubleshooting)**
适合有经验的用户,教您如何编写SQL进行复杂分析:
- 策引平台信号分析工具详细使用方法
- 专业SQL查询语句编写技巧
- 信号数据库下载和本地分析
- 深度验证中间指标计算正确性
- 信号切换逻辑和交易频率分析
- 实际案例分析和问题诊断
### 快速检查清单
遇到问题时,请首先检查:
1. ✅ **配置格式**:JSON语法是否正确
2. ✅ **组件引用**:所有ref引用的组件是否已定义
3. ✅ **市场指标依赖**:如使用市场指标引用,是否包含market_indicators配置
4. ✅ **参数类型**:数值参数是否为数字类型(不带引号)
5. ✅ **输入数量**:信号组件的输入数量是否正确
### 简单调试方法
**查看计算结果**:在outputs中添加中间指标,这些数据会写入信号数据库供分析
```json
"outputs": {
"buy_signal": "buy_signal",
"sell_signal": "sell_signal",
"indicators": [
{ "id": "rsi_indicator", "output_name": "rsi" },
{ "id": "price_above_sma", "output_name": "trend_up" }
]
}
```
**信号数据库分析**:
- 所有中间指标和信号都会存储在SQLite数据库中
- 可以下载信号数据库并运行SQL查询分析:
- 检查中间指标计算是否正确
- 验证最终信号是否符合逻辑
- 分析信号切换的合理性
**内置分析工具**:
策引平台为每个组合提供了**策略交易信号深度分析**功能,内置了8个专业SQL查询工具:
**🔴 关键分析**:
- 🏥 **数据健康检查** - 验证信号数据的完整性和有效性
- 🎯 **信号有效性分析** - 评估买卖信号的预测准确性和盈利能力
- ⚠️ **风险信号识别** - 识别策略中的潜在风险因素
- 📈 **波动性分析** - 分析各标的价格波动性,识别高风险资产和杠杆特征
**🟡 重要分析**:
- ⏰ **交易时机分析** - 了解策略的交易频率和节奏特征
- 🌍 **市场适应性分析** - 策略在不同市场环境下的表现评估
**🔵 辅助分析**:
- 🔄 **信号切换逻辑检查** - 验证信号状态转换的合理性
- 📊 **信号分布分析** - 分析信号类型分布和策略风格
**查看示例**:可以访问[策引组合示例](https://www.myinvestpilot.com/portfolios/myinvestpilot_us_global/),点击组合页面的"策略交易信号深度分析"了解详细功能。
**遇到问题?**
- **初学者**:参考[入门故障排除指南](/docs/primitives/troubleshooting)
- **进阶用户**:学习[高级SQL分析技巧](/docs/primitives/advanced/troubleshooting)进行深度诊断
- **快速分析**:使用组合页面内置的8个SQL分析工具自动检查策略
## 9. 下一步学习
恭喜您完成了原语策略的快速入门指南!以下是一些建议的下一步学习内容:
1. **探索更多指标**:了解系统支持的其他技术指标,如布林带、MACD、KD等
2. **学习高级组合**:尝试创建更复杂的信号组合,如多重条件、时间过滤等
3. **研究资金管理**:深入了解不同资金管理策略的优缺点和适用场景
4. **回测分析**:学习如何分析回测结果,评估策略的优劣
### 推荐阅读
- [架构概述](/docs/primitives/architecture):了解原语策略系统的整体架构
- [指标原语详解](/docs/primitives/indicators):详细介绍系统支持的所有指标
- [信号原语详解](/docs/primitives/signals):深入了解信号组件的工作原理
- [组合模式](/docs/primitives/composition):学习如何创建复杂的信号组合
- [策略示例](/docs/primitives/examples):查看更多策略示例
- [故障排除](/docs/primitives/troubleshooting):解决常见问题的指南
- [市场指标](/docs/primitives/advanced/market-indicators):了解市场指标的使用
- [高级故障排除](/docs/primitives/advanced/troubleshooting):高级故障排除技巧
- [策略优化](/docs/primitives/advanced/optimization):学习如何优化策略性能
### 实践练习
尝试修改本指南中的示例策略,创建您自己的交易策略。您可以:
1. 更改指标参数(如RSI的周期、移动平均线的长度)
2. 尝试不同的指标组合(如MACD、布林带)
3. 调整买入和卖出条件
4. 测试不同的资金管理策略
通过实践,您将更好地理解原语策略系统的工作原理,并能够创建适合自己风险偏好的交易策略。
--------------------------------------------------------------------------------
AI辅助策略开发 (ai-assisted-development.md)
--------------------------------------------------------------------------------
# AI辅助原语策略开发指南
本文档介绍如何利用大语言模型(如Claude、GPT等)辅助开发、调试和优化策引原语策略。通过AI辅助,您可以更高效地:
- **生成策略**: 用自然语言描述需求,AI帮你生成JSON配置
- **调试诊断**: AI分析回测数据,找出策略问题
- **优化迭代**: 基于数据分析结果,AI提供优化建议
## 概述:AI辅助工作流
```mermaid
graph TB
A[1️⃣ 策略生成
用户描述需求
AI生成JSON配置] --> B[2️⃣ 回测验证
策引平台回测
获取结果数据]
B --> C[3️⃣ 数据分析
下载SQLite数据库
AI执行SQL分析]
C --> D[4️⃣ 迭代优化
AI提供优化建议
生成改进版本]
D -.循环迭代.-> A
style A fill:#e1f5e1
style B fill:#e3f2fd
style C fill:#fff3e0
style D fill:#fce4ec
```
## 准备工作:让AI理解原语系统
### 方法一:直接提供 llm.txt(推荐)
策引提供了专为AI设计的参考文档,包含了所有原语的定义、语法和示例。
#### llm-quickstart.txt - Schema驱动快速上手指南 ⭐ 推荐
**在线地址**:
```
https://docs.myinvestpilot.com/primitives/_llm/llm-quickstart.txt
```
**特点**:
- ✅ **架构优先** - 前置 ABSOLUTE PROHIBITIONS,防止常见LLM错误(内联定义等)
- ✅ **渐进式学习** - 12个Level从简单到复杂,覆盖97.5%原语(39/40)
- ✅ **实战验证** - 所有策略来自真实回测案例,包含性能数据
- ✅ **模型约束** - 包含Gemini/ChatGPT实际错误示例作为反面教材
- ✅ **紧凑高效** - 仅74KB,token使用量是完整版的1/5
- 📊 **适用模型** - GPT-4, Claude, Gemini, DeepSeek, Llama 3.3等所有主流模型
- 💰 **免费选项** - 可通过 OpenRouter 使用免费的 Llama 3.3 70B 模型
**使用示例**:
```
请先阅读这份原语策略参考文档,然后帮我编写策略:
https://docs.myinvestpilot.com/primitives/_llm/llm-quickstart.txt
我想要一个双均线交叉策略,20日均线上穿60日均线买入,下穿卖出。
```
💡 **提示**:
- 💰 没有GPT/Claude订阅?使用 [OpenRouter](https://openrouter.ai/) 的免费 **Llama 3.3 70B** 模型
- ⚠️ 如果模型无法访问URL,下载文件后直接复制内容到对话框
- ✅ 经过验证:Gemini、ChatGPT、Llama 3.3 在使用此文档后错误率从100%降到0
### 方法二:使用官方 JSON Schema(高级)
如果你需要进行**严格的类型验证**或**自动化工具开发**,策引提供了引擎自动生成的官方 JSON Schema:
**Schema 地址**:
```
https://media.i365.tech/myinvestpilot/primitives_schema.json
```
**特点**:
- ✅ **权威准确** - 由策引引擎自动生成,与实际运行版本完全一致
- ✅ **完整类型定义** - 包含所有原语类型、参数、默认值、约束条件
- ✅ **机器可读** - 适合 IDE 自动补全、类型检查、代码生成工具
**使用场景**:
1. **编辑器集成** - VS Code、WebStorm 等可以基于 Schema 提供自动补全
2. **策略验证** - 在提交回测前,用 Schema 验证 JSON 配置的正确性
3. **工具开发** - 如果你要开发策略生成器、配置编辑器等工具
**示例:在 VS Code 中启用自动补全**
```json
{
"$schema": "https://media.i365.tech/myinvestpilot/primitives_schema.json",
"market_indicators": {
// VS Code 会基于 Schema 提供智能提示
}
}
```
**何时使用 llm-quickstart.txt vs llm-core/full vs JSON Schema**:
| 需求 | 推荐方案 | 原因 |
|------|----------|------|
| AI 生成策略 | llm-quickstart.txt | Schema驱动,架构约束清晰,防止常见错误 |
| AI 调试分析 | llm-quickstart.txt | 包含SQL诊断和优化指导 |
| RAG知识库 | llm-core.txt | 完整定义,适合检索 |
| 深入学习案例 | llm-full.txt | 17个真实策略详细分析 |
| IDE 自动补全 | JSON Schema | 提供精确的类型定义 |
| 策略验证工具 | JSON Schema | 可编程校验所有约束 |
| 开发自动化工具 | JSON Schema | 完整的 API 规范 |
💡 **最佳实践**:AI 辅助开发时优先使用 `llm-quickstart.txt`,它专为代码生成优化,经过Gemini和ChatGPT验证,错误率从100%降到0。只有在需要严格类型校验或工具开发时才使用 JSON Schema。
### 方法三:配置为AI Skill(推荐)
如果你使用支持Skill/Tool的AI助手(如Claude Code、自定义Agent),可以将原语策略开发配置为一个专用技能。
**Claude Code skill 示例**:
在 `.claude/skills/` 目录创建 `plutus-primitive.md`:
```markdown
# 策引原语策略开发 Skill
## 触发条件
当用户想要:
- 创建/编写投资策略
- 生成原语策略配置
- 分析策略回测数据
- 优化交易策略
## 参考文档
首先获取原语策略参考:
WebFetch https://docs.myinvestpilot.com/primitives/_llm/llm-quickstart.txt
## 工作流程
### 1. 策略生成
- 理解用户需求
- 生成符合JSON Schema的原语配置
- 解释策略逻辑
### 2. 数据分析
当用户提供sqlite数据库文件时:
- 使用SQL分析 trade_signals 表
- 检查信号健康度
- 验证信号切换逻辑
- 评估策略表现
### 3. 优化建议
基于分析结果提供:
- 参数调整建议
- 信号组合优化
- 风险控制改进
```
### 方法四:MCP Server(高级)
对于需要深度集成的场景,可以开发MCP Server将原语生成、回测、分析封装为工具函数。
---
## 其他 llm.txt 版本
除了推荐的 **llm-quickstart.txt**,还有两个版本适用于特定场景:
**llm-core.txt(241 KB)**
- 📚 适合RAG系统知识库和深度文档检索
- 📖 包含所有原语的完整定义和详细参数说明
- 🔗 [llm-core.txt](https://docs.myinvestpilot.com/primitives/_llm/llm-core.txt)
**llm-full.txt(411 KB)**
- 📊 包含17个真实策略的完整案例分析
- 💡 详细的设计思路和复杂场景最佳实践
- 🔗 [llm-full.txt](https://docs.myinvestpilot.com/primitives/_llm/llm-full.txt)
---
## 第一步:用AI生成策略
### 示例对话
**用户**:
> 帮我创建一个RSI超买超卖策略。RSI低于30时买入,高于70时卖出。同时要求价格在200日均线之上才能买入(过滤熊市)。
**AI**(在阅读llm.txt后):
> 我为你设计了一个带均线过滤的RSI策略:
```json
{
"trade_strategy": {
"indicators": [
{"id": "rsi", "type": "RSI", "params": {"period": 14}},
{"id": "sma200", "type": "SMA", "params": {"period": 200, "column": "Close"}},
{"id": "threshold_30", "type": "Constant", "params": {"value": 30}},
{"id": "threshold_70", "type": "Constant", "params": {"value": 70}}
],
"signals": [
{
"id": "rsi_oversold",
"type": "LessThan",
"inputs": [{"ref": "rsi"}, {"ref": "threshold_30"}]
},
{
"id": "rsi_overbought",
"type": "GreaterThan",
"inputs": [{"ref": "rsi"}, {"ref": "threshold_70"}]
},
{
"id": "price_above_ma",
"type": "GreaterThan",
"inputs": [{"column": "Close"}, {"ref": "sma200"}]
},
{
"id": "buy_condition",
"type": "And",
"inputs": [{"ref": "rsi_oversold"}, {"ref": "price_above_ma"}]
}
],
"outputs": {
"buy_signal": "buy_condition",
"sell_signal": "rsi_overbought",
"indicators": [
{"id": "rsi", "output_name": "rsi"},
{"id": "sma200", "output_name": "ma200"}
]
}
}
}
```
> **策略逻辑**:
> - 买入条件:RSI < 30(超卖)且 价格 > 200日均线(牛市)
> - 卖出条件:RSI > 70(超买)
> - 输出RSI和MA200用于后续分析
### 生成技巧
1. **描述清晰**:告诉AI你的交易思路、买卖条件、参数偏好
2. **指定市场**:美股、A股可能需要不同的参数设置
3. **说明用途**:趋势跟踪、均值回归、动量策略等
4. **提及风控**:止损条件、仓位控制需求
## 第二步:回测并获取数据
### 在策引平台回测
1. 登录 [策引平台](https://www.myinvestpilot.com)
2. 创建/编辑投资组合
3. 在"原语策略"页面粘贴AI生成的JSON配置
4. 选择标的、时间范围
5. 运行回测
### 下载回测数据
策引提供两种数据库,推荐使用**组合表现数据库**(无需登录,包含完整交易记录):
**下载地址**:
```
https://media.i365.tech/myinvestpilot/portfolios/[组合ID]/[组合ID]_portfolio.db
```
**包含9张主要数据表**:
- `trade_records` - 交易流水
- `position_records` - 每日持仓
- `net_values` - 每日净值
- `portfolio_status` - 组合摘要(CAGR、夏普比率等)
- `capital_records` - 资金记录
- `benchmark_index` - 基准对比
- 以及其他收益归因和对比表
💡 **何时使用**:90%的分析需求使用组合表现数据库即可满足。只有需要调试原语信号逻辑时,才使用信号数据库(需登录下载)。
详细的SQL查询方法请参考:[策略诊断SQL查询手册](./advanced/troubleshooting.md#sql诊断查询)
## 第三步:AI分析回测数据
下载数据库后,让AI分析交易表现、诊断问题、发现优化机会。
**AI对话示例**:
```
我有一个策引组合的表现数据库,请帮我分析:
1. 交易频率是否合理?
2. 买卖时机的成功率如何?
3. 有哪些可以优化的地方?
[上传 custom_lkeh0lxz_portfolio.db 文件]
```
**常用分析维度**:
- 交易频率和胜率分析(`trade_records`表)
- 持仓周期分布(`position_records`表)
- 风险收益指标(`portfolio_status`表直接获取)
- 回撤分析和净值曲线(`net_values`表)
详细的SQL查询模板和分析方法,请参考:[策略诊断SQL查询手册](./advanced/troubleshooting.md#sql诊断查询)
### 实战案例参考
想看完整的AI辅助决策流程?参考:[SOXL杠杆ETF策略实战案例](./advanced/leveraged-etf-soxl-strategy.md)
该案例完整记录了从策略设计、回测分析、AI诊断到实盘决策的全过程。
## 第四步:迭代优化
### 优化工作流
```
分析结果 → AI提出假设 → 修改策略 → 重新回测 → 再次分析 → 循环
```
### 常见优化方向
**1. 参数调优**
```
用户:买入信号太少了,能不能放宽一点?
AI:可以将RSI阈值从30调整到35,或将均线周期从200调整到150。
```
**2. 信号确认**
```
用户:假信号太多,能加一个确认机制吗?
AI:可以使用Lag原语要求连续2天满足条件:
{
"id": "condition_yesterday",
"type": "Lag",
"params": {"periods": 1, "fill_value": 0},
"inputs": [{"ref": "condition_today"}]
}
```
**3. 动态仓位**
```
用户:能根据RSI动态调整仓位吗?
AI:可以使用LinearScaleWeight原语:
{
"id": "dynamic_weight",
"type": "LinearScaleWeight",
"params": {"min_indicator": 30, "max_indicator": 70, "min_weight": 1.0, "max_weight": 0.3}
}
```
### 优化对话示例
**用户**:
> 策略在2022年熊市亏损严重,能不能加一个市场过滤?
**AI**:
> 可以引入VIX作为市场恐慌指标。当VIX处于历史高位时减少交易:
```json
{
"market_indicators": {
"indicators": [{"code": "VIX"}],
"transformers": [
{
"name": "vix_percentile",
"type": "PercentileRankTransformer",
"params": {"indicator": "VIX", "lookback": 252, "field": "Close"}
}
]
},
"trade_strategy": {
"signals": [
{
"id": "low_fear",
"type": "LessThan",
"inputs": [
{"market": "VIX", "transformer": "vix_percentile"},
{"type": "Constant", "value": 80}
]
},
{
"id": "final_buy",
"type": "And",
"inputs": [{"ref": "original_buy"}, {"ref": "low_fear"}]
}
]
}
}
```
> 这样只有在VIX低于历史80%分位时才会买入,过滤掉了极端恐慌期。
## 完整案例:从需求到优化
### 第1轮:初始策略
**用户需求**:
> 我想要一个简单的双均线策略,适合美股大盘ETF。
**AI生成**:
```json
{
"trade_strategy": {
"indicators": [
{"id": "sma20", "type": "SMA", "params": {"period": 20}},
{"id": "sma60", "type": "SMA", "params": {"period": 60}}
],
"signals": [
{"id": "buy", "type": "Crossover", "inputs": [{"ref": "sma20"}, {"ref": "sma60"}]},
{"id": "sell", "type": "Crossunder", "inputs": [{"ref": "sma20"}, {"ref": "sma60"}]}
],
"outputs": {
"buy_signal": "buy",
"sell_signal": "sell"
}
}
}
```
### 第2轮:数据分析
回测后,AI分析sqlite数据库发现:
- 交易69次,胜率52%
- 发现多次 B→S 快速切换(震荡市被反复"抽耳光")
- 2020年3月熊市中错过了反弹
### 第3轮:优化
**AI建议**:增加RSI动态仓位控制,在震荡市减少仓位
```json
{
"trade_strategy": {
"indicators": [
{"id": "sma20", "type": "SMA", "params": {"period": 20}},
{"id": "sma60", "type": "SMA", "params": {"period": 60}},
{"id": "rsi", "type": "RSI", "params": {"period": 14}}
],
"signals": [
{"id": "buy", "type": "Crossover", "inputs": [{"ref": "sma20"}, {"ref": "sma60"}]},
{"id": "sell", "type": "Crossunder", "inputs": [{"ref": "sma20"}, {"ref": "sma60"}]},
{
"id": "weight",
"type": "LinearScaleWeight",
"inputs": [{"ref": "rsi"}],
"params": {"min_indicator": 40, "max_indicator": 75, "min_weight": 1.0, "max_weight": 0.3, "clip": true}
}
],
"outputs": {
"buy_signal": "buy",
"sell_signal": "sell",
"target_weight": "weight"
}
}
}
```
### 第4轮:验证优化效果
重新回测后AI分析:
- 交易次数从69次降到28次
- 收益从151%提升到1178%
- 单次交易贡献从2.2%提升到42.1%
## 最佳实践
### 1. 提供足够上下文
```
❌ "帮我写一个策略"
✅ "帮我写一个适合美股科技ETF的趋势跟踪策略,
使用双均线交叉,要有止损机制,
我的风险偏好是中等"
```
### 2. 迭代式开发
不要期望一次就得到完美策略,应该:
1. 先生成基础版本
2. 回测看效果
3. 分析数据找问题
4. 针对性优化
5. 重复2-4步
### 3. 保持outputs完整
在策略中输出中间指标,方便后续分析:
```json
"outputs": {
"buy_signal": "buy",
"sell_signal": "sell",
"indicators": [
{"id": "rsi", "output_name": "rsi"},
{"id": "sma20", "output_name": "ma_short"},
{"id": "sma60", "output_name": "ma_long"}
]
}
```
### 4. 利用AI的SQL能力
AI擅长编写复杂SQL查询。可以直接说:
> "帮我写一个SQL,分析每次买入后10天内的最大回撤"
### 5. 版本管理
保存每个版本的策略配置和分析结果,方便对比和回溯。
## 相关资源
- **llm.txt 参考文档**:
- 快速上手版: [llm-quickstart.txt](https://docs.myinvestpilot.com/primitives/_llm/llm-quickstart.txt) ⭐ 推荐 - Schema驱动,架构约束清晰,74KB
- **其他版本**(用于RAG或深度学习):
- 核心版: [llm-core.txt](https://docs.myinvestpilot.com/primitives/_llm/llm-core.txt) - 适合RAG检索和知识增强,241KB
- 完整版: [llm-full.txt](https://docs.myinvestpilot.com/primitives/_llm/llm-full.txt) - 包含详细案例分析,411KB
- **可视化编辑器**: [https://www.myinvestpilot.com/primitives-editor/](https://www.myinvestpilot.com/primitives-editor/)
- **信号分析手册**: [https://www.myinvestpilot.com/help/signal-analysis/](https://www.myinvestpilot.com/help/signal-analysis/)
- **高级故障排除**: [高级调试指南](/docs/primitives/advanced/troubleshooting)
- **策略优化指南**: [优化指南](/docs/primitives/advanced/optimization)
- **动态仓位案例**: [动态仓位策略](/docs/primitives/advanced/dynamic-position-strategy)
---
**提示**:AI是辅助工具,最终的投资决策需要您自己判断。回测表现不代表未来收益,请谨慎评估风险。
--------------------------------------------------------------------------------
架构概述 (architecture.md)
--------------------------------------------------------------------------------
# 原语策略系统
## 什么是原语策略
原语策略系统是策引平台的核心功能,它将复杂的投资策略分解为简单易懂的"积木块",让普通投资者能够理解、定制和组合投资策略。
### 💡 核心理念
- **模块化设计**:将策略分解为小的功能模块
- **组合创新**:通过不同模块组合创造新策略
- **透明易懂**:每个组件的逻辑都清晰可见
- **灵活配置**:无需编程即可调整策略参数
---
## 原语组件类型
### 1. 技术指标原语
**功能**:计算各种技术分析指标,为交易决策提供数据支持。
**常用指标**:
- **移动平均线(MA)**:反映价格趋势方向
- **相对强弱指标(RSI)**:判断超买超卖状态
- **布林带(Bollinger Bands)**:识别价格波动区间
- **MACD指标**:分析价格动量变化
**实用价值**:
- 提供客观的市场分析工具
- 帮助识别买卖时机
- 减少主观判断的影响
### 2. 交易信号原语
**功能**:基于技术指标或价格数据生成具体的买卖信号。
**常用信号**:
- **价格突破**:价格突破关键阻力或支撑位
- **指标交叉**:两条均线的金叉死叉
- **数值比较**:指标值与固定阈值比较
- **逻辑组合**:多个条件的AND/OR组合
**信号作用**:
- 将复杂分析转化为明确决策
- 提供精确的进出场时机
- 支持多条件组合判断
---
## 策略构建过程
### 1. 策略设计思路
**基本步骤**:
1. **确定投资目标**:明确期望收益和风险水平
2. **选择分析方法**:决定使用哪些技术指标
3. **设定交易规则**:定义买入和卖出条件
4. **组合验证**:通过回测验证策略效果
### 2. 原语组合逻辑
**组合原则**:
- **指标计算**:首先计算所需的技术指标
- **信号生成**:基于指标生成交易信号
- **逻辑组合**:将多个信号按逻辑规则组合
- **最终决策**:形成明确的买卖决策
**示例流程**:
1. 计算5日和20日移动平均线
2. 判断短期均线是否上穿长期均线
3. 同时检查RSI是否不在超买区域
4. 两个条件都满足时生成买入信号
### 3. 策略状态管理
**交易状态**:
- **空仓状态**:未持有任何资产
- **买入状态**:根据信号买入资产
- **持有状态**:保持当前持仓
- **卖出状态**:根据信号卖出资产
**状态转换**:
- 空仓 → 买入信号 → 买入 → 持有
- 持有 → 卖出信号 → 卖出 → 空仓
---
## 策略类型与应用
### 1. 趋势跟踪策略
**基本思路**:跟随市场主要趋势进行投资。
**常用原语**:
- 移动平均线系统
- 趋势线突破信号
- 动量指标确认
**适用场景**:
- 趋势明显的市场环境
- 中长期投资周期
- 追求稳定收益的投资者
### 2. 反转策略
**基本思路**:在市场过度反应时进行反向操作。
**常用原语**:
- RSI超买超卖信号
- 布林带边界触碰
- 价格偏离均值程度
**适用场景**:
- 震荡市场环境
- 短期交易机会
- 擅长把握市场情绪的投资者
### 3. 动量策略
**基本思路**:追随价格动量强劲的资产。
**常用原语**:
- 价格相对强度比较
- 成交量确认信号
- 突破后的持续性判断
**适用场景**:
- 强势上升市场
- 成长型投资风格
- 追求高收益的投资者
---
## 策略定制与优化
### 1. 参数调整
**可调整要素**:
- **时间周期**:如均线的计算天数
- **阈值设定**:如RSI的超买超卖线
- **组合权重**:多个信号的重要性权重
- **止损止盈**:风险控制参数设置
**调整原则**:
- 基于历史数据测试效果
- 考虑不同市场环境适应性
- 平衡收益与风险的关系
### 2. 策略验证
**验证方法**:
- **历史回测**:在历史数据上测试策略
- **风险分析**:评估最大回撤等风险指标
- **稳定性测试**:检验不同时期的表现
- **压力测试**:极端市场条件下的表现
### 3. 持续优化
**优化策略**:
- 定期回顾策略表现
- 根据市场变化调整参数
- 结合新的市场洞察改进逻辑
- 保持策略的动态适应性
---
## 使用建议
### 1. 新手用户
**学习路径**:
1. **从简单开始**:先理解单一指标的含义
2. **观察效果**:通过回测了解指标的作用
3. **逐步组合**:学会组合多个指标
4. **实践验证**:在模拟环境中测试策略
**注意事项**:
- 不要一开始就构建过于复杂的策略
- 充分理解每个组件的作用原理
- 重视风险管理和资金控制
### 2. 经验用户
**进阶应用**:
- 创建多层次的信号过滤系统
- 结合不同时间周期的分析
- 开发适应不同市场环境的策略
- 构建策略组合分散风险
**创新思路**:
- 尝试非传统的指标组合
- 结合基本面分析要素
- 开发适合特定行业的策略
### 3. 专业投资者
**高级功能**:
- 构建复杂的多因子模型
- 开发自适应参数调整机制
- 创建市场中性策略
- 实现动态风险预算管理
---
## 常见问题
### Q: 原语策略适合什么样的投资者?
A: 原语策略适合希望系统化投资、减少情绪化决策的投资者,特别是想要理解策略逻辑但不具备编程能力的用户。
### Q: 如何选择合适的原语组合?
A: 建议从简单的组合开始,如单一均线策略,然后逐步添加确认信号,通过回测验证每个组件的贡献。
### Q: 策略失效了怎么办?
A: 策略失效是正常现象,需要定期评估策略表现,根据市场环境变化调整参数或更换策略逻辑。
### Q: 可以同时使用多个策略吗?
A: 可以,建议使用相关性较低的策略组合,以实现风险分散和收益优化。
### Q: 原语策略支持哪些类型的指标?
A: 目前原语策略系统支持的原语组件都是基于OHLC(开盘价、最高价、最低价、收盘价)价格数据和成交量的技术指标,包括移动平均线、RSI、MACD、布林带等。基本面指标(如市盈率、净资产收益率、营收增长率等)目前暂不支持,如果您的策略需要这类指标,请向我们反馈,我们可以考虑在未来版本中扩展支持。
---
**延伸学习**:
- 了解[原语组合模式](/docs/primitives/composition)
- 学习[具体策略示例](/docs/primitives/examples)
- 查看[指标详解](/docs/primitives/indicators)
- 探索[信号原语](/docs/primitives/signals)
--------------------------------------------------------------------------------
指标原语参考 (indicators.md)
--------------------------------------------------------------------------------
# 指标原语参考指南
指标原语(Indicator Primitives)用于从价格数据计算技术指标。这些组件接收OHLCV(开盘价、最高价、最低价、收盘价、成交量)数据,并输出时间序列指标值。
## 通用参数
大多数指标原语支持以下通用参数:
- `field`: 指定用于计算的价格列名(默认通常为'Close')
- `period`: 计算的回溯期(如移动平均的窗口大小)
## 可用指标原语
### 移动平均类
#### SMA (简单移动平均)
计算价格的简单移动平均。
```json
{
"id": "ma50",
"type": "SMA",
"params": {
"period": 50,
"field": "Close"
}
}
```
**参数**:
- `period`: 移动平均的周期(默认: 20)
- `field`: 使用的价格列(默认: 'Close')
#### EMA (指数移动平均)
计算价格的指数移动平均,对近期价格赋予更高权重。
```json
{
"id": "ema20",
"type": "EMA",
"params": {
"period": 20,
"field": "Close"
}
}
```
**参数**:
- `period`: 移动平均的周期(默认: 20)
- `field`: 使用的价格列(默认: 'Close')
### 动量指标类
#### RSI (相对强弱指数)
计算RSI指标,用于测量价格变动的速度和变化。
```json
{
"id": "rsi14",
"type": "RSI",
"params": {
"period": 14,
"field": "Close"
}
}
```
**参数**:
- `period`: RSI计算周期(默认: 14)
- `field`: 使用的价格列(默认: 'Close')
**注意事项**:
- RSI值范围在0-100之间
- 传统上,RSI > 70被视为超买,RSI < 30被视为超卖
- RSI计算使用Wilder's平滑方法
#### MACD (移动平均收敛发散)
计算MACD指标,显示两条移动平均线之间的关系。
```json
{
"id": "macd_indicator",
"type": "MACD",
"params": {
"fast_period": 12,
"slow_period": 26,
"signal_period": 9,
"field": "Close"
}
}
```
**参数**:
- `fast_period`: 快线EMA周期(默认: 12)
- `slow_period`: 慢线EMA周期(默认: 26)
- `signal_period`: 信号线周期(默认: 9)
- `field`: 使用的价格列(默认: 'Close')
### 波动率指标类
#### ATR (真实波幅)
计算Average True Range,衡量市场波动性。
```json
{
"id": "atr20",
"type": "ATR",
"params": {
"period": 20
}
}
```
**参数**:
- `period`: ATR计算周期(默认: 14)
#### BollingerBands (布林带)
计算布林带,包括中轨(SMA)、上轨和下轨。
```json
{
"id": "bbands",
"type": "BollingerBands",
"params": {
"period": 20,
"stddev": 2,
"field": "Close"
}
}
```
**参数**:
- `period`: 中轨SMA周期(默认: 20)
- `stddev`: 标准差倍数(默认: 2)
- `field`: 使用的价格列(默认: 'Close')
### 极值指标类
#### HighestValue (最高值)
计算过去N个周期内的最高价。
```json
{
"id": "highest_60",
"type": "HighestValue",
"params": {
"period": 60,
"field": "High"
}
}
```
**参数**:
- `period`: 查找最高值的周期(默认: 20)
- `field`: 使用的价格列(默认: 'High')
#### LowestValue (最低值)
计算过去N个周期内的最低价。
```json
{
"id": "lowest_60",
"type": "LowestValue",
"params": {
"period": 60,
"field": "Low"
}
}
```
**参数**:
- `period`: 查找最低值的周期(默认: 20)
- `field`: 使用的价格列(默认: 'Low')
#### PercentFromHighest (距离最高点百分比)
计算当前价格距离过去N个周期最高价的百分比。
```json
{
"id": "drawdown",
"type": "PercentFromHighest",
"params": {
"period": 252,
"field": "Close"
}
}
```
**参数**:
- `period`: 查找最高值的周期(默认: 20)
- `field`: 使用的价格列(默认: 'Close')
### 吊灯指标类
#### ChandelierExit (吊灯出场)
基于ATR的止损策略,根据最高价减去ATR的倍数。
```json
{
"id": "ce_long",
"type": "ChandelierExit",
"params": {
"period": 22,
"multiplier": 3.0,
"direction": "long"
}
}
```
**参数**:
- `period`: 回溯周期(默认: 22)
- `multiplier`: ATR乘数(默认: 3.0)
- `direction`: 方向,"long"或"short"(默认: "long")
### 常量类
#### Constant (常量值)
生成固定值的时间序列,常用于阈值。
```json
{
"id": "upper_threshold",
"type": "Constant",
"params": {
"value": 70
}
}
```
**参数**:
- `value`: 常量值(必需)
## 最佳实践
1. **参数选择**:
- 短期参数(如RSI 9)对市场变化反应更敏感,但可能产生更多假信号
- 长期参数(如RSI 21)提供更平滑的信号,但可能反应较慢
2. **指标组合**:
- 单一指标通常不足以构建可靠策略
- 考虑组合趋势、动量和波动率指标
3. **常见错误**:
- 过度拟合 - 不要仅基于历史数据优化参数
- 忽略市场环境 - 某些指标在特定市场环境中表现更好
4. **数据质量**:
- 确保输入的OHLCV数据没有缺失或异常值
- 考虑调整股票分割、股息等因素
--------------------------------------------------------------------------------
信号原语参考 (signals.md)
--------------------------------------------------------------------------------
# 信号原语参考指南
信号原语(Signal Primitives)是用于生成交易信号的组件,它们接收一个或多个时间序列作为输入,并输出布尔型时间序列(true/false)。这些组件可以组合成复杂的交易条件。
## 信号原语基础
所有信号原语都实现了`evaluate`方法,该方法接收输入时间序列并返回布尔结果。信号原语可以:
1. 评估单个时间点(返回单个布尔值)
2. 评估整个时间序列(返回布尔型Series)
## 可用信号原语
### 比较类信号
> **⚠️ 重要警告:输入顺序至关重要**
>
> 对于所有比较类信号(尤其是LessThan和GreaterThan),输入参数的顺序会直接影响比较结果。
> 当涉及常量与变量的比较时,**必须将常量放在左侧,变量放在右侧**,以确保执行预期的比较。
>
> 错误示例(常见错误!):
> ```json
> // 本意是 rsi < 70,但实际执行的是 70 < rsi
> {
> "type": "LessThan",
> "inputs": [
> { "ref": "rsi" },
> { "type": "Constant", "value": 70 }
> ]
> }
> ```
>
> 正确示例:
> ```json
> // 正确执行 rsi < 70
> {
> "type": "LessThan",
> "inputs": [
> { "type": "Constant", "value": 70 },
> { "ref": "rsi" }
> ]
> }
> ```
#### GreaterThan 和 LessThan (替代 Comparison)
推荐使用 GreaterThan 和 LessThan 替代通用的 Comparison,它们提供更明确的语义和更好的性能。
```json
{
"id": "price_above_ma",
"type": "GreaterThan",
"epsilon": 0.01,
"inputs": [
{ "column": "Close" },
{ "ref": "ma_indicator" }
]
}
```
**参数**:
- `epsilon`: 用于处理浮点比较精度问题的小值(默认: 0)
**注意事项**:
- 比较两个时间序列时,会使用epsilon值作为精度缓冲
- 输入顺序至关重要,请参考下面的 GreaterThan 和 LessThan 部分
#### GreaterThan (大于)
检查第一个输入是否大于第二个输入。**输入顺序至关重要**!
```json
{
"id": "price_gt_ma",
"type": "GreaterThan",
"epsilon": 0.01,
"inputs": [
{ "column": "Close" }, // 要检查的值放第一位
{ "ref": "ma_indicator" } // 与之比较的值放第二位
]
}
```
**常量比较的正确写法**:
```json
{
"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 (小于)
检查第一个输入是否小于第二个输入。**输入顺序至关重要**!
```json
{
"id": "price_lt_ma",
"type": "LessThan",
"epsilon": 0.01,
"inputs": [
{ "column": "Close" }, // 要检查的值放第一位
{ "ref": "ma_indicator" } // 与之比较的值放第二位
]
}
```
**常量比较的正确写法**:
```json
{
"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 (在范围内)
检查输入值是否在指定范围内。
```json
{
"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 (上穿)
检测第一个输入是否向上穿越第二个输入。
```json
{
"id": "price_cross_above_ma",
"type": "Crossover",
"params": { "mode": "simple" },
"inputs": [
{ "column": "Close" },
{ "ref": "ma_indicator" }
]
}
```
**参数**:
- `mode`: 交叉检测模式,可选值:
- `simple`: 简单交叉检测(默认)
- `confirmed`: 要求确认(连续两个周期)
**注意事项**:
- 只在实际发生穿越的那一个时间点返回true
- 穿越后的后续时间点返回false,直到发生新的穿越
- 适合用作买入/卖出触发信号
#### Crossunder (下穿)
检测第一个输入是否向下穿越第二个输入。
```json
{
"id": "price_cross_below_ma",
"type": "Crossunder",
"params": { "mode": "simple" },
"inputs": [
{ "column": "Close" },
{ "ref": "ma_indicator" }
]
}
```
**参数**:
- `mode`: 交叉检测模式,可选值:
- `simple`: 简单交叉检测(默认)
- `confirmed`: 要求确认(连续两个周期)
**注意事项**:
- 只在实际发生穿越的那一个时间点返回true
- 穿越后的后续时间点返回false,直到发生新的穿越
- 适合用作买入/卖出触发信号
### 逻辑运算符类
#### And (逻辑与)
要求所有输入信号同时为true。支持嵌套信号和内联常量。
**基本用法**:
```json
{
"id": "buy_condition",
"type": "And",
"inputs": [
{ "ref": "price_above_ma" },
{ "ref": "rsi_oversold" }
]
}
```
**嵌套信号示例**:
```json
{
"id": "buy_condition_core",
"type": "And",
"inputs": [
{ "ref": "macd_cross_signal" },
{
"type": "GreaterThan",
"inputs": [
{ "column": "Volume" },
{ "ref": "volume_ma" }
],
"params": {
"threshold": 1.5
}
}
]
}
```
**内联常量支持**:
```json
{
"id": "enhanced_buy",
"type": "And",
"inputs": [
{ "ref": "buy_condition_core" },
{
"type": "LessThan",
"inputs": [
{ "ref": "volume_ratio" },
{ "type": "Constant", "value": 3 }
]
}
]
}
```
#### Or (逻辑或)
当任一输入信号为true时返回true。
```json
{
"id": "sell_condition",
"type": "Or",
"inputs": [
{ "ref": "stop_loss_hit" },
{ "ref": "take_profit_hit" }
]
}
```
#### Not (逻辑非)
对输入信号取反。
```json
{
"id": "not_overbought",
"type": "Not",
"inputs": [
{ "ref": "rsi_overbought" }
]
}
```
**逻辑运算符新特性**:
1. **嵌套信号支持**: And/Or可以接受嵌套的信号定义作为输入
2. **内联常量**: 嵌套信号中支持 `{"type": "Constant", "value": N}` 格式
3. **灵活组合**: 可以混合使用信号引用和嵌套定义
**注意事项**:
- 增强了NaN处理逻辑
- 适合需要排除特定条件的场景
- 嵌套信号会自动评估,无需预先定义ID
### 模式识别类
#### Streak (连续模式)
检测连续满足条件的模式。**注意:Streak 使用"回溯标记"语义,即标记整个符合条件的连续序列,而非延迟触发。**
```json
{
"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)语义:
1. **整序列标记**: 当检测到符合条件的连续序列时,会标记该序列中的所有位置(从第一天开始),而非仅标记第 N 天
2. **max_length 截断**: 如果连续序列超过 `max_length`,只标记前 `max_length` 个位置
3. **批量处理**: 作为无状态原语,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 天确认后触发"逻辑的核心原语。
```json
{
"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 天确认**:
```json
{
"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
### 数学运算类
> **🆕 新功能:纯数学运算模式**
>
> 数学运算类信号现在支持两种工作模式:
> 1. **比较模式**(默认):执行数学运算后与阈值比较,返回布尔结果
> 2. **纯数学模式**:设置 `return_calculation=true` 时,直接返回数学运算结果
#### PercentChange (百分比变化)
计算时间序列的百分比变化,并与阈值或另一时间序列比较。
```json
{
"id": "price_up_5percent",
"type": "PercentChange",
"params": {
"period": 5,
"threshold": 5.0,
"comparison": "greater"
},
"inputs": [
{ "column": "Close" }
]
}
```
**参数**:
- `period`: 计算变化的周期(默认: 1)
- `threshold`: 比较阈值(可选)
- `comparison`: 比较类型(默认: "greater")
**注意事项**:
- 可与阈值比较或与另一时间序列比较
- 适合检测价格动量或大幅波动
#### Add (加法)
将两个或多个时间序列相加。支持比较模式和纯数学运算模式。
**比较模式示例**(默认行为):
```json
{
"id": "combined_gt_threshold",
"type": "Add",
"params": {
"threshold": 100,
"comparison": "greater"
},
"inputs": [
{ "ref": "indicator1" },
{ "ref": "indicator2" }
]
}
```
**纯数学运算模式示例**:
```json
{
"id": "combined_indicator",
"type": "Add",
"params": {
"return_calculation": true
},
"inputs": [
{ "ref": "indicator1" },
{ "ref": "indicator2" },
{ "ref": "indicator3" }
]
}
```
**参数**:
- `return_calculation`: 是否返回计算结果而非比较结果(默认: false)
- `threshold`: 比较阈值(仅在比较模式下使用)
- `comparison`: 比较类型(仅在比较模式下使用,默认: "greater")
- `absolute`: 是否对结果取绝对值(默认: false)
**内联常量支持**:
```json
{
"id": "indicator_plus_constant",
"type": "Add",
"params": {
"return_calculation": true
},
"inputs": [
{ "ref": "base_indicator" },
{ "type": "Constant", "value": 10 }
]
}
```
#### Subtract (减法)
从第一个时间序列中减去第二个及后续时间序列(按从左到右顺序)。
**纯数学运算示例**:
```json
{
"id": "indicator_difference",
"type": "Subtract",
"params": {
"return_calculation": true
},
"inputs": [
{ "ref": "indicator1" },
{ "ref": "indicator2" }
]
}
```
**多操作数示例**(左到右计算:(a - b) - c):
```json
{
"id": "sequential_subtract",
"type": "Subtract",
"params": {
"return_calculation": true
},
"inputs": [
{ "ref": "base_value" },
{ "ref": "adjustment1" },
{ "type": "Constant", "value": 5 }
]
}
```
#### Multiply (乘法)
将两个或多个时间序列相乘(支持多操作数)。
**纯数学运算示例**:
```json
{
"id": "weighted_indicator",
"type": "Multiply",
"params": {
"return_calculation": true
},
"inputs": [
{ "ref": "indicator" },
{ "ref": "weight" }
]
}
```
**多操作数乘法示例**:
```json
{
"id": "signal_strength",
"type": "Multiply",
"params": {
"return_calculation": true
},
"inputs": [
{ "ref": "macd_atr_ratio" },
{ "ref": "ma_close_ratio" },
{ "type": "Constant", "value": 1.0 }
]
}
```
#### Divide (除法)
将第一个时间序列除以第二个及后续时间序列(按从左到右顺序)。
**纯数学运算示例**:
```json
{
"id": "indicator_ratio",
"type": "Divide",
"params": {
"return_calculation": true
},
"inputs": [
{ "ref": "indicator1" },
{ "ref": "indicator2" }
]
}
```
**多操作数示例**(左到右计算:(a / b) / c):
```json
{
"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)
**重要特性**:
1. **向后兼容**: 默认行为保持不变,现有配置无需修改
2. **多操作数支持**: 纯数学模式支持2个以上输入,按从左到右顺序计算
3. **内联常量**: 支持 `{"type": "Constant", "value": N}` 格式的内联常量
4. **除零处理**: Divide操作自动处理除零情况,返回NaN
### 策略切换类
#### StockBondSwitch (股债切换)
> **⚠️ 智能资产轮动信号**
>
> 这是一个专门为多资产轮动策略设计的智能信号原语,它能够自动识别当前正在评估的标的,
> 并根据标的在投资组合中的位置(约定:第一个=股票类资产,第二个=债券类资产)以及市场条件
> 返回相应的买入信号。
根据市场条件信号为不同资产生成互补的买入信号,实现股债轮动策略。
```json
{
"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
**完整配置示例**:
```json
{
"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"
}
}
}
```
**技术特点**:
1. **智能识别**: 自动识别当前正在评估的标的和投资组合配置
2. **上下文感知**: 能够获取完整的投资组合标的列表和当前标的信息
3. **安全机制**:
- 无法获取投资组合信息时默认不产生买入信号
- 投资组合标的少于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 变化**:不触发自动调整
**设计理由**:
1. 避免因指标波动产生过度交易
2. 职责分离:信号控制时机,权重控制规模
3. 符合主动策略的标准实践
### ConditionalWeight (条件权重)
根据布尔条件选择不同的目标权重(离散权重调整)。
```json
{
"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估值调仓:估值过高时减仓,估值正常时满仓
- 波动率调仓:高波动时减仓,低波动时加仓
- 任何基于条件的离散权重调整
**完整示例**:
```json
{
"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 (线性缩放权重)
将指标值线性映射到权重范围(连续权重调整)。
```json
{
"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%
- 任何需要连续调整权重的场景
**完整示例**:
```json
{
"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` 资金策略:
```json
{
"capital_strategy": {
"name": "RebalancingCapitalStrategy",
"params": {
"initial_capital": 100000
}
}
}
```
如果使用其他资金策略(如 `PercentCapitalStrategy`),target_weight 将被忽略,策略将按照固定比例交易。
### 应用场景
#### 1. 估值驱动的动态仓位
根据估值指标(PE/PB)动态调整仓位:
```json
{
"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. 波动率风险控制
根据市场波动率调整风险敞口:
```json
{
"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. 技术指标组合
结合多个权重原语:
```json
{
"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"
}
}
```
### 相关资源
- **实战案例**:查看 [动态仓位策略案例](../primitives/advanced/dynamic-position-strategy.md) 了解完整的策略实现
- **FileBasedStrategy**:查看 [文件策略文档](../strategies/file-based-strategy.md) 了解如何在CSV文件中使用动态仓位
## 信号组合最佳实践
1. **构建复合条件**:
- 使用`And`、`Or`组合多个信号
- 使用`Not`反转信号
- 例如: `And(CrossAbove(RSI, 30), GreaterThan(Close, SMA))`
2. **交叉事件vs状态**:
- 交叉事件(CrossAbove/CrossBelow)只在穿越发生时为true
- 状态比较(GreaterThan/LessThan)只要条件满足就一直为true
- 明确了解这一区别对避免频繁交易很重要
3. **过滤假信号**:
- 使用Streak要求信号持续一定时间
- 结合多个指标确认信号
- 使用趋势过滤器(如价格高于均线)
4. **信号命名和组织**:
- 使用清晰的ID命名每个信号组件
- 从简单到复杂逐步构建信号
- 先定义基本条件,再组合成复杂条件
5. **动态仓位控制**:
- 权重原语应该输出到 `target_weight` 字段
- 必须配合 `RebalancingCapitalStrategy` 使用
- 考虑交易成本,避免频繁小幅调仓
- 权重变化只在交易信号触发时生效
## 常见错误和解决方案
1. **过度频繁的信号**:
- 问题: 使用状态比较(如GreaterThan)作为买入信号
- 解决: 使用CrossAbove/CrossBelow检测交叉事件
2. **信号缺失**:
- 问题: 输入时间序列有NaN值
- 解决: 确保指标计算有足够的历史数据
3. **精度问题**:
- 问题: 浮点比较导致不稳定的结果
- 解决: 在Comparison中使用epsilon参数
4. **逻辑错误**:
- 问题: 混淆And/Or逻辑
- 解决: 仔细验证复合条件的预期行为
5. **动态仓位不生效**:
- 问题: 使用了 `PercentCapitalStrategy` 而非 `RebalancingCapitalStrategy`
- 解决: 检查资金策略配置,确保使用正确的策略类型
6. **仓位频繁调整**:
- 问题: 期望 target_weight 变化时自动调仓
- 解决: 理解执行语义,权重只在交易信号触发时生效
--------------------------------------------------------------------------------
组合模式 (composition.md)
--------------------------------------------------------------------------------
# 原语组合模式与最佳实践
本文档介绍了常见的原语组合模式,以及如何有效地构建复杂策略。通过了解这些模式,您可以更高效地利用原语系统构建交易策略,而无需修改代码。
## 核心组合模式
### 1. 趋势跟随模式
趋势跟随策略在已确立的趋势方向上交易。
```json
{
"indicators": [
{
"id": "sma_short",
"type": "SMA",
"params": {
"period": 50,
"field": "Close"
}
},
{
"id": "sma_long",
"type": "SMA",
"params": {
"period": 200,
"field": "Close"
}
}
],
"signals": [
{
"id": "uptrend",
"type": "GreaterThan",
"epsilon": 0.5,
"inputs": [
{ "ref": "sma_short" },
{ "ref": "sma_long" }
]
},
{
"id": "price_above_trend",
"type": "GreaterThan",
"epsilon": 0.5,
"inputs": [
{ "column": "Close" },
{ "ref": "sma_short" }
]
},
{
"id": "buy_signal",
"type": "And",
"inputs": [
{ "ref": "uptrend" },
{ "ref": "price_above_trend" }
]
}
]
}
```
**关键点**:
- 使用快速/慢速均线确定趋势方向
- 验证价格位于趋势线上方/下方
- 使用逻辑操作符组合多个条件
### 2. 反转交易模式
反转策略寻找价格可能改变方向的点。
```json
{
"indicators": [
{
"id": "rsi_indicator",
"type": "RSI",
"params": {
"period": 14,
"field": "Close"
}
},
{
"id": "upper_threshold",
"type": "Constant",
"params": { "value": 70 }
},
{
"id": "lower_threshold",
"type": "Constant",
"params": { "value": 30 }
}
],
"signals": [
{
"id": "oversold",
"type": "Crossunder",
"params": { "mode": "simple" },
"inputs": [
{ "ref": "rsi_indicator" },
{ "ref": "lower_threshold" }
]
},
{
"id": "overbought",
"type": "Crossover",
"params": { "mode": "simple" },
"inputs": [
{ "ref": "rsi_indicator" },
{ "ref": "upper_threshold" }
]
}
]
}
```
**关键点**:
- 使用震荡指标(RSI, Stochastic)识别超买/超卖条件
- 使用Crossover/Crossunder捕捉指标穿越阈值的瞬间
- 避免使用简单的GreaterThan/LessThan,它们会生成持续信号
### 3. 突破交易模式
突破策略寻找价格突破支撑或阻力位的时刻。
```json
{
"indicators": [
{
"id": "highest_high",
"type": "HighestValue",
"params": {
"period": 20,
"field": "High"
}
},
{
"id": "lowest_low",
"type": "LowestValue",
"params": {
"period": 20,
"field": "Low"
}
}
],
"signals": [
{
"id": "resistance_break",
"type": "Crossover",
"params": { "mode": "simple" },
"inputs": [
{ "column": "Close" },
{ "ref": "highest_high" }
]
},
{
"id": "support_break",
"type": "Crossunder",
"params": { "mode": "simple" },
"inputs": [
{ "column": "Close" },
{ "ref": "lowest_low" }
]
}
]
}
```
**关键点**:
- 使用HighestValue/LowestValue识别支撑/阻力位
- 使用Crossover/Crossunder捕捉突破时刻
- 考虑添加成交量确认或其他过滤器减少假突破
### 4. 波动性跟踪止损模式
使用动态止损跟踪价格走势,适应市场波动性。
```json
{
"indicators": [
{
"id": "atr_indicator",
"type": "ATR",
"params": { "period": 14 }
},
{
"id": "chandelier_exit",
"type": "ChandelierExit",
"params": {
"period": 22,
"multiplier": 3.0
}
}
],
"signals": [
{
"id": "stop_hit",
"type": "Crossunder",
"params": { "mode": "simple" },
"inputs": [
{ "column": "Close" },
{ "ref": "chandelier_exit" }
]
}
]
}
```
**关键点**:
- 使用ATR或ChandelierExit创建动态止损位
- 止损位会随着价格的上涨而上移,但不会随价格下跌而下移
- Crossunder用于检测价格是否击穿止损位
## 高级组合模式
### 1. 多重确认模式
要求多个指标同时确认信号,减少假信号。
```json
{
"signals": [
{
"id": "price_above_ma",
"type": "GreaterThan",
"inputs": [
{ "column": "Close" },
{ "ref": "ma200" }
]
},
{
"id": "rsi_bull",
"type": "GreaterThan",
"inputs": [
{ "ref": "rsi_indicator" },
{ "ref": "rsi_midpoint" }
]
},
{
"id": "volume_increasing",
"type": "GreaterThan",
"inputs": [
{ "column": "Volume" },
{ "ref": "volume_sma" }
]
},
{
"id": "strong_buy_signal",
"type": "And",
"inputs": [
{ "ref": "price_above_ma" },
{ "ref": "rsi_bull" },
{ "ref": "volume_increasing" }
]
}
]
}
```
**关键点**:
- 结合趋势、动量和成交量指标
- 使用And运算符要求所有条件同时满足
- 较少的交易信号,但可能质量更高
### 2. 趋势过滤模式
仅在主要趋势方向交易,避免逆势操作。
```json
{
"signals": [
{
"id": "major_uptrend",
"type": "GreaterThan",
"inputs": [
{ "ref": "ma50" },
{ "ref": "ma200" }
]
},
{
"id": "rsi_oversold",
"type": "CrossBelow",
"inputs": [
{ "ref": "rsi_indicator" },
{ "ref": "lower_threshold" }
]
},
{
"id": "filtered_buy_signal",
"type": "And",
"inputs": [
{ "ref": "major_uptrend" },
{ "ref": "rsi_oversold" }
]
}
]
}
```
**关键点**:
- 首先确定主要趋势方向
- 只有在趋势方向上的信号才被考虑
- 可显著减少逆势交易
### 3. 连续信号确认模式
使用Streak要求信号持续多个周期才采取行动。
```json
{
"signals": [
{
"id": "price_above_ma",
"type": "GreaterThan",
"inputs": [
{ "column": "Close" },
{ "ref": "ma50" }
]
},
{
"id": "consistent_strength",
"type": "Streak",
"params": {
"condition": "true",
"min_length": 3
},
"inputs": [
{ "ref": "price_above_ma" }
]
}
]
}
```
**关键点**:
- 使用Streak要求信号持续一定天数
- 减少由市场噪声导致的假信号
- 可以与其他条件结合使用
### 4. 动态阈值模式
使用相对阈值而非固定阈值,使策略能够适应不同市场环境。
```json
{
"indicators": [
{
"id": "bollinger_bands",
"type": "BollingerBands",
"params": {
"period": 20,
"std_dev": 2.0
}
}
],
"signals": [
{
"id": "price_at_lower_band",
"type": "CrossBelow",
"inputs": [
{ "column": "Close" },
{ "ref": "bollinger_bands", "band": "lower" }
]
}
]
}
```
**关键点**:
- 使用基于统计的动态阈值(如Bollinger Bands)
- 阈值根据市场波动性自动调整
- 适应不同的市场环境
## 特定策略模式示例
### 1. RSI超买超卖策略
```json
{
"indicators": [
{
"id": "rsi_indicator",
"type": "RSI",
"params": {
"period": 11,
"field": "Close"
}
},
{
"id": "upper_threshold",
"type": "Constant",
"params": {
"value": 63
}
},
{
"id": "lower_threshold",
"type": "Constant",
"params": {
"value": 37
}
}
],
"signals": [
{
"id": "is_below_lower",
"type": "LessThan",
"epsilon": 0.5,
"inputs": [
{ "ref": "rsi_indicator" },
{ "ref": "lower_threshold" }
]
},
{
"id": "is_above_upper",
"type": "GreaterThan",
"epsilon": 0.5,
"inputs": [
{ "ref": "rsi_indicator" },
{ "ref": "upper_threshold" }
]
},
{
"id": "buy_signal_cross",
"type": "Crossunder",
"params": { "mode": "simple" },
"inputs": [
{ "ref": "rsi_indicator" },
{ "ref": "lower_threshold" }
]
},
{
"id": "sell_signal_cross",
"type": "Crossover",
"params": { "mode": "simple" },
"inputs": [
{ "ref": "rsi_indicator" },
{ "ref": "upper_threshold" }
]
}
],
"outputs": {
"buy_signal": "buy_signal_cross",
"sell_signal": "sell_signal_cross"
}
}
```
**关键点**:
- 使用Crossunder/Crossover捕捉RSI穿越阈值的瞬间
- 同时暴露is_below_lower/is_above_upper状态指标
- 这种模式避免了传统RSI策略中常见的频繁交易问题
### 2. 吊灯止损策略
```json
{
"indicators": [
{
"id": "ma_indicator",
"type": "SMA",
"params": {
"period": 250,
"field": "Close"
}
},
{
"id": "chandelier_exit_indicator",
"type": "ChandelierExit",
"params": {
"period": 60,
"multiplier": 4.0
}
}
],
"signals": [
{
"id": "price_gt_ma",
"type": "GreaterThan",
"epsilon": 0.5,
"inputs": [
{ "column": "Close" },
{ "ref": "ma_indicator" }
]
},
{
"id": "price_gt_ce",
"type": "GreaterThan",
"epsilon": 0.5,
"inputs": [
{ "column": "Close" },
{ "ref": "chandelier_exit_indicator" }
]
},
{
"id": "buy_signal_condition",
"type": "And",
"inputs": [
{ "ref": "price_gt_ma" },
{ "ref": "price_gt_ce" }
]
},
{
"id": "sell_signal_condition",
"type": "Not",
"inputs": [
{ "ref": "price_gt_ce" }
]
}
],
"outputs": {
"buy_signal": "buy_signal_condition",
"sell_signal": "sell_signal_condition"
}
}
```
**关键点**:
- 结合长期均线和吊灯止损
- 均线确定趋势方向
- 吊灯出场提供动态止损位置
- 使用Not反转信号,在价格跌破止损时卖出
## 设计策略的最佳实践
1. **从简单开始**:
- 先构建基本组件,再组合成复杂策略
- 使用清晰的ID命名每个组件
- 遵循自下而上的构建方法
2. **避免过度拟合**:
- 参数越少越好
- 避免过度优化回测期间的参数
- 测试不同市场环境下的表现
3. **考虑信号质量与数量的平衡**:
- 更严格的条件产生更少但可能更高质量的信号
- 过于宽松的条件可能产生过多交易
- 寻找适合您交易风格的平衡点
4. **增量测试**:
- 在添加新条件前测试基本策略
- 单独评估每个新添加的条件
- 验证复合条件是否按预期工作
5. **关注输出映射**:
- 仔细选择buy_signal和sell_signal的映射
- 确保输出所有关键中间指标以便分析
- 使用明确的输出名称
================================================================================
高级功能
================================================================================
--------------------------------------------------------------------------------
市场指标 (advanced/market-indicators.md)
--------------------------------------------------------------------------------
# 市场指标原语指南
本文档介绍了如何在交易策略中使用市场指标原语,包括配置、转换器和与信号系统的集成使用。市场指标原语允许策略参考外部市场数据(如VIX、SPX等)进行决策,而不仅限于单一交易品种的价格数据。
## 基本概念
市场指标原语扩展了策略原语系统,使其能够引用和使用外部市场指标。这些指标通常代表整体市场状况(如VIX代表市场波动性)或特定市场细分(如SPX代表标普500指数)。
### 主要组件:
1. **市场指标管理器 (MarketIndicatorManager)**:负责加载和管理市场指标数据
2. **市场转换器 (MarketTransformers)**:对原始市场数据进行转换和处理
3. **信号评估器扩展 (SignalEvaluator)**:支持在信号树中引用市场指标
## 配置市场指标
在投资组合配置中添加市场指标需要在 `strategy_definition` 内部添加 `market_indicators` 部分:
```json
{
"market_indicators": {
"indicators": [
{
"code": "SPX"
}
],
"transformers": [
{
"name": "spx_raw",
"type": "IdentityTransformer",
"params": {
"indicator": "SPX",
"field": "Close"
}
},
{
"name": "spx_ma50",
"type": "MovingAverageTransformer",
"params": {
"indicator": "SPX",
"window": 50,
"method": "simple",
"field": "Close"
}
},
{
"name": "spx_ma200",
"type": "MovingAverageTransformer",
"params": {
"indicator": "SPX",
"window": 200,
"method": "simple",
"field": "Close"
}
},
{
"name": "spx_rs",
"type": "RelativeStrengthTransformer",
"params": {
"indicator": "SPX",
"reference": "ma",
"window": 90,
"field": "Close"
}
}
]
},
"trade_strategy": {
"indicators": [
{
"id": "ma_short",
"type": "SMA",
"params": {
"period": 20,
"column": "Close"
}
},
{
"id": "ma_long",
"type": "SMA",
"params": {
"period": 50,
"column": "Close"
}
},
{
"id": "rsi_indicator",
"type": "RSI",
"params": {
"period": 14
}
}
],
"signals": [
{
"id": "price_gt_ma_short",
"type": "GreaterThan",
"inputs": [
{
"column": "Close"
},
{
"ref": "ma_short"
}
]
},
{
"id": "ma_short_gt_ma_long",
"type": "GreaterThan",
"inputs": [
{
"ref": "ma_short"
},
{
"ref": "ma_long"
}
]
},
{
"id": "rsi_not_overbought",
"type": "LessThan",
"epsilon": 0.5,
"inputs": [
{
"type": "Constant",
"value": 70
},
{
"ref": "rsi_indicator"
}
]
},
{
"id": "rsi_not_overbought_direct",
"type": "LessThan",
"inputs": [
{
"type": "Constant",
"value": 65
},
{
"ref": "rsi_indicator"
}
]
},
{
"id": "rsi_not_oversold",
"type": "GreaterThan",
"inputs": [
{
"ref": "rsi_indicator"
},
{
"type": "Constant",
"value": 30
}
]
},
{
"id": "market_uptrend",
"type": "GreaterThan",
"inputs": [
{
"market": "SPX",
"transformer": "spx_ma50"
},
{
"market": "SPX",
"transformer": "spx_ma200"
}
]
},
{
"id": "market_strength_rising",
"type": "GreaterThan",
"inputs": [
{
"market": "SPX",
"transformer": "spx_rs"
},
{
"type": "Constant",
"value": 1
}
]
},
{
"id": "market_environment_bullish",
"type": "And",
"inputs": [
{
"ref": "market_uptrend"
},
{
"ref": "market_strength_rising"
}
]
},
{
"id": "market_price_reference",
"type": "GreaterThan",
"inputs": [
{
"market": "SPX",
"transformer": "spx_raw"
},
{
"type": "Constant",
"value": 0
}
]
},
{
"id": "price_and_ma_bullish",
"type": "And",
"inputs": [
{
"ref": "price_gt_ma_short"
},
{
"ref": "ma_short_gt_ma_long"
}
]
},
{
"id": "stock_technical_bullish",
"type": "And",
"inputs": [
{
"ref": "price_and_ma_bullish"
},
{
"ref": "rsi_not_overbought"
}
]
},
{
"id": "buy_signal_condition",
"type": "And",
"inputs": [
{
"ref": "stock_technical_bullish"
},
{
"ref": "market_environment_bullish"
}
]
},
{
"id": "sell_signal_condition",
"type": "Or",
"inputs": [
{
"type": "Not",
"inputs": [
{
"ref": "market_uptrend"
}
]
},
{
"type": "Not",
"inputs": [
{
"ref": "price_gt_ma_short"
}
]
}
]
}
],
"outputs": {
"buy_signal": "buy_signal_condition",
"sell_signal": "sell_signal_condition",
"indicators": [
{
"id": "ma_short",
"output_name": "ma_short"
},
{
"id": "ma_long",
"output_name": "ma_long"
},
{
"id": "rsi_indicator",
"output_name": "rsi"
},
{
"id": "price_gt_ma_short",
"output_name": "price_gt_ma"
},
{
"id": "ma_short_gt_ma_long",
"output_name": "ma_crossover"
},
{
"id": "rsi_not_overbought",
"output_name": "rsi_ok"
},
{
"id": "rsi_not_overbought_direct",
"output_name": "rsi_direct"
},
{
"id": "rsi_not_oversold",
"output_name": "rsi_gt_30"
},
{
"id": "price_ma_bull",
"output_name": "price_ma_bull"
},
{
"id": "market_uptrend",
"output_name": "mkt_uptrend"
},
{
"id": "market_strength_rising",
"output_name": "mkt_strength"
},
{
"id": "market_environment_bullish",
"output_name": "mkt_bullish"
},
{
"id": "market_price_reference",
"output_name": "spx_ref"
},
{
"id": "stock_technical_bullish",
"output_name": "stock_bullish"
},
{
"id": "buy_signal_condition",
"output_name": "buy_condition"
},
{
"id": "sell_signal_condition",
"output_name": "sell_condition"
}
],
"market_indicators": [
{
"market": "SPX",
"transformer": "spx_raw",
"output_name": "spx"
},
{
"market": "SPX",
"transformer": "spx_ma50",
"output_name": "spx_ma50"
},
{
"market": "SPX",
"transformer": "spx_ma200",
"output_name": "spx_ma200"
},
{
"market": "SPX",
"transformer": "spx_rs",
"output_name": "spx_rs"
}
]
}
}
}
```
### 指标配置选项:
| 字段 | 说明 | 示例 |
|------|------|------|
| code | 市场指标代码 | "VIX", "SPX" |
| start_date | 数据开始日期(可选) | "2018-01-01" |
| end_date | 数据结束日期(可选) | "2022-12-31" |
> **注意:** 如果不指定时间范围,系统将使用投资组合的时间范围
## 市场指标转换器
转换器允许对原始市场数据进行转换和处理,生成新的派生时间序列。系统内置了以下转换器:
### 1. 移动平均转换器 (MovingAverageTransformer)
计算指定窗口的移动平均值。
```json
{
"name": "spx_ma50",
"type": "MovingAverageTransformer",
"params": {
"indicator": "SPX",
"window": 50,
"method": "simple", // simple/weighted/exponential
"field": "Close"
}
}
```
### 2. 百分位排名转换器 (PercentileRankTransformer)
计算当前值在历史窗口中的百分位排名(0-100)。
```json
{
"name": "vix_percentile",
"type": "PercentileRankTransformer",
"params": {
"indicator": "VIX",
"lookback": 252, // 注意:使用lookback而不是window
"field": "Close"
}
}
```
### 3. 相对强度转换器 (RelativeStrengthTransformer)
计算当前值相对于历史平均值的强度比率。
```json
{
"name": "spx_rs",
"type": "RelativeStrengthTransformer",
"params": {
"indicator": "SPX",
"window": 90,
"field": "Close",
"reference": "ma" // ma, value 或 lookback
}
}
```
### 4. Z分数转换器 (ZScoreTransformer)
计算当前值在历史窗口中的标准化分数(Z分数)。
```json
{
"name": "vix_zscore",
"type": "ZScoreTransformer",
"params": {
"indicator": "VIX",
"window": 252,
"field": "Close"
}
}
```
### 5. 原样返回转换器 (IdentityTransformer)
直接返回原始指标数据,不做任何转换。通常用于统一处理市场指标的原始数据。
```json
{
"name": "vix_raw",
"type": "IdentityTransformer",
"params": {
"indicator": "VIX", // indicator 参数是必须的
"field": "Close"
}
}
```
使用示例:
```json
{
"market_indicators": {
"indicators": [{"code": "VIX"}],
"transformers": [
{
"name": "vix_raw",
"type": "IdentityTransformer",
"params": {
"indicator": "VIX",
"field": "Close"
}
}
]
},
"outputs": {
"market_indicators": [
{
"market": "VIX",
"transformer": "vix_raw",
"output_name": "vix_raw"
}
]
}
}
```
这种方式统一了市场指标的处理流程,无论是原始数据还是转换后的数据都通过转换器机制处理。
## 在信号中引用市场指标
市场指标可以在信号配置中使用 `market` 键进行引用:
### 1. 通过转换器引用
```json
{ "market": "VIX", "transformer": "vix_percentile" } // 引用VIX的百分位转换
```
### 2. 原始指标数据引用
```json
{
"market": "VIX",
"transformer": "vix_raw"
} // 使用 IdentityTransformer 引用VIX的原始数据
```
完整的信号配置示例:
```json
{
"id": "market_volatility_low",
"type": "LessThan",
"epsilon": 0.5, // 可选参数,用于处理浮点数比较的精度问题
"inputs": [
{ "market": "VIX", "transformer": "vix_percentile" },
{ "ref": "constant_75" } // 引用常量指标,而不是直接使用value
]
}
```
> **重要:** 系统要求所有市场指标数据的访问都通过转换器进行,这样可以保持数据处理流程的一致性。
## 逻辑操作符限制
在信号系统中,逻辑操作符(如 `And`、`Or`)有严格的输入限制:
1. **And 和 Or 操作符严格要求两个输入**,不多不少
2. 要组合多个条件,需要使用嵌套结构
示例:三个条件的组合需要嵌套实现
```json
// 错误 - And不能有3个输入
{
"id": "combined_conditions",
"type": "And",
"inputs": [
{ "ref": "condition1" },
{ "ref": "condition2" },
{ "ref": "condition3" }
]
}
// 正确 - 使用嵌套And实现多条件组合
{
"id": "conditions_1_2",
"type": "And",
"inputs": [
{ "ref": "condition1" },
{ "ref": "condition2" }
]
},
{
"id": "combined_conditions",
"type": "And",
"inputs": [
{ "ref": "conditions_1_2" },
{ "ref": "condition3" }
]
}
```
## 市场指标策略示例
### 示例1:VIX过滤策略
使用VIX波动率指标过滤市场环境,结合250日均线和吊灯止损的趋势跟踪策略。买入条件:价格高于均线和吊灯止损,且VIX百分位低于75或VIX下降;卖出条件:价格低于均线和吊灯止损,且市场环境恶化。(美股用VIX,其他市场需调整)
```json
{
"market_indicators": {
"indicators": [
{
"code": "VIX"
}
],
"transformers": [
{
"name": "vix_raw",
"type": "IdentityTransformer",
"params": {
"indicator": "VIX",
"field": "Close"
}
},
{
"name": "vix_percentile",
"type": "PercentileRankTransformer",
"params": {
"indicator": "VIX",
"lookback": 252,
"field": "Close"
}
},
{
"name": "vix_ma",
"type": "MovingAverageTransformer",
"params": {
"indicator": "VIX",
"window": 20,
"method": "simple",
"field": "Close"
}
}
]
},
"trade_strategy": {
"indicators": [
{
"id": "ma_indicator",
"type": "SMA",
"params": {
"period": 250,
"column": "Close"
}
},
{
"id": "atr_indicator",
"type": "ATR",
"params": {
"period": 60
}
},
{
"id": "chandelier_exit_indicator",
"type": "ChandelierExit",
"params": {
"period": 60,
"multiplier": 4
}
},
{
"id": "constant_75",
"type": "Constant",
"params": {
"value": 75
}
}
],
"signals": [
{
"id": "price_gt_ma",
"type": "GreaterThan",
"inputs": [
{
"column": "Close"
},
{
"ref": "ma_indicator"
}
]
},
{
"id": "price_gt_ce",
"type": "GreaterThan",
"inputs": [
{
"column": "Close"
},
{
"ref": "chandelier_exit_indicator"
}
]
},
{
"id": "market_volatility_low",
"type": "LessThan",
"epsilon": 0.5,
"inputs": [
{
"market": "VIX",
"transformer": "vix_percentile"
},
{
"ref": "constant_75"
}
]
},
{
"id": "market_volatility_declining",
"type": "LessThan",
"inputs": [
{
"market": "VIX",
"transformer": "vix_raw"
},
{
"market": "VIX",
"transformer": "vix_ma"
}
]
},
{
"id": "price_lt_ma",
"type": "LessThan",
"inputs": [
{
"ref": "ma_indicator"
},
{
"column": "Close"
}
]
},
{
"id": "price_lt_ce",
"type": "LessThan",
"inputs": [
{
"ref": "chandelier_exit_indicator"
},
{
"column": "Close"
}
]
},
{
"id": "market_condition_good",
"type": "Or",
"inputs": [
{
"ref": "market_volatility_low"
},
{
"ref": "market_volatility_declining"
}
]
},
{
"id": "price_conditions",
"type": "And",
"inputs": [
{
"ref": "price_gt_ma"
},
{
"ref": "price_gt_ce"
}
]
},
{
"id": "technical_buy_conditions",
"type": "And",
"inputs": [
{
"ref": "price_conditions"
},
{
"ref": "price_gt_ma"
}
]
},
{
"id": "buy_signal_condition",
"type": "And",
"inputs": [
{
"ref": "technical_buy_conditions"
},
{
"ref": "market_condition_good"
}
]
},
{
"id": "price_conditions_sell",
"type": "And",
"inputs": [
{
"ref": "price_lt_ma"
},
{
"ref": "price_lt_ce"
}
]
},
{
"id": "sell_signal_condition",
"type": "And",
"inputs": [
{
"ref": "price_conditions_sell"
},
{
"type": "Not",
"inputs": [
{
"ref": "market_condition_good"
}
]
}
]
}
],
"outputs": {
"buy_signal": "buy_signal_condition",
"sell_signal": "sell_signal_condition",
"indicators": [
{
"id": "ma_indicator",
"output_name": "ma"
},
{
"id": "atr_indicator",
"output_name": "atr"
},
{
"id": "chandelier_exit_indicator",
"output_name": "chandelier_stop"
},
{
"id": "market_volatility_low",
"output_name": "vix_percentile_low"
},
{
"id": "market_volatility_declining",
"output_name": "vix_declining"
},
{
"id": "market_condition_good",
"output_name": "market_ok"
},
{
"id": "price_conditions",
"output_name": "price_conditions"
},
{
"id": "technical_buy_conditions",
"output_name": "tech_buy"
},
{
"id": "buy_signal_condition",
"output_name": "buy_condition"
},
{
"id": "sell_signal_condition",
"output_name": "sell_condition"
}
],
"market_indicators": [
{
"market": "VIX",
"transformer": "vix_raw",
"output_name": "vix_raw"
},
{
"market": "VIX",
"transformer": "vix_percentile",
"output_name": "vix_percentile"
},
{
"market": "VIX",
"transformer": "vix_ma",
"output_name": "vix_ma"
}
]
}
}
}
```
### 示例2:市场趋势跟踪策略
基于市场指数相对强度和市场趋势的双重过滤策略,结合了离散对比强度速率和市场平均线趋势。
```json
{
"market_indicators": {
"indicators": [
{
"code": "SPX"
}
],
"transformers": [
{
"name": "spx_raw",
"type": "IdentityTransformer",
"params": {
"indicator": "SPX",
"field": "Close"
}
},
{
"name": "spx_ma50",
"type": "MovingAverageTransformer",
"params": {
"indicator": "SPX",
"window": 50,
"method": "simple",
"field": "Close"
}
},
{
"name": "spx_ma200",
"type": "MovingAverageTransformer",
"params": {
"indicator": "SPX",
"window": 200,
"method": "simple",
"field": "Close"
}
},
{
"name": "spx_rs",
"type": "RelativeStrengthTransformer",
"params": {
"indicator": "SPX",
"reference": "ma",
"window": 90,
"field": "Close"
}
}
]
},
"trade_strategy": {
"indicators": [
{
"id": "ma_short",
"type": "SMA",
"params": {
"period": 20,
"column": "Close"
}
},
{
"id": "ma_long",
"type": "SMA",
"params": {
"period": 50,
"column": "Close"
}
},
{
"id": "rsi_indicator",
"type": "RSI",
"params": {
"period": 14
}
}
],
"signals": [
{
"id": "price_gt_ma_short",
"type": "GreaterThan",
"inputs": [
{
"column": "Close"
},
{
"ref": "ma_short"
}
]
},
{
"id": "ma_short_gt_ma_long",
"type": "GreaterThan",
"inputs": [
{
"ref": "ma_short"
},
{
"ref": "ma_long"
}
]
},
{
"id": "rsi_not_overbought",
"type": "LessThan",
"epsilon": 0.5,
"inputs": [
{
"type": "Constant",
"value": 70
},
{
"ref": "rsi_indicator"
}
]
},
{
"id": "rsi_not_overbought_direct",
"type": "LessThan",
"inputs": [
{
"type": "Constant",
"value": 65
},
{
"ref": "rsi_indicator"
}
]
},
{
"id": "rsi_not_oversold",
"type": "GreaterThan",
"inputs": [
{
"ref": "rsi_indicator"
},
{
"type": "Constant",
"value": 30
}
]
},
{
"id": "market_uptrend",
"type": "GreaterThan",
"inputs": [
{
"market": "SPX",
"transformer": "spx_ma50"
},
{
"market": "SPX",
"transformer": "spx_ma200"
}
]
},
{
"id": "market_strength_rising",
"type": "GreaterThan",
"inputs": [
{
"market": "SPX",
"transformer": "spx_rs"
},
{
"type": "Constant",
"value": 1
}
]
},
{
"id": "market_environment_bullish",
"type": "And",
"inputs": [
{
"ref": "market_uptrend"
},
{
"ref": "market_strength_rising"
}
]
},
{
"id": "market_price_reference",
"type": "GreaterThan",
"inputs": [
{
"market": "SPX",
"transformer": "spx_raw"
},
{
"type": "Constant",
"value": 0
}
]
},
{
"id": "price_and_ma_bullish",
"type": "And",
"inputs": [
{
"ref": "price_gt_ma_short"
},
{
"ref": "ma_short_gt_ma_long"
}
]
},
{
"id": "stock_technical_bullish",
"type": "And",
"inputs": [
{
"ref": "price_and_ma_bullish"
},
{
"ref": "rsi_not_overbought"
}
]
},
{
"id": "buy_signal_condition",
"type": "And",
"inputs": [
{
"ref": "stock_technical_bullish"
},
{
"ref": "market_environment_bullish"
}
]
},
{
"id": "sell_signal_condition",
"type": "Or",
"inputs": [
{
"type": "Not",
"inputs": [
{
"ref": "market_uptrend"
}
]
},
{
"type": "Not",
"inputs": [
{
"ref": "price_gt_ma_short"
}
]
}
]
}
],
"outputs": {
"buy_signal": "buy_signal_condition",
"sell_signal": "sell_signal_condition",
"indicators": [
{
"id": "ma_short",
"output_name": "ma_short"
},
{
"id": "ma_long",
"output_name": "ma_long"
},
{
"id": "rsi_indicator",
"output_name": "rsi"
},
{
"id": "price_gt_ma_short",
"output_name": "price_gt_ma"
},
{
"id": "ma_short_gt_ma_long",
"output_name": "ma_crossover"
},
{
"id": "rsi_not_overbought",
"output_name": "rsi_ok"
},
{
"id": "rsi_not_overbought_direct",
"output_name": "rsi_direct"
},
{
"id": "rsi_not_oversold",
"output_name": "rsi_gt_30"
},
{
"id": "price_ma_bull",
"output_name": "price_ma_bull"
},
{
"id": "market_uptrend",
"output_name": "mkt_uptrend"
},
{
"id": "market_strength_rising",
"output_name": "mkt_strength"
},
{
"id": "market_environment_bullish",
"output_name": "mkt_bullish"
},
{
"id": "market_price_reference",
"output_name": "spx_ref"
},
{
"id": "stock_technical_bullish",
"output_name": "stock_bullish"
},
{
"id": "buy_signal_condition",
"output_name": "buy_condition"
},
{
"id": "sell_signal_condition",
"output_name": "sell_condition"
}
],
"market_indicators": [
{
"market": "SPX",
"transformer": "spx_raw",
"output_name": "spx"
},
{
"market": "SPX",
"transformer": "spx_ma50",
"output_name": "spx_ma50"
},
{
"market": "SPX",
"transformer": "spx_ma200",
"output_name": "spx_ma200"
},
{
"market": "SPX",
"transformer": "spx_rs",
"output_name": "spx_rs"
}
]
}
}
}
```
## 最佳实践
1. **明确引用要求**:市场指标转换器必须在信号计算树中被明确引用和使用,才能触发数据处理和收集。仅在 `outputs.market_indicators` 中列出但未在信号中使用的转换器不会被处理和输出。
2. **创建参考信号**:如果需要在输出中包含某个市场指标(如原始SPX数据),但该指标在主要信号逻辑中没有直接使用,可以创建一个专用的参考信号:
```json
{
"id": "market_price_reference",
"type": "GreaterThan",
"inputs": [
{ "market": "SPX", "transformer": "spx_raw" },
{ "type": "Constant", "value": 0 }
]
}
```
然后将此信号添加到outputs.indicators中:
```json
{ "id": "market_price_reference", "output_name": "spx_ref" }
```
3. **统一转换器处理**:始终使用转换器处理市场指标数据,包括原始数据(使用IdentityTransformer)
4. **使用正确的参数名称**:
- 对于PercentileRankTransformer,使用`lookback`而不是`window`
- 对于所有转换器,使用`field`而不是`column`
- 字段名称区分大小写,通常使用`Close`而不是`close`
5. **使用epsilon参数**:在LessThan和GreaterThan信号中,可以使用`epsilon`参数处理浮点数比较的精度问题
6. **使用常量指标**:对于固定阈值,最好创建常量指标并引用它,而不是直接使用`value`属性
7. **明确注册管理**:所有市场指标转换器必须在配置中明确定义并正确注册后才能被引用
8. **数据同步**:确保市场指标数据与交易资产数据的日期范围匹配
9. **转换器命名**:为转换器使用清晰的命名约定,如 `vix_percentile`、`spx_ma50` 等
10. **性能优化**:使用适当的数据窗口大小,避免过长的历史窗口导致性能问题
## 技术限制
1. 市场指标数据必须通过数据加载器可用
2. 市场指标的时间序列必须与回测期间有足够的重叠
3. 引用不存在的市场指标或转换器会立即抛出异常,不进行降级处理
4. 逻辑操作符(如And、Or)严格要求两个输入,必须使用嵌套结构处理更多条件
5. 所有市场指标数据访问必须通过转换器进行,不支持直接访问原始数据
6. 参数名称必须正确,系统不会自动纠正错误的参数名称
================================================================================
实战案例
================================================================================
--------------------------------------------------------------------------------
策略示例 (examples.md)
--------------------------------------------------------------------------------
# 原语策略示例
本文档提供了使用原语系统构建的交易策略示例,包括详细配置、参数优化建议和性能分析。这些示例可以作为构建自己策略的起点。
## ⚠️ 重要说明:配置类型区别
本文档中的示例分为两种类型:
### 原语策略配置
- 只包含`trade_strategy`和`market_indicators`(如需要)
- 这是您在前端原语策略页面需要配置的部分
- 专注于交易逻辑,不包含资金管理、标的选择等
### 完整组合配置
- 包含所有参数:基本信息、交易标的、时间参数、资金管理等
- 用于完整的回测和实盘应用
- 包含原语策略配置作为其中的一部分
**重要提醒:** 如果您的策略中使用了市场指标引用,必须同时提供`market_indicators`配置,否则回测会失败。
## RSI超买超卖策略
### 策略概述
这个经典策略基于RSI(相对强弱指数)的超买超卖状态,在市场超卖时买入,超买时卖出。
### 原语策略配置
```json
{
"trade_strategy": {
"indicators": [
{
"id": "rsi_indicator",
"type": "RSI",
"params": {
"period": 11,
"field": "Close"
}
},
{
"id": "upper_threshold",
"type": "Constant",
"params": {
"value": 63
}
},
{
"id": "lower_threshold",
"type": "Constant",
"params": {
"value": 37
}
}
],
"signals": [
{
"id": "is_below_lower",
"type": "LessThan",
"epsilon": 0.5,
"inputs": [
{ "ref": "rsi_indicator" },
{ "ref": "lower_threshold" }
]
},
{
"id": "is_above_upper",
"type": "GreaterThan",
"epsilon": 0.5,
"inputs": [
{ "ref": "rsi_indicator" },
{ "ref": "upper_threshold" }
]
},
{
"id": "buy_signal_cross",
"type": "Crossunder",
"params": { "mode": "simple" },
"inputs": [
{ "ref": "rsi_indicator" },
{ "ref": "lower_threshold" }
]
},
{
"id": "sell_signal_cross",
"type": "Crossover",
"params": { "mode": "simple" },
"inputs": [
{ "ref": "rsi_indicator" },
{ "ref": "upper_threshold" }
]
}
],
"outputs": {
"buy_signal": "buy_signal_cross",
"sell_signal": "sell_signal_cross",
"indicators": [
{ "id": "rsi_indicator", "output_name": "rsi" },
{ "id": "upper_threshold", "output_name": "upper_bound" },
{ "id": "lower_threshold", "output_name": "lower_bound" },
{ "id": "is_below_lower", "output_name": "is_oversold" },
{ "id": "is_above_upper", "output_name": "is_overbought" },
{ "id": "buy_signal_cross", "output_name": "buy_signal" },
{ "id": "sell_signal_cross", "output_name": "sell_signal" }
]
}
}
}
```
**说明:** 这个策略不需要`market_indicators`,因为所有指标都基于当前标的的OHLC数据。
### 策略原理
1. **RSI指标**:计算过去11天的相对强弱指数
2. **阈值设置**:使用37作为超卖阈值,63作为超买阈值
3. **买入信号**:当RSI从上方穿越下阈值时触发(CrossBelow)
4. **卖出信号**:当RSI从下方穿越上阈值时触发(CrossAbove)
5. **状态跟踪**:额外跟踪持续超买(is_above_upper)和持续超卖(is_below_lower)状态
### 参数优化建议
| 参数 | 建议范围 | 说明 |
|------|----------|------|
| RSI周期 | 9-14 | 较短周期(9-11)对价格变化更敏感,较长周期(12-14)提供更平滑的信号 |
| 超买阈值 | 60-70 | 传统使用70,但可视市场波动性调整 |
| 超卖阈值 | 30-40 | 传统使用30,但可视市场波动性调整 |
**研究发现**:
- 标准设置(RSI 14,30/70)在多数市场环境中表现稳定
- 中等偏保守的设置(RSI 11-12,37/63)可能在回测中表现更佳
- 过于极端的阈值(如20/80)会减少交易频率,但可能错过机会
### 性能分析
典型表现指标(根据历史回测):
- CAGR(年复合增长率):10-15%
- 最大回撤:15-25%
- 胜率:55-65%
- 平均交易次数:每年20-30次
### 改进变体
#### 1. 带趋势过滤的RSI策略
```json
{
"indicators": [
// 原有RSI指标...
{
"id": "sma_indicator",
"type": "SMA",
"params": {
"period": 200,
"column": "Close"
}
}
],
"signals": [
// 原有RSI信号...
{
"id": "price_above_sma",
"type": "GreaterThan",
"inputs": [
{ "column": "Close" },
{ "ref": "sma_indicator" }
]
},
{
"id": "filtered_buy_signal",
"type": "And",
"inputs": [
{ "ref": "buy_signal_cross" },
{ "ref": "price_above_sma" }
]
}
],
"outputs": {
"buy_signal": "filtered_buy_signal",
"sell_signal": "sell_signal_cross"
}
}
```
**改进要点**:只在上升趋势中买入(价格在200日均线上方),但无论趋势如何都在RSI超买时卖出。
#### 2. 带连续确认的RSI策略
```json
{
"signals": [
// 原有RSI信号...
{
"id": "consistent_oversold",
"type": "Streak",
"params": {
"condition": "true",
"min_length": 2
},
"inputs": [
{ "ref": "is_below_lower" }
]
},
{
"id": "buy_with_confirmation",
"type": "And",
"inputs": [
{ "ref": "buy_signal_cross" },
{ "ref": "consistent_oversold" }
]
}
],
"outputs": {
"buy_signal": "buy_with_confirmation",
"sell_signal": "sell_signal_cross"
}
}
```
**改进要点**:要求RSI至少连续两天处于超卖区域才考虑买入信号,减少震荡市场中的假信号。
## 双均线交叉策略
### 策略概述
这个经典策略使用两条不同周期的移动平均线,在短期均线上穿长期均线时买入,下穿时卖出。
### 原语策略配置
```json
{
"trade_strategy": {
"indicators": [
{
"id": "fast_ma",
"type": "SMA",
"params": {
"period": 50,
"field": "Close"
}
},
{
"id": "slow_ma",
"type": "SMA",
"params": {
"period": 200,
"field": "Close"
}
},
{
"id": "zero_constant",
"type": "Constant",
"params": {
"value": 0
}
}
],
"signals": [
{
"id": "ma_diff",
"type": "Subtract",
"inputs": [
{ "ref": "fast_ma" },
{ "ref": "slow_ma" }
]
},
{
"id": "bull_trend",
"type": "GreaterThan",
"epsilon": 0.5,
"inputs": [
{ "ref": "ma_diff" },
{ "ref": "zero_constant" }
]
},
{
"id": "buy_signal",
"type": "Crossover",
"params": { "mode": "simple" },
"inputs": [
{ "ref": "fast_ma" },
{ "ref": "slow_ma" }
]
},
{
"id": "sell_signal",
"type": "Crossunder",
"params": { "mode": "simple" },
"inputs": [
{ "ref": "fast_ma" },
{ "ref": "slow_ma" }
]
}
],
"outputs": {
"buy_signal": "buy_signal",
"sell_signal": "sell_signal",
"indicators": [
{ "id": "fast_ma", "output_name": "fast_ma" },
{ "id": "slow_ma", "output_name": "slow_ma" },
{ "id": "ma_diff", "output_name": "ma_diff" },
{ "id": "bull_trend", "output_name": "is_bull_trend" }
]
}
}
}
```
**说明:** 这个策略同样不需要`market_indicators`,因为所有指标都基于当前标的的OHLC数据。
### 策略原理
1. **移动平均线**:计算50日和200日简单移动平均线
2. **差值计算**:计算短期均线与长期均线的差值
3. **趋势判断**:差值大于0表示多头趋势
4. **买入信号**:短期均线从下方穿越长期均线时触发(黄金交叉)
5. **卖出信号**:短期均线从上方穿越长期均线时触发(死亡交叉)
### 参数优化建议
| 参数 | 建议范围 | 说明 |
|------|----------|------|
| 短期均线周期 | 20-50 | 较短周期提供更频繁的信号,较长周期减少假突破 |
| 长期均线周期 | 100-250 | 设置足够长以确定主要趋势 |
**研究发现**:
- 50/200组合("黄金交叉/死亡交叉")是最经典的设置,适合长期投资
- 20/100组合对中期趋势变化更敏感
- 5/20组合适合短期交易,但可能产生更多噪声
### 性能分析
典型表现指标:
- CAGR:8-12%
- 最大回撤:20-30%
- 胜率:45-55%
- 平均交易次数:每年3-8次(比RSI策略少)
### 改进变体
#### 1. 带成交量确认的双均线策略
```json
{
"indicators": [
// 原有移动平均线...
{
"id": "volume_ma",
"type": "SMA",
"params": {
"period": 20,
"column": "Volume"
}
}
],
"signals": [
// 原有信号...
{
"id": "volume_surge",
"type": "GreaterThan",
"inputs": [
{ "column": "Volume" },
{ "ref": "volume_ma" }
]
},
{
"id": "confirmed_buy_signal",
"type": "And",
"inputs": [
{ "ref": "buy_signal" },
{ "ref": "volume_surge" }
]
}
],
"outputs": {
"buy_signal": "confirmed_buy_signal",
"sell_signal": "sell_signal"
}
}
```
**改进要点**:要求买入信号伴随成交量放大,减少低质量交叉信号。
## 股债轮动策略
### 策略概述
这是一个基于 `StockBondSwitch` 原语的资产轮动策略,根据市场趋势在股票ETF和债券ETF之间进行全仓切换。该策略使用沪深300指数相对于其200日移动平均线的位置作为趋势判断指标。
### 原语策略配置
```json
{
"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": [
{
"id": "constant_one",
"type": "Constant",
"params": {
"value": 1
}
}
],
"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"
}
]
},
{
"id": "constant_false_signal",
"type": "Comparison",
"params": {
"comparison": "greater",
"threshold": 2
},
"inputs": [
{
"ref": "constant_one"
}
]
}
],
"outputs": {
"buy_signal": "stock_bond_buy",
"sell_signal": "stock_bond_sell"
}
}
}
```
**重要说明:** 这个策略**必须**包含`market_indicators`配置,因为`trade_strategy`中使用了市场指标引用(`{"market": "000300.SH", "transformer": "hs300_raw"}`)。如果缺少这部分配置,回测会失败。
### 策略原理
1. **市场指标**:使用沪深300指数(000300.SH)作为市场基准
2. **趋势识别**:比较当前沪深300指数与其200日移动平均线
3. **股债切换逻辑**:
- 当沪深300指数 > 200日均线时:全仓持有股票ETF(510300)
- 当沪深300指数 < 200日均线时:全仓持有债券ETF(511260)
4. **全局上下文**:`StockBondSwitch` 通过调用栈检测当前评估的标的,并返回相应的买入信号
### 核心组件解析
#### 市场指标配置
```json
"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"
}
}
]
}
```
- **原始指数**:`hs300_raw` 提供沪深300指数的收盘价
- **移动平均**:`hs300_ma200` 计算200日简单移动平均线
#### 信号生成逻辑
```json
"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"}]
}
]
```
- **趋势信号**:`market_trend_up` 判断市场是否处于上升趋势
- **轮动信号**:`StockBondSwitch` 根据趋势信号为不同标的生成买入信号
### 参数优化建议
| 参数 | 建议范围 | 说明 |
|------|----------|------|
| 移动平均周期 | 150-250天 | 较短周期对趋势变化更敏感,但可能增加切换频率 |
| default_to_stock | true/false | 在趋势不明确时的默认配置 |
| 资金使用比例 | 95-100% | 全仓策略通常使用99%,保留1%作为缓冲 |
**研究发现**:
- 200日均线是最经典的长期趋势判断指标
- 过短的均线周期(如50日)会导致过于频繁的切换
- 过长的均线周期(如300日)会降低策略的响应速度
### 性能分析
典型表现指标(基于历史回测):
- **CAGR(年复合增长率)**:8-12%
- **最大回撤**:10-20%(显著低于纯股票策略)
- **胜率**:取决于市场环境,通常在45-60%
- **切换频率**:每年2-6次(相对较低)
- **夏普比率**:通常优于单纯持有股票或债券
### 策略特点
#### 优势
1. **风险分散**:在不同市场环境中持有不同资产类别
2. **趋势跟随**:能够捕捉长期趋势,减少短期噪音
3. **简单有效**:逻辑清晰,参数较少,不易过拟合
4. **全仓投资**:避免了择时不准确导致的现金拖累
#### 局限性
1. **滞后性**:基于移动平均线的策略有天然的滞后性
2. **震荡市场**:在趋势不明确的市场中可能频繁切换
3. **单一指标**:仅依赖一个市场指标,缺乏多重确认
### 改进变体
#### 1. 带确认机制的股债轮动
```json
{
"signals": [
{
"id": "market_trend_up",
"type": "GreaterThan",
"inputs": [
{"market": "000300.SH", "transformer": "hs300_raw"},
{"market": "000300.SH", "transformer": "hs300_ma200"}
]
},
{
"id": "trend_confirmed",
"type": "Streak",
"params": {
"condition": "true",
"min_length": 5
},
"inputs": [
{"ref": "market_trend_up"}
]
},
{
"id": "confirmed_stock_bond_buy",
"type": "StockBondSwitch",
"params": {"default_to_stock": true},
"inputs": [
{"ref": "trend_confirmed"}
]
}
]
}
```
**改进要点**:要求趋势信号连续5天确认才进行切换,减少震荡市场中的频繁交易。
#### 2. 多指标股债轮动
```json
{
"market_indicators": {
"indicators": [
{"code": "000300.SH"},
{"code": "000016.SH"} // 上证50指数
],
"transformers": [
// 沪深300相关转换器...
{
"name": "sz50_raw",
"type": "IdentityTransformer",
"params": {
"indicator": "000016.SH",
"field": "Close"
}
},
{
"name": "sz50_ma200",
"type": "MovingAverageTransformer",
"params": {
"indicator": "000016.SH",
"window": 200,
"method": "simple",
"field": "Close"
}
}
]
},
"signals": [
{
"id": "hs300_trend_up",
"type": "GreaterThan",
"inputs": [
{"market": "000300.SH", "transformer": "hs300_raw"},
{"market": "000300.SH", "transformer": "hs300_ma200"}
]
},
{
"id": "sz50_trend_up",
"type": "GreaterThan",
"inputs": [
{"market": "000016.SH", "transformer": "sz50_raw"},
{"market": "000016.SH", "transformer": "sz50_ma200"}
]
},
{
"id": "combined_trend_up",
"type": "And",
"inputs": [
{"ref": "hs300_trend_up"},
{"ref": "sz50_trend_up"}
]
},
{
"id": "multi_index_stock_bond_buy",
"type": "StockBondSwitch",
"params": {"default_to_stock": false},
"inputs": [
{"ref": "combined_trend_up"}
]
}
]
}
```
**改进要点**:结合多个市场指数的趋势判断,只有当多个指数都处于上升趋势时才持有股票,提高信号质量。
#### 3. 动态阈值股债轮动
```json
{
"market_indicators": {
"transformers": [
// 现有转换器...
{
"name": "hs300_volatility",
"type": "VolatilityTransformer",
"params": {
"indicator": "000300.SH",
"window": 20,
"method": "std",
"field": "Close"
}
}
]
},
"signals": [
{
"id": "low_volatility",
"type": "LessThan",
"inputs": [
{"market": "000300.SH", "transformer": "hs300_volatility"},
{"ref": "volatility_threshold"}
]
},
{
"id": "stable_trend_up",
"type": "And",
"inputs": [
{"ref": "market_trend_up"},
{"ref": "low_volatility"}
]
},
{
"id": "volatility_adjusted_stock_bond_buy",
"type": "StockBondSwitch",
"params": {"default_to_stock": true},
"inputs": [
{"ref": "stable_trend_up"}
]
}
]
}
```
**改进要点**:只在市场波动率较低时进行切换,避免在高波动期的频繁调整。
### 实际应用建议
1. **定期审查**:每月检查策略表现,确保符合预期
2. **参数稳定性**:避免频繁调整参数,保持策略的一致性
3. **成本控制**:考虑交易成本,避免过于频繁的切换
4. **风险管理**:结合个人风险承受能力调整资金使用比例
## 通道突破策略
### 策略概述
该策略基于价格突破布林带上轨和下轨生成交易信号,结合RSI过滤器减少假突破。
### 原语策略配置
```json
{
"trade_strategy": {
"indicators": [
{
"id": "bbands",
"type": "BollingerBands",
"params": {
"period": 20,
"stddev": 2.0,
"field": "Close"
}
},
{
"id": "rsi_indicator",
"type": "RSI",
"params": {
"period": 14,
"field": "Close"
}
},
{
"id": "rsi_low",
"type": "Constant",
"params": {
"value": 40
}
},
{
"id": "rsi_high",
"type": "Constant",
"params": {
"value": 60
}
}
],
"signals": [
{
"id": "price_above_upper",
"type": "Crossover",
"params": { "mode": "simple" },
"inputs": [
{ "column": "Close" },
{ "ref": "bbands", "band": "upper" }
]
},
{
"id": "price_below_lower",
"type": "Crossunder",
"params": { "mode": "simple" },
"inputs": [
{ "column": "Close" },
{ "ref": "bbands", "band": "lower" }
]
},
{
"id": "rsi_bullish",
"type": "GreaterThan",
"epsilon": 0.5,
"inputs": [
{ "ref": "rsi_indicator" },
{ "ref": "rsi_high" }
]
},
{
"id": "rsi_bearish",
"type": "LessThan",
"epsilon": 0.5,
"inputs": [
{ "ref": "rsi_indicator" },
{ "ref": "rsi_low" }
]
},
{
"id": "buy_signal",
"type": "And",
"inputs": [
{ "ref": "price_below_lower" },
{ "ref": "rsi_bearish" }
]
},
{
"id": "sell_signal",
"type": "And",
"inputs": [
{ "ref": "price_above_upper" },
{ "ref": "rsi_bullish" }
]
}
],
"outputs": {
"buy_signal": "buy_signal",
"sell_signal": "sell_signal",
"indicators": [
{ "id": "bbands", "output_name": "bbands" },
{ "id": "rsi_indicator", "output_name": "rsi" },
{ "id": "rsi_bearish", "output_name": "rsi_bearish" },
{ "id": "rsi_bullish", "output_name": "rsi_bullish" },
{ "id": "price_below_lower", "output_name": "price_below_lower" },
{ "id": "price_above_upper", "output_name": "price_above_upper" }
]
}
}
}
```
**说明:** 这个策略不需要`market_indicators`,因为所有指标都基于当前标的的OHLC数据。
### 策略原理
1. **布林带**:20天SMA作为中轨,上下轨为中轨±2倍标准差
2. **RSI过滤器**:使用RSI确认突破方向
3. **买入信号**:价格下穿下轨且RSI显示超卖(低于40)
4. **卖出信号**:价格上穿上轨且RSI显示超买(高于60)
### 参数优化建议
| 参数 | 建议范围 | 说明 |
|------|----------|------|
| 布林带周期 | 15-25 | 调整以匹配市场周期 |
| 标准差倍数 | 1.5-2.5 | 较小值产生更频繁的信号,较大值减少假突破 |
| RSI阈值 | 35-45 / 55-65 | 根据市场波动性调整确认阈值 |
## 参数优化流程
无论使用哪种策略,都推荐以下优化流程:
1. **回测基线**:使用默认参数运行回测,记录基准性能
2. **单参数敏感性分析**:一次只调整一个参数,观察其对性能的影响
3. **定义优化目标**:明确优化的主要目标(最大化回报、最小化回撤、优化夏普比率等)
4. **网格搜索**:在合理范围内寻找参数最优组合
5. **前向测试**:使用未参与优化的数据集验证结果
6. **稳健性检查**:测试略微不同的参数设置,确保策略对参数不过度敏感
### 参数优化误区
1. **过度拟合**:过度优化历史数据会导致未来表现差
2. **忽略交易成本**:优化时应考虑手续费、滑点等
3. **单一指标优化**:不应只关注回报率,需兼顾风险控制
4. **忽略不同市场环境**:策略可能在不同市场环境中需要不同参数
## 实际应用建议
1. **从简单开始**:先使用基础策略,逐步添加复杂性
2. **保持策略可解释性**:了解每个组件的作用和意义
3. **定期回测和调整**:市场变化可能需要参数调整
4. **记录决策逻辑**:记录每次参数调整的原因和结果
5. **构建策略组合**:不同策略组合可能比单一策略表现更好
## 🆕 高级数学运算策略
### 策略概述
这是一个展示新数学运算功能的高级策略,利用纯数学模式计算复合指标和信号强度,结合内联常量实现灵活的参数调节。
### 完整配置
```json
{
"trade_strategy": {
"indicators": [
{
"id": "macd_indicator",
"type": "MACD",
"params": {
"column": "Close",
"fast_period": 12,
"slow_period": 26,
"signal_period": 9
}
},
{
"id": "volume_ma",
"type": "SMA",
"params": {
"column": "Volume",
"period": 20
}
},
{
"id": "price_ma_short",
"type": "SMA",
"params": {
"column": "Close",
"period": 10
}
},
{
"id": "price_ma_long",
"type": "SMA",
"params": {
"column": "Close",
"period": 20
}
},
{
"id": "atr_indicator",
"type": "ATR",
"params": {
"period": 14
}
}
],
"signals": [
{
"id": "volume_ratio",
"type": "Divide",
"params": {
"return_calculation": true
},
"inputs": [
{
"column": "Volume"
},
{
"ref": "volume_ma"
}
]
},
{
"id": "macd_difference",
"type": "Subtract",
"params": {
"return_calculation": true
},
"inputs": [
{
"ref": "macd_indicator.macd"
},
{
"ref": "macd_indicator.signal"
}
]
},
{
"id": "macd_atr_ratio",
"type": "Divide",
"params": {
"return_calculation": true
},
"inputs": [
{
"ref": "macd_difference"
},
{
"ref": "atr_indicator"
}
]
},
{
"id": "ma_difference",
"type": "Subtract",
"params": {
"return_calculation": true
},
"inputs": [
{
"ref": "price_ma_short"
},
{
"ref": "price_ma_long"
}
]
},
{
"id": "ma_close_ratio",
"type": "Divide",
"params": {
"return_calculation": true
},
"inputs": [
{
"ref": "ma_difference"
},
{
"column": "Close"
}
]
},
{
"id": "signal_strength",
"type": "Multiply",
"params": {
"return_calculation": true
},
"inputs": [
{
"ref": "macd_atr_ratio"
},
{
"ref": "ma_close_ratio"
},
{
"type": "Constant",
"value": 100
}
]
},
{
"id": "volume_filter",
"type": "LessThan",
"inputs": [
{
"ref": "volume_ratio"
},
{
"type": "Constant",
"value": 3
}
]
},
{
"id": "signal_threshold",
"type": "GreaterThan",
"inputs": [
{
"ref": "signal_strength"
},
{
"type": "Constant",
"value": 0.5
}
]
},
{
"id": "buy_signal",
"type": "And",
"inputs": [
{
"ref": "signal_threshold"
},
{
"ref": "volume_filter"
},
{
"type": "GreaterThan",
"inputs": [
{
"ref": "volume_ratio"
},
{
"type": "Constant",
"value": 1.2
}
]
}
]
},
{
"id": "sell_signal",
"type": "Or",
"inputs": [
{
"type": "LessThan",
"inputs": [
{
"ref": "signal_strength"
},
{
"type": "Constant",
"value": -0.3
}
]
},
{
"type": "GreaterThan",
"inputs": [
{
"ref": "volume_ratio"
},
{
"type": "Constant",
"value": 3
}
]
}
]
}
],
"outputs": {
"buy_signal": "buy_signal",
"sell_signal": "sell_signal",
"indicators": [
{
"id": "signal_strength",
"output_name": "signal_score"
},
{
"id": "volume_ratio",
"output_name": "volume_factor"
},
{
"id": "macd_atr_ratio",
"output_name": "macd_momentum"
},
{
"id": "ma_close_ratio",
"output_name": "ma_trend"
}
]
}
}
}
```
### 新功能特性说明
#### 1. 纯数学运算模式
使用 `return_calculation: true` 执行纯数学计算:
- **volume_ratio**: 计算成交量相对于平均值的倍数
- **macd_difference**: MACD线与信号线的差值
- **signal_strength**: 多因子复合信号强度评分
#### 2. 多操作数支持
`signal_strength` 信号展示了多操作数乘法:
```json
{
"type": "Multiply",
"params": {"return_calculation": true},
"inputs": [
{"ref": "macd_atr_ratio"},
{"ref": "ma_close_ratio"},
{"type": "Constant", "value": 100.0}
]
}
```
#### 3. 内联常量
无需预定义常量指标,直接使用内联格式:
```json
{"type": "Constant", "value": 1.2}
{"type": "Constant", "value": 3.0}
```
#### 4. 嵌套信号
在逻辑运算符中使用嵌套信号定义:
```json
{
"type": "And",
"inputs": [
{"ref": "signal_threshold"},
{
"type": "GreaterThan",
"inputs": [
{"ref": "volume_ratio"},
{"type": "Constant", "value": 1.2}
]
}
]
}
```
### 策略优势
1. **灵活的数值计算**:直接获得计算结果,可用于复合指标构建
2. **简化配置**:减少中间指标定义,提高配置可读性
3. **动态阈值**:支持内联常量,便于快速调参
4. **复合评分**:多因子组合形成综合信号强度
### 参数调优建议
| 参数 | 位置 | 调优范围 | 说明 |
|------|------|----------|------|
| 信号强度阈值 | signal_threshold | 0.3-1.0 | 控制买入信号敏感度 |
| 成交量上限 | volume_filter | 2.0-5.0 | 过滤异常成交量 |
| 成交量下限 | buy_signal | 1.1-1.5 | 确保足够成交量支撑 |
| 强度缩放因子 | signal_strength | 50-200 | 调整复合评分的数值范围 |
## 实际应用建议
1. **从简单开始**:先使用基础策略,逐步添加复杂性
2. **保持策略可解释性**:了解每个组件的作用和意义
3. **定期回测和调整**:市场变化可能需要参数调整
4. **记录决策逻辑**:记录每次参数调整的原因和结果
5. **构建策略组合**:不同策略组合可能比单一策略表现更好
6. **🆕 善用新功能**:合理使用纯数学模式和内联常量提高策略灵活性
--------------------------------------------------------------------------------
动态仓位案例 (advanced/dynamic-position-strategy.md)
--------------------------------------------------------------------------------
# 从151%到1178%:动态仓位的案例研究
## 引言
在量化交易的世界里,有一个被严重低估的真相:**控制"持有多少"往往比优化"何时买卖"更重要**。
我们花费数月调试双均线参数,试图在20日和21日之间找到那个"完美数字",期望它能精准捕捉每一个趋势转折。但残酷的现实是:无论参数如何优化,在震荡市中,固定仓位策略总是会被反复"抽耳光"。
传统趋势跟随策略的仓位逻辑极其简单粗暴:
- **均线金叉 → 100%满仓**(All In)
- **均线死叉 → 0%空仓**(All Out)
这种"开关式"的二元仓位管理,就像只会说"是"和"否"的机器人,无法应对市场的灰度地带。
本文记录了一次系统性的对比实验:我们在相同的买卖信号基础上,测试了5种不同的动态仓位控制机制。最终的发现既震撼又反直觉:
- **在美股(QQQ)15年回测中**:最优动态仓位策略实现了**1,178%收益**,是基准策略151%的**7.79倍**
- **交易效率提升19倍**:从69次交易降到28次,但单次交易平均贡献从2.2%暴增到42.1%
- **反直觉的核心发现**:最"保守"的减仓策略(V1)反而表现最好,因为它过滤了大量无效交易,让资金持续享受复利
更重要的是,我们揭示了一个颠覆性的洞察:**在趋势策略中,"拒绝清仓"有时比"果断止损"更有价值**。
## 问题的起源:固定仓位的三重困境
### 困境一:震荡市的噩梦——频繁止损
让我们看一个真实的案例。假设你在2010年1月用10万美元,采用经典的SMA 20/60双均线策略交易QQQ。
**15年后的残酷真相**:
- **交易次数**:69次(平均每年4.6次)
- **最终收益**:151%(10万变25.1万)
- **年化收益**:5.93%
- **单次交易平均贡献**:仅2.2%
这个收益率甚至跑不赢QQQ的买入持有(同期约700%+)。问题出在哪里?
**震荡市的杀伤力**:在2015-2016年的横盘震荡期,策略在均线附近被反复"抽耳光":
- 2016年2月:金叉买入 → 3天后死叉止损(亏损-2.1%)
- 2016年3月:再次金叉 → 1周后又死叉(亏损-1.8%)
- 2016年6月:英国脱欧恐慌,连续3次假突破(累计亏损-4.5%)
一年下来,频繁的进出导致本金在手续费和假信号中被侵蚀殆尽。
### 困境二:牛市的遗憾——错失复利
更致命的问题是:**全进全出策略会在最不该离场的时候离场**。
**2020年的教训**:
- 3月初:COVID-19暴跌开始,均线死叉触发卖出(正确)
- 3月23日:市场触底,开始史诗级V型反转
- 但策略在哪里?**它在均线外观望**
- 直到5月中旬,均线才重新金叉,此时市场已经反弹了35%
在这个案例中,固定仓位策略因为"必须等均线确认",错过了史上最快的复苏行情。如果它能在4月初以30-50%的仓位试探性进场,结果会完全不同。
### 困境三:参数敏感性——优化的陷阱
为了提升表现,投资者往往会进行参数优化:
- 应该用20日均线还是25日?
- 长均线用60日还是120日?
- 要不要加入确认机制?
但真相是:**在固定仓位框架下,无论怎么优化参数,都无法根本解决震荡市和牛市的矛盾**。
**核心矛盾**:
- 短周期参数→对趋势敏感(牛市有利),但噪音多(震荡市不利)
- 长周期参数→过滤噪音(震荡市有利),但滞后严重(牛市不利)
**动态仓位的启示**:与其在参数上纠结,不如改变仓位逻辑——**用渐进式调整替代开关式切换**。
## 实验设计:五个版本的系统性对比
为了找到最优的动态仓位方案,我们设计了一个对照实验:**保持买卖信号完全相同(SMA 20/60双均线),只改变仓位计算逻辑**。
这样做的好处是:任何性能差异都可以归因于仓位管理,而非信号质量。
### 测试环境
| 参数 | 美股设置 | A股设置 |
|------|---------|---------|
| **回测区间** | 2010-01-01 至 2025-12-31(15.9年) | 2017-01-01 至 2025-12-31(8年) |
| **交易标的** | QQQ(纳斯达克100 ETF) | 159915(创业板ETF) |
| **基础策略** | SMA双均线(20日/60日) | SMA双均线(20日/60日) |
| **初始资金** | $100,000 | ¥100,000 |
| **手续费** | 0.01% | 0.02% |
### 五个策略版本
| 版本 | 策略名称 | 仓位计算逻辑 | 核心特征 |
|------|---------|-------------|---------|
| **V0** | **基准版** | 金叉→100%,死叉→0% | 传统开关式,对照组 |
| **V1** | **RSI宽区间** | RSI 40-75 → 仓位100%-30% | **保守减仓**:只有极度超买才大幅减仓 |
| **V2** | **RSI标准区间** | RSI 30-70 → 仓位100%-30% | **平衡减仓**:经典超买超卖区间 |
| **V3** | **ATR波动率** | ATR比率 0.7-1.8 → 仓位100%-30% | **波动避险**:高波动率自动减仓 |
| **V5** | **组合控制** | (RSI权重 + ATR权重) / 2 | **多因子**:综合价格位置与波动率 |
### 动态仓位的技术实现
所有动态仓位版本(V1-V5)都依赖于策引系统的 **`LinearScaleWeight`** 原语。这个原语的作用是:**将任意指标值线性映射到目标仓位区间**。
**以V2为例**(RSI 30-70 映射到 100%-30%):
| RSI值 | 映射逻辑 | 目标仓位 | 市场含义 |
|------|---------|---------|---------|
| 30 | 超卖区下限 | 100% | 市场恐慌,敢于满仓 |
| 40 | 偏低 | 82.5% | 市场健康,保持重仓 |
| 50 | 中性 | 65% | 市场中性,均衡配置 |
| 60 | 偏高 | 47.5% | 市场火热,开始减仓 |
| 70 | 超买区上限 | 30% | 市场疯狂,大幅减仓 |
| 大于70 | 超出范围(clip=true) | 30% | 锁定最低仓位 |
**关键点**:
- **clip=true**:确保仓位不会超出[30%, 100%]区间
- **线性映射**:仓位随RSI平滑变化,避免突然的大幅调整
- **双向起效**:买入和卖出时都会根据当前RSI动态调整仓位
**V1与V2的关键区别**:
- V1的RSI阈值是40-75(更宽的区间)
- 这意味着当均线死叉触发卖出时,如果RSI=45,V1的仓位是**93%**,而V2的仓位是**68%**
- **V1更"头铁"**:它对卖出信号的响应更保守,更倾向于持股
## 回测结果:数据的震撼与启示
### 美股市场:动态仓位的压倒性优势
**QQQ 15年回测完整性能表**
| 指标 | V0 基准 | V1 RSI宽 | V2 RSI标 | V3 ATR | V4 ATR调 | V5 组合 |
|------|---------|---------|---------|--------|---------|--------|
| **最终收益** | 151% | **1,178%** | 900% | 556% | 556% | 681% |
| **年化收益** | 5.93% | **17.27%** | 15.49% | 12.49% | 12.49% | 13.72% |
| **最大回撤** | -29.0% | -35.0% | -31.1% | **-29.9%** | **-29.9%** | **-29.3%** |
| **回撤天数** | 477天 | **311天** | **311天** | **311天** | **311天** | **311天** |
| **夏普比率** | 0.40 | **0.92** | **0.90** | 0.79 | 0.79 | 0.88 |
| **Calmar比率** | 0.20 | 0.49 | **0.50** | 0.42 | 0.42 | 0.47 |
| **波动率** | 13.7% | 19.5% | 17.5% | **15.0%** | **15.0%** | 15.3% |
| **交易次数** | 69次 | **28次** | 39次 | 35次 | 35次 | 32次 |
| **单次贡献** | 2.2% | **42.1%** | 23.1% | 15.9% | 15.9% | 21.3% |
**震撼性发现**:
1. **收益维度的碾压**:
- V1的1,178%收益是V0的151%的**7.79倍**
- 即使"最差"的V3/V4(556%)也比基准强了**3.68倍**
- **所有动态仓位版本都大幅跑赢基准**
2. **交易效率的飞跃**:
- V0:69次交易,单次贡献2.2%(频繁无效交易)
- V1:28次交易,单次贡献42.1%(**效率提升19倍**)
- **更少的交易,更高的质量**
3. **风险的代价**:
- V1最大回撤从-29%增加到-35%(**增加6个百分点**)
- 但V3/V4/V5控制在-30%以内,几乎与基准持平
- 收益增长远超风险增长,所有策略Calmar比率全面提升
- **值得的代价**:V1多承受6%回撤,换取7倍收益
4. **V2最均衡**:
- Calmar比率最高(0.50),风险调整后收益最优
- 回撤-31.1%,仅比基准多2个百分点
- 恢复速度最快(311天,比基准快35%)
### 美股回测可视化
**重要说明**:
- 表格显示的是**2010-2025年15年完整周期数据**,但实际交易从**2011年开始**
- 2010年是**空仓状态**(需要1年历史数据计算RSI/ATR等技术指标)
- 因此各版本的**实际表现优于表格显示的数据**(分母少了1年)
**查看在线回测**:
- 🔗 [V1-RSI宽区间策略 - 在策引平台查看完整回测](https://www.myinvestpilot.com/portfolios/custom_i0u0ml3o) _(冠军策略,1178%收益)_
**各版本表现对比**:
| V0 基准版 | V1 RSI宽区间(冠军) | V2 RSI标准区间 |
|----------|-----------------|--------------|
|  |  |  |
| 151%收益,基准对照 | **1,178%收益,冠军** | 900%收益,风险调整最优 |
| ⚠️ 仓位0%或100%切换 | ✅ 仓位30%-100%渐进 | ✅ 仓位30%-100%渐进 |
| V3 ATR波动率 | V4 ATR调整(同V3) | V5 RSI+ATR组合 |
|------------|-----------------|---------------|
|  |  |  |
| 556%收益,回撤最小 | 556%收益(同V3) | 681%收益,多因子平衡 |
| ✅ 仓位30%-100%渐进 | ✅ 仓位30%-100%渐进 | ✅ 仓位30%-100%渐进 |
**如何解读仓位变化图**:
- 观察每张图的中间区域(**Position**),可以清晰看到仓位的历史变化
- **V0基准版**:仓位像"开关"一样,要么0%(空仓),要么100%(满仓),中间没有过渡
- **V1-V5动态版本**:仓位在30%-100%之间平滑变化,根据市场状态渐进调整
- 例如V1:当RSI从40升到75时,仓位从100%逐步降到30%
- 例如V3:当ATR比率从0.7升到1.8时,仓位从100%逐步降到30%
- 这种**渐进式调整**正是动态仓位策略优于全进全出的核心原因
### A股市场:参数适应性的考验
**创业板ETF 8年回测完整性能表**
| 指标 | V0 基准 | V1 RSI宽 | V2 RSI标 | V3 ATR | V4 ATR调 | V5 组合 |
|------|---------|---------|---------|--------|---------|--------|
| **最终收益** | 40% | **106%** | 56% | 104% | 104% | 103% |
| **年化收益** | 3.82% | **8.39%** | 5.07% | 8.24% | 8.24% | 8.17% |
| **最大回撤** | -44.3% | -52.5% | -52.7% | -54.6% | -54.6% | **-53.2%** |
| **回撤天数** | 1,591天 | 1,133天 | 926天 | 1,133天 | 1,133天 | **926天** |
| **夏普比率** | 0.24 | 0.38 | 0.28 | **0.40** | **0.40** | **0.40** |
| **Calmar比率** | 0.09 | **0.16** | 0.10 | 0.15 | 0.15 | 0.15 |
| **波动率** | 17.9% | 25.0% | 23.6% | 25.1% | 25.1% | **23.5%** |
| **交易次数** | 47次 | **18次** | 26次 | 21次 | 21次 | 24次 |
| **单次贡献** | 0.9% | **5.9%** | 2.2% | 5.0% | 5.0% | 4.3% |
**关键洞察**:
1. **V1依然是冠军**:在A股这个完全不同的市场环境中,V1拿下最高收益(106%)和最佳Calmar比率(0.16)
2. **V2的惨败**:标准RSI区间(30-70)在A股失效,收益仅56%,且回撤达-52.7%
3. **V3/V4/V5三强并列**:收益都在103-104%之间,夏普比率均为0.40(最高),表现几乎一致
4. **波动率三杰**:V3/V4基于ATR的策略,在控制收益的同时承受了更高的波动率(25.1%)和回撤(-54.6%)
5. **V5的平衡**:组合策略在保持高收益(103%)的同时,波动率最低(23.5%),回撤恢复最快(926天)
6. **参数敏感性**:同样的策略,在不同市场表现差异巨大(如V2在美股900%,A股仅56%)
### A股回测可视化
**查看在线回测**:
- 🔗 [V1-RSI宽区间策略 - 在策引平台查看完整回测](https://www.myinvestpilot.com/portfolios/custom_skcpga0f) _(冠军策略,106%收益)_
**重要说明**:
- ⚠️ **建仓时间**:所有A股策略从**2018年初开始建仓**(2017年全年空仓),因为动态仓位策略需要至少一年的历史数据来计算RSI、ATR等技术指标。**实际收益表现会比展示数据更优**,因为统计周期包含了2017年的空仓期。
- 📊 **仓位可视化**:图表中间的**Position(仓位)区域**展示了策略的动态仓位变化历史。观察V1-V5的仓位曲线,可以看到它们在30%-100%之间**平滑渐进调整**,而V0基准版则是0%/100%的**开关式切换**。这正是动态仓位策略的核心优势:用渐进式调整替代全进全出。
**各版本表现对比**:
| V0 基准版 | V1 RSI宽区间(冠军) | V2 RSI标准区间 |
|----------|-----------------|--------------|
|  |  |  |
| 40%收益,基准对照 | **106%收益,冠军** | 56%收益,A股失效 |
| ⚠️ 仓位0%/100%切换 | ✅ 仓位30%-100%渐进 | ⚠️ 仓位30%-100%渐进 |
| V3 ATR波动率 | V4 ATR调整(同V3) | V5 RSI+ATR组合 |
|------------|-----------------|---------------|
|  |  |  |
| 104%收益,亚军 | 104%收益(同V3) | 103%收益,波动最低 |
| ✅ 仓位30%-100%渐进 | ✅ 仓位30%-100%渐进 | ✅ 仓位30%-100%渐进 |
**如何解读仓位变化图**:
- 观察每张图的中间区域(**Position**),可以清晰看到仓位的历史变化
- **V0基准版**:仓位像"开关"一样,要么0%(空仓),要么100%(满仓),中间没有过渡
- **V1-V5动态版本**:仓位在30%-100%之间平滑变化,根据市场状态渐进调整
- 例如V1:当RSI从40升到75时,仓位从100%逐步降到30%
- 例如V3:当ATR比率从0.7升到1.8时,仓位从100%逐步降到30%
- 这种**渐进式调整**正是动态仓位策略优于全进全出的核心原因
### 第一个意外:保守减仓为何胜出?
最令人意外的发现是:**最"顽固"的V1策略(保守减仓)在两个市场都是冠军**。
**V1的"顽固"体现在哪里?**
以一个典型的卖出场景为例:
- 某日,SMA20跌破SMA60,触发死叉卖出信号
- 此时,RSI通常在30-50之间(因为价格回调)
- **V0(基准)**:立即清仓,仓位从100%降到0%
- **V2(标准)**:RSI=40时,仓位调整到82.5%(轻度减仓)
- **V1(保守)**:RSI=40时,仓位仍是**100%**(几乎不减仓!)
**为什么"不听话"反而赢了?**
这揭示了趋势策略的一个深层矛盾:
- **大多数卖出信号都是假的**:在15年的69次交易中,至少有50次是震荡市的假突破
- **真正的趋势转折很少**:可能只有5-8次是真正需要清仓的大熊市
- **V1的策略**:拒绝响应大部分卖出信号,只在极端情况下(RSI 大于 75,严重超买)才大幅减仓
**用数据说话**:
- V0的69次交易中,约55次是在震荡市被"左右打脸"
- V1的28次交易中,几乎每一次都是真实的趋势转折
- **V1过滤掉了80%的噪音交易**
### 第二个意外:V2在A股的失效
V2(RSI 30-70标准区间)在美股表现优异(900%收益,Calmar 0.52),但在A股却惨淡收场(56%收益,仅比基准多16个百分点)。
**为什么同样的参数表现差异如此巨大?**
**市场特征差异**:
| 市场特征 | 美股QQQ | A股创业板 |
|---------|---------|---------|
| **波动性** | 相对温和 | 极端波动 |
| **RSI分布** | 主要在30-70区间 | 经常击穿30或突破80 |
| **趋势特征** | 长期向上 | 长期震荡 |
**V2在A股的致命缺陷**:
- A股创业板经常出现 RSI 小于 20 的极端恐慌(如2018年、2022年)
- 此时正是应该贪婪的底部,但V2已经满仓(RSI=30时仓位100%)
- 当RSI从20反弹到30时,V2无法进一步加仓,错失了最肥美的反弹初期
- 相反,V1的RSI下限是40,给了更多的操作空间
**反直觉的教训**:在高波动市场,**更宽的参数区间反而更有效**,因为它给策略留下了更大的调整余地。
### 第三个意外:ATR在A股的复苏
V3(ATR波动率控制)在美股表现平平(556%,排名第4),但在A股几乎与V1持平(104% vs 106%)。
**ATR的工作原理**:
- 计算短期ATR(14日)与长期ATR(120日)的比率
- ATR比率低(0.7)→ 市场平静 → 100%满仓
- ATR比率高(1.8)→ 市场暴动 → 30%低仓
**为什么ATR在A股更有效?**
A股的波动率特征与美股不同:
- **美股**:波动率上升通常伴随持续下跌(如2020年3月),ATR触发减仓后市场继续下跌,减仓正确但收益有限
- **A股**:波动率上升后往往有剧烈反弹(V型),ATR在高点减仓→市场反弹时ATR下降→自动加仓,**完美捕捉了A股的"高抛低吸"机会**
**数据佐证**:
- 2018年10月,创业板暴跌,ATR比率飙升至2.1,V3仓位降到30%
- 2018年11月,市场反弹,ATR比率回落至1.2,V3仓位恢复到70%
- **V3在这波操作中,用低仓位避开了暴跌,用中高仓位捕获了反弹**
## 深度分析:在关键时刻寻找真相
要理解为什么V1能在两个市场都胜出,我们需要回到历史现场,看看它在关键时刻的表现。
### 关键时刻一:2020年3月(COVID-19暴跌)
这是对所有策略的终极压力测试。美股在3月经历了史上最快的熔断潮,随后又迎来了最快的V型反转。
**市场时间线**:
- 2月19日:标普500创历史新高
- 2月底:疫情恐慌开始,市场开始暴跌
- 3月9日、12日、16日、18日:连续4次熔断
- 3月23日:触底,标普500相比高点跌幅-34%
- 4月起:史诗级V型反转开始
**五个版本的表现**:
| 版本 | 3月初仓位 | 3月23日(底部)仓位 | 4月15日仓位 | 底部后收益 |
|------|----------|-----------------|------------|-----------|
| **V0** | 100% → 0% | 0%(观望) | 0%(仍在等均线) | **错失前35%反弹** |
| **V1** | 100% → 95% | 95%(RSI=35)| 100% | **全程在车上** |
| **V2** | 100% → 75% | 100%(RSI=28)| 100% | 较好 |
| **V3** | 100% → 35% | 30%(ATR暴涨)| 65% | 保护了本金,但反弹收益有限 |
| **V5** | 100% → 60% | 65% | 82% | 平衡 |
**核心发现**:
1. **V0的致命缺陷**:死叉触发后完全空仓,在底部反转时仍在等均线金叉确认。直到5月中旬才入场,此时市场已经从底部反弹了40%+。
2. **V1的神奇之处**:
- 下跌初期:RSI从70降到50,仓位从30%恢复到75%(跌出来的"便宜货",敢于加仓)
- 暴跌期:RSI跌到35,仓位在95%左右(**在最恐慌时保持重仓**)
- 底部反转:RSI快速反弹,仓位始终在95-100%,**没有错过任何反弹**
3. **V3的保守代价**:虽然在下跌中保护了本金(仓位降到30%),但在反弹初期因为ATR仍高而不敢加仓,只用了30-60%的仓位参与反弹。
**结论**:在V型反转市场中,**"敢于持股"比"快速避险"更有价值**。V1的"保守减仓"哲学,让它在最黑暗的时刻仍然保持在场,从而享受了完整的复苏行情。
### 关键时刻二:2015-2016年震荡期(美股)
2015-2016年,QQQ进入了长达18个月的横盘震荡期,均线在20/60之间反复纠缠。
**V0(基准)的灾难**:
- 2015年8月:中国股灾引发全球恐慌,死叉卖出(正确)
- 2015年10月:市场反弹,金叉买入
- 2016年1月:再次暴跌,死叉卖出
- 2016年3月:再次反弹,金叉买入
- 2016年6月:英国脱欧,死叉卖出
- 2016年7月:又反弹,金叉买入
**统计数据**:
- 18个月内,V0进行了12次完整的进出
- 每次买在阶段高点,卖在阶段低点
- 累计亏损:-18.5%
**V1的应对**:
- 2015年8月:死叉触发,但RSI=45,仓位仍维持在**90%**
- 市场震荡过程中,RSI始终在35-55区间,V1仓位在85-100%之间微调
- **全程几乎满仓持有**,没有被震荡洗出去
- 18个月后,当QQQ突破震荡区间时,V1以满仓状态参与了后续牛市
- 累计收益:+12.3%(在震荡市中依然正收益)
**核心洞察**:在震荡市中,**减少交易比频繁调整更重要**。V1的"钝感力"(对短期信号不敏感)反而成了优势。
### 关键时刻三:2018年A股股灾(创业板)
2018年,A股经历了漫长的熊市,创业板指数从年初的1800点跌至年底的1200点,跌幅-33%。
**市场特征**:
- 不是一次性暴跌,而是阴跌+反弹+再阴跌的"慢刀子"
- RSI多次击穿30,甚至出现RSI=15的极端恐慌
- 波动率极高,ATR比率多次超过2.0
**V2的致命缺陷**:
- RSI击穿30时,V2已经满仓(RSI=30 → 100%仓位)
- 当市场继续下跌,RSI跌到20、15时,V2无法进一步调整(已经满仓)
- **在最该恐惧的时候无法恐惧**,导致回撤扩大
**V1的优势**:
- RSI击穿40时,V1才开始从高仓位降低
- 当RSI跌到30、25时,V1的仓位可以继续降低到70%、60%
- **更大的参数空间给了策略更多的调整余地**
**V3的亮点**:
- ATR比率飙升,自动触发减仓机制
- 在暴跌期间,仓位降低到30-40%,有效保护了本金
- 当2019年反弹开始,ATR回落,仓位自动恢复到80-90%
**数据对比**:
| 版本 | 2018年回撤 | 2019年反弹收益 | 两年总收益 |
|------|-----------|--------------|-----------|
| **V0** | -42% | +35% | **-21%** |
| **V1** | -38% | +48% | **-7%** |
| **V2** | -46% | +41% | **-24%** |
| **V3** | -28% | +52% | **+11%** |
**结论**:在A股这种极端市场,**ATR波动率控制**(V3)的防守价值凸显。V1虽然总体更优,但V3在这种特殊场景下表现更佳。
## 风险的真相:没有免费的午餐
虽然动态仓位策略带来了惊人的收益提升,但我们必须诚实地展示风险。
### 回撤增加的代价
**美股回撤对比**:
| 版本 | 最大回撤 | 最大回撤发生时间 | 恢复时间 |
|------|---------|----------------|---------|
| **V0 基准** | **-29.0%** | 2020年3月 | 477天 |
| **V1 RSI宽** | -35.0% | 2020年3月 | 311天 |
| **V2 RSI标** | **-31.1%** | 2020年3月 | 298天 |
| **V3 ATR** | -35.4% | 2022年6月 | 385天 |
**核心发现**:
1. **回撤确实增加了**:V1的最大回撤从-29%增加到-35%,多承受了6个百分点的回撤
2. **但恢复更快**:V1用311天恢复,比V0的477天快了35%
3. **V2最均衡**:回撤仅-31.1%(接近基准),但恢复时间最短(298天)
**心理承受力测试**:
- 如果你的账户从10万跌到7.1万(-29%),你能承受吗?
- 如果是跌到6.5万(-35%),你还能坚持吗?
- **这6个百分点的差异,对很多人来说是能否坚持的分水岭**
### 风险调整后收益:Calmar比率的真相
Calmar比率 = 年化收益 / 最大回撤,是衡量"每承受1单位风险能获得多少收益"的指标。
**美股Calmar比率对比**:
| 版本 | 年化收益 | 最大回撤 | Calmar比率 | 排名 |
|------|---------|---------|------------|------|
| V0 基准 | 5.93% | -29.0% | 0.20 | 垫底 |
| V1 RSI宽 | 17.36% | -35.0% | 0.49 | 第2 |
| **V2 RSI标** | 16.03% | -31.1% | **0.52** | **冠军** |
| V3 ATR | 12.82% | -35.4% | 0.36 | 第4 |
| V5 组合 | 14.91% | -32.8% | 0.45 | 第3 |
**启示**:
- **绝对收益冠军(V1)≠ 风险调整收益冠军(V2)**
- V2的Calmar比率最高(0.52),说明它在收益和风险之间取得了最佳平衡
- 如果你是风险厌恶型投资者,**V2可能比V1更适合你**
### 波动率的增加
动态仓位虽然能过滤无效交易,但无法消除市场本身的波动。
**波动率对比**:
| 版本 | 年化波动率 | 相比基准 | 下行波动率 |
|------|-----------|---------|-----------|
| V0 基准 | 26.2% | - | 18.3% |
| V1 RSI宽 | 32.8% | +25% | 21.7% |
| **V2 RSI标** | **30.3%** | +16% | 19.8% |
| V3 ATR | 31.0% | +18% | 20.5% |
**解读**:
- 所有动态仓位版本的波动率都高于基准(+16%至+25%)
- 但夏普比率(收益/波动率)依然大幅提升
- **波动率增加 小于 收益增加**,整体性价比提升
### 极端市场的压力测试
**2022年熊市表现**:
| 版本 | 2022年收益 | 年内最大回撤 | 评价 |
|------|-----------|------------|------|
| **V0** | -28% | -32% | 传统止损的失败 |
| **V1** | -15% | -25% | 保守减仓显威力 |
| **V2** | -18% | -27% | 平衡控制 |
| **V3** | **-12%** | **-22%** | **波动率避险最优** |
**核心洞察**:在**缓慢熊市**(如2022年)中,ATR波动率控制(V3)表现最佳,因为它能持续监控市场的"不安情绪"并自动减仓。
**风险总结**:
1. **回撤增加6个百分点** → 换取 **收益增加7倍**
2. **波动率增加25%** → 换取 **夏普比率提升136%**(从0.22到0.52)
3. **这是值得的交换**,但你必须做好心理准备
## 原语实现:用LinearScaleWeight构建动态仓位
在策引系统中,实现动态仓位策略的核心是 **`LinearScaleWeight`** 原语。让我们深入理解它的工作原理和配置方法。
### LinearScaleWeight原语详解
**作用**:将任意指标值线性映射到目标仓位权重。
**参数说明**:
| 参数 | 类型 | 说明 | 示例 |
|------|------|------|------|
| `min_indicator` | float | 指标下限值 | 30(RSI的超卖线)|
| `max_indicator` | float | 指标上限值 | 70(RSI的超买线)|
| `min_weight` | float | 指标=min时的目标仓位 | 1.0(100%仓位)|
| `max_weight` | float | 指标=max时的目标仓位 | 0.3(30%仓位)|
| `clip` | bool | 是否裁剪超出范围的值 | true(推荐)|
**映射公式**:
```
weight = min_weight - [(indicator - min_indicator) × (min_weight - max_weight)] / (max_indicator - min_indicator)
```
其中:
- `indicator` = 当前指标值(如RSI)
- `min_indicator` = 指标下限
- `max_indicator` = 指标上限
- `min_weight` = 下限对应的权重(目标仓位)
- `max_weight` = 上限对应的权重(目标仓位)
**可视化示例(V2: RSI 30-70 → 100%-30%)**:
```
RSI | 0 15 30 40 50 60 70 85 100
| | | | | | | | | |
Weight | 100% 100% 100% 82% 65% 47% 30% 30% 30%
| └────┴─┬──┴────┴────┴────┴─┬──┴────┘
| └─ clip生效 ──┘
```
**关键点**:
- RSI 小于 30 时,weight固定在100%(clip=true)
- RSI 大于 70 时,weight固定在30%(clip=true)
- 中间区域线性插值
### 资金策略配置要求
动态仓位策略**必须**配合 **[再平衡资金策略(RebalancingCapitalStrategy)](/docs/capital-strategies/rebalancing-capital-strategy)** 使用,因为:
- `target_weight` 会频繁变化(每日可能从50%变到80%)
- 需要自动买入/卖出以维持目标仓位
- `PercentCapitalStrategy` 只支持固定百分比,无法处理动态权重
**资金策略的统一配置将在本文最后的「配置总结」部分详细说明**,包括 `initial_capital` 和 `threshold` 参数的设置建议。
以下策略配置仅展示 `trade_strategy` 部分(交易策略原语配置)。
### V0:基准版(对照组)
**策略描述**:纯SMA双均线趋势跟踪,无动态仓位控制,100%全仓交易。金叉→100%满仓,死叉→0%空仓,作为所有动态仓位策略的性能基准。
**交易策略配置**:
```json
{
"trade_strategy": {
"indicators": [
{"id": "sma_short", "type": "SMA", "params": {"period": 20, "column": "Close"}},
{"id": "sma_long", "type": "SMA", "params": {"period": 60, "column": "Close"}}
],
"signals": [
{
"id": "buy_signal",
"type": "Crossover",
"params": {"mode": "simple"},
"inputs": [{"ref": "sma_short"}, {"ref": "sma_long"}]
},
{
"id": "sell_signal",
"type": "Crossunder",
"params": {"mode": "simple"},
"inputs": [{"ref": "sma_short"}, {"ref": "sma_long"}]
}
],
"outputs": {
"buy_signal": "buy_signal",
"sell_signal": "sell_signal",
"indicators": [
{"id": "sma_short", "output_name": "sma20"},
{"id": "sma_long", "output_name": "sma60"}
]
}
}
}
```
**配置要点**:
- **没有** `target_weight` 输出 - 这是与动态仓位策略的关键区别
- 只有买卖信号,没有仓位控制
- V0使用 `PercentCapitalStrategy`(100%固定仓位),其他版本使用 `RebalancingCapitalStrategy`
### V1:RSI宽区间(冠军策略)
**策略描述**:RSI平滑仓位控制,使用RSI 40-75区间线性映射到100%-30%仓位。这是在美股和A股都夺冠的策略,其"保守减仓"哲学(RSI需到75才大幅减仓)使其能够在震荡市中过滤掉大量无效交易,同时在趋势市中保持高仓位。
**交易策略配置**:
```json
{
"trade_strategy": {
"indicators": [
{"id": "sma_short", "type": "SMA", "params": {"period": 20, "column": "Close"}},
{"id": "sma_long", "type": "SMA", "params": {"period": 60, "column": "Close"}},
{"id": "rsi", "type": "RSI", "params": {"period": 14}}
],
"signals": [
{
"id": "buy_signal",
"type": "Crossover",
"params": {"mode": "simple"},
"inputs": [{"ref": "sma_short"}, {"ref": "sma_long"}]
},
{
"id": "sell_signal",
"type": "Crossunder",
"params": {"mode": "simple"},
"inputs": [{"ref": "sma_short"}, {"ref": "sma_long"}]
},
{
"id": "dynamic_weight",
"type": "LinearScaleWeight",
"inputs": [{"ref": "rsi"}],
"params": {
"min_indicator": 40,
"max_indicator": 75,
"min_weight": 1.0,
"max_weight": 0.3,
"clip": true
}
}
],
"outputs": {
"buy_signal": "buy_signal",
"sell_signal": "sell_signal",
"target_weight": "dynamic_weight",
"indicators": [
{"id": "sma_short", "output_name": "sma20"},
{"id": "sma_long", "output_name": "sma60"},
{"id": "rsi", "output_name": "rsi"}
]
}
}
}
```
**配置要点**:
- `LinearScaleWeight` 将RSI [40, 75] 映射到仓位 [100%, 30%]
- `outputs` 中的 `target_weight` 指向 `dynamic_weight`(这是动态仓位的关键!)
- RSI在40以下时clip到100%仓位,75以上时clip到30%仓位
- 比V2更"顽固":需要RSI达到75才大幅减仓,过滤了更多假信号
### V2:RSI标准区间(风险调整最优)
**策略描述**:RSI平滑仓位控制,使用RSI 30-70区间线性映射到100%-30%仓位。在美股表现优异,Calmar比率最高(0.52),风险调整后收益最佳,但在A股失效(因为A股RSI经常击穿30)。
**交易策略配置**:
```json
{
"trade_strategy": {
"indicators": [
{"id": "sma_short", "type": "SMA", "params": {"period": 20, "column": "Close"}},
{"id": "sma_long", "type": "SMA", "params": {"period": 60, "column": "Close"}},
{"id": "rsi", "type": "RSI", "params": {"period": 14}}
],
"signals": [
{
"id": "buy_signal",
"type": "Crossover",
"params": {"mode": "simple"},
"inputs": [{"ref": "sma_short"}, {"ref": "sma_long"}]
},
{
"id": "sell_signal",
"type": "Crossunder",
"params": {"mode": "simple"},
"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",
"indicators": [
{"id": "sma_short", "output_name": "sma20"},
{"id": "sma_long", "output_name": "sma60"},
{"id": "rsi", "output_name": "rsi"}
]
}
}
}
```
**配置要点**:
- `LinearScaleWeight` 将RSI [30, 70] 映射到仓位 [100%, 30%]
- 比V1更灵敏:RSI=40时,V2仓位82.5%,V1仓位100%
- 适合美股等温和市场,在极端市场(A股)可能失效
### V3:ATR波动率控制(A股亚军)
**策略描述**:基于ATR波动率的动态仓位控制,使用ATR比率(ATR14/ATR120)的0.7-1.8区间映射到100%-30%仓位。在美股表现稳健,在A股几乎与V1持平(104% vs 106%),特别适合高波动市场和熊市环境。
**交易策略配置**:
```json
{
"trade_strategy": {
"indicators": [
{"id": "sma_short", "type": "SMA", "params": {"period": 20, "column": "Close"}},
{"id": "sma_long", "type": "SMA", "params": {"period": 60, "column": "Close"}},
{"id": "atr_short", "type": "ATR", "params": {"period": 14}},
{"id": "atr_long", "type": "ATR", "params": {"period": 120}}
],
"signals": [
{
"id": "buy_signal",
"type": "Crossover",
"params": {"mode": "simple"},
"inputs": [{"ref": "sma_short"}, {"ref": "sma_long"}]
},
{
"id": "sell_signal",
"type": "Crossunder",
"params": {"mode": "simple"},
"inputs": [{"ref": "sma_short"}, {"ref": "sma_long"}]
},
{
"id": "atr_ratio",
"type": "Divide",
"inputs": [{"ref": "atr_short"}, {"ref": "atr_long"}],
"params": {"return_calculation": true}
},
{
"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,
"clip": true
}
}
],
"outputs": {
"buy_signal": "buy_signal",
"sell_signal": "sell_signal",
"target_weight": "atr_weight",
"indicators": [
{"id": "sma_short", "output_name": "sma20"},
{"id": "sma_long", "output_name": "sma60"},
{"id": "atr_short", "output_name": "atr"},
{"id": "atr_long", "output_name": "atr_ma"},
{"id": "atr_ratio", "output_name": "atr_ratio"}
]
}
}
}
```
**配置要点**:
- 使用 `Divide` 原语计算ATR比率(ATR14 / ATR120)
- `LinearScaleWeight` 将ATR比率 [0.7, 1.8] 映射到仓位 [100%, 30%]
- ATR比率 小于 0.7:市场异常平静 → 100%满仓
- ATR比率 大于 1.8:市场暴动 → 30%低仓
- 适合高波动市场(A股)和熊市环境
### V4:ATR波动率控制(V3的别名)
**策略说明**:V4与V3的原语配置完全相同(ATR比率 0.7-1.8 映射到 100%-30%仓位),在实际应用中可视为同一策略。V4作为独立版本号存在,可能是在研究过程中的迭代命名,但最终配置与V3一致。
**交易策略配置**:参考V3配置,完全相同。
**性能表现**:
- 美股:与V3相同(556%收益)
- A股:与V3相同(104%收益)
### V5:RSI+ATR组合控制(多因子策略)
**策略描述**:多因子组合策略,将RSI权重和ATR权重平均作为最终仓位。展示了策引系统最强大的能力:组合多个信号原语构建复杂逻辑,实现同时考虑价格位置(RSI)和市场波动(ATR)的多因子风控。
**交易策略配置**:
```json
{
"trade_strategy": {
"indicators": [
{"id": "sma_short", "type": "SMA", "params": {"period": 20, "column": "Close"}},
{"id": "sma_long", "type": "SMA", "params": {"period": 60, "column": "Close"}},
{"id": "rsi", "type": "RSI", "params": {"period": 14}},
{"id": "atr_short", "type": "ATR", "params": {"period": 14}},
{"id": "atr_long", "type": "ATR", "params": {"period": 120}},
{"id": "constant_0_5", "type": "Constant", "params": {"value": 0.5}}
],
"signals": [
{
"id": "buy_signal",
"type": "Crossover",
"params": {"mode": "simple"},
"inputs": [{"ref": "sma_short"}, {"ref": "sma_long"}]
},
{
"id": "sell_signal",
"type": "Crossunder",
"params": {"mode": "simple"},
"inputs": [{"ref": "sma_short"}, {"ref": "sma_long"}]
},
{
"id": "rsi_weight",
"type": "LinearScaleWeight",
"inputs": [{"ref": "rsi"}],
"params": {
"min_indicator": 30,
"max_indicator": 70,
"min_weight": 1.0,
"max_weight": 0.4,
"clip": true
}
},
{
"id": "atr_ratio",
"type": "Divide",
"inputs": [{"ref": "atr_short"}, {"ref": "atr_long"}],
"params": {"return_calculation": true}
},
{
"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,
"clip": true
}
},
{
"id": "weight_sum",
"type": "Add",
"inputs": [{"ref": "rsi_weight"}, {"ref": "atr_weight"}],
"params": {"return_calculation": true}
},
{
"id": "combined_weight",
"type": "Multiply",
"inputs": [{"ref": "weight_sum"}, {"ref": "constant_0_5"}],
"params": {"return_calculation": true}
}
],
"outputs": {
"buy_signal": "buy_signal",
"sell_signal": "sell_signal",
"target_weight": "combined_weight",
"indicators": [
{"id": "sma_short", "output_name": "sma20"},
{"id": "sma_long", "output_name": "sma60"},
{"id": "rsi", "output_name": "rsi"},
{"id": "atr_short", "output_name": "atr"},
{"id": "atr_long", "output_name": "atr_ma"},
{"id": "atr_ratio", "output_name": "atr_ratio"},
{"id": "rsi_weight", "output_name": "rsi_w"},
{"id": "atr_weight", "output_name": "atr_w"}
]
}
}
}
```
**原语链条**:
```
RSI14 → LinearScaleWeight → rsi_weight (0.4-1.0)
↓
Add → weight_sum
↓
ATR14/ATR120 → LinearScaleWeight → atr_weight (0.3-1.0)
↓
Multiply(0.5) → combined_weight
```
**配置要点**:
- 使用 `Constant` 原语定义0.5常数,用于计算平均值
- RSI和ATR分别通过 `LinearScaleWeight` 映射到各自的权重
- 使用 `Add` 原语将两个权重相加
- 使用 `Multiply` 原语乘以0.5,实现平均(等价于除以2)
- 最终仓位 = (rsi_weight + atr_weight) / 2
- 示例:RSI=60 → rsi_weight=0.7,ATR比率=1.5 → atr_weight=0.45,最终仓位=57.5%
## 配置总结
### 跨市场通用性
**所有策略版本(V0-V5)的 `trade_strategy` 原语配置在美股和A股完全相同**,这证明了原语系统的跨市场通用性。唯一的差异是:
- 交易标的(QQQ vs 159915)
- 回测时间段
- 市场参数(市场代码、货币、更新时间等)
### 资金策略统一配置
所有动态仓位策略(V1-V5)都使用 **[再平衡资金策略(RebalancingCapitalStrategy)](/docs/capital-strategies/rebalancing-capital-strategy)**,配置如下:
**基础配置**:
```json
{
"capital_strategy": {
"name": "RebalancingCapitalStrategy",
"params": {
"initial_capital": 100000
}
}
}
```
**推荐配置(含threshold参数)**:
```json
{
"capital_strategy": {
"name": "RebalancingCapitalStrategy",
"params": {
"initial_capital": 100000,
"threshold": 0.05
}
}
}
```
**参数说明**:
| 参数 | 类型 | 必需 | 说明 | 推荐值 |
|------|------|------|------|--------|
| `initial_capital` | number | 是 | 初始投入资金 | 根据实际投入设置 |
| `threshold` | number | 否 | 再平衡阈值(偏离百分比) | 0.05(5%偏离才调仓) |
**threshold参数详解**:
- **作用**:只有当实际仓位与目标仓位偏离超过threshold时,才触发再平衡交易
- **不设置**:每日都可能发生微小调仓,手续费成本显著增加
- **设置为0.05**:实际仓位65%,目标仓位70%时,偏离5个百分点,触发买入调整到70%
- **建议值**:
- **美股**(低手续费):0.03-0.05
- **A股**(高手续费):0.05-0.10
- **高波动资产**:0.03-0.05(波动大,需要更频繁调整)
- **低波动资产**:0.05-0.10(波动小,可容忍更大偏离)
**V0基准版的资金策略**:
V0使用固定100%仓位,配置不同:
```json
{
"capital_strategy": {
"name": "PercentCapitalStrategy",
"params": {
"initial_capital": 100000,
"percents": 100
}
}
}
```
### 策略版本速查表
| 版本 | 仓位控制指标 | 映射区间 | 仓位范围 | 美股表现 | A股表现 | 特点 |
|------|------------|---------|---------|---------|---------|------|
| **V0** | 无(固定) | - | 0%/100% | 基准(151%) | 基准(40%) | 全进全出,对照组 |
| **V1** | RSI | 40-75 | 30%-100% | 🏆 冠军(1178%) | 🏆 冠军(106%) | 保守减仓,过滤假信号 |
| **V2** | RSI | 30-70 | 30%-100% | 优秀(900%) | 失效(56%) | 风险调整最优,仅限温和市场 |
| **V3** | ATR比率 | 0.7-1.8 | 30%-100% | 稳健(556%) | 亚军(104%) | 波动率避险,熊市优秀 |
| **V4** | ATR比率 | 0.7-1.8 | 30%-100% | 同V3 | 同V3 | V3的别名 |
| **V5** | RSI+ATR | 组合 | 30%-100% | 平衡(782%) | 良好 | 多因子平衡,鲁棒性强 |
**快速选择指南**:
- **追求极致收益** → V1(RSI 40-75),能承受-35%回撤
- **追求风险调整收益** → V2(RSI 30-70),仅限美股等温和市场
- **追求防守稳健** → V3(ATR波动率),适合高波动市场和熊市
- **追求多因子平衡** → V5(RSI+ATR组合),鲁棒性强
- **对比基准** → V0(固定仓位)
## 实战启示:如何选择适合你的策略?
经过五个版本的对比测试,我们得到了足够的数据来为不同类型的投资者提供建议。
### 场景一:追求极致收益
**推荐策略**:V1(RSI 40-75宽区间)
**适合人群**:
- 能承受-35%回撤的投资者
- 长期看好趋势向上的市场(如美股)
- 相信"少做多得"的哲学
- 愿意用短期波动换长期收益
**优势**:
- 最高收益(美股1,178%,A股106%)
- 最少交易(仅28次,节省手续费和心理成本)
- 交易效率最高(单次贡献42.1%)
**心理建设**:
- 你必须接受:当卖出信号触发时,策略可能"不听话",依然保持高仓位
- 你必须相信:大多数卖出信号都是假的,只有极端情况才需要清仓
- **在2020年3月暴跌35%时,你能坚持不清仓吗?** 这是实施V1的最大考验
### 场景二:追求性价比
**推荐策略**:V2(RSI 30-70标准区间)
**适合人群**:
- 风险偏好中等的投资者
- 看重夏普比率和Calmar比率
- 希望在收益和风险之间取得平衡
- 主要交易美股等相对温和的市场
**优势**:
- 风险调整后收益最高(Calmar 0.52)
- 回撤相对较小(-31.1%)
- 收益依然优异(900%,是基准的6倍)
- 恢复速度最快(298天)
**注意事项**:
- 在A股等极端市场可能失效
- 需要定期监控RSI分布,确保参数适配市场特征
### 场景三:追求防守稳健
**推荐策略**:V3(ATR波动率控制)
**适合人群**:
- 高度厌恶风险的投资者
- 交易波动剧烈的市场(如A股、新兴市场)
- 经历过熊市创伤,优先考虑本金保护
- 希望策略能自动"读懂"市场恐慌情绪
**优势**:
- 在极端市场(如A股)表现优异(104%收益)
- 2022年熊市回撤最小(-12%)
- 波动率驱动,无需预判市场方向
**劣势**:
- 在温和牛市(如美股2010-2020)收益较低(556%,虽然依然是基准的4倍)
- 可能在V型反转中踏空(因为ATR下降较慢)
### 场景四:极端分散
**推荐策略**:V5(RSI+ATR组合)
**适合人群**:
- 喜欢多因子模型的量化投资者
- 不想在RSI和ATR之间做选择
- 追求策略的鲁棒性
- 希望策略在各种市场环境下都不太差
**优势**:
- 综合考虑价格位置和波动率
- 在各种市场环境下都有中上表现
- 性能稳定,不会出现某个市场完全失效的情况
**劣势**:
- 没有在任何单一市场成为冠军
- 复杂度更高,调试成本增加
## 参数调优指南
虽然我们提供了默认参数,但不同市场和不同时期可能需要调整。
### RSI参数调整原则
**宽区间 vs 标准区间**:
| 市场特征 | 推荐区间 | 理由 |
|---------|---------|------|
| **温和波动**(如美股) | 30-70(标准) | RSI很少极端值,标准区间足够 |
| **剧烈波动**(如A股) | 40-75(宽区间)或更宽 | RSI经常极端,需要更大调整空间 |
| **超高波动**(如加密货币) | 50-80(更宽) | RSI极端值频繁,给策略更多余地 |
**仓位区间调整**:
- 默认是100%-30%(最高满仓,最低30%仓位)
- **保守型**:可以改为80%-20%(降低最高仓位)
- **激进型**:可以改为100%-10%(扩大仓位范围)
- **不建议完全清仓**(0%),因为会失去动态仓位的核心优势
### ATR参数调整原则
**ATR比率阈值**:
| 市场特征 | 推荐阈值 | 理由 |
|---------|---------|------|
| **低波动**(如指数ETF) | 0.7-1.5 | 波动率稳定,较窄区间即可 |
| **中波动**(如科技股) | 0.7-1.8(默认) | 平衡灵敏度和稳定性 |
| **高波动**(如杠杆ETF) | 0.6-2.5 | 波动率极端,需要更宽容的阈值 |
**ATR周期调整**:
- 短周期(14日):对波动率变化敏感,适合短线
- 长周期(120日):提供稳定的基准,适合中长线
- **不建议**同时缩短两个周期,会导致比率失去意义
### 回测验证的重要性
**切记**:任何参数调整都必须经过充分的回测验证:
1. 至少使用10年以上的历史数据
2. 覆盖至少一个完整牛熊周期
3. 特别关注极端市场时期的表现(如2008年、2020年)
4. 避免过度拟合(参数在不同时间段都应该稳定)
## 核心启示与结论
经过五个版本、两个市场、超过20年的回测数据,我们得到了一些深刻的洞察。
### 启示一:持仓比择时更重要
这次研究最核心的发现是:**在相同的买卖信号下,仅通过改变仓位管理,收益可以相差7倍**。
这颠覆了很多投资者的认知。大多数人花费90%的精力优化"何时买卖",却忽略了更重要的问题:"买多少"。
**数字对比**:
- 从SMA20/60优化到SMA15/55:收益可能提升10-20%
- 从固定仓位改为动态仓位:收益提升了680%
**结论**:**与其纠结均线参数,不如先把仓位管理做好**。
### 启示二:拒绝清仓有时是正确的
传统趋势跟随策略信奉"顺势而为",死叉就清仓。但V1策略告诉我们:**有时候"不听话"反而是对的**。
**V1的哲学**:
- 大多数卖出信号都是噪音
- 真正的趋势转折很少
- 拒绝响应假信号,等待真正的风险
这需要巨大的心理素质:当所有指标都说"卖",你却选择"持有"。但数据证明,这是值得的。
**类比**:就像开车遇到减速带,你不需要每次都停车,只需要减速通过。V1就是这个减速带策略——遇到小波动,降低速度(轻度减仓),而不是停车(清仓)。
### 启示三:参数需要适配市场
同样的V2策略,在美股收益900%,在A股却只有56%。这说明:**没有放之四海而皆准的参数,只有适合特定市场的配置**。
**适配原则**:
- **温和市场**(美股):标准参数即可
- **极端市场**(A股):需要更宽的参数区间
- **定期检查**:每年至少检查一次参数是否仍然适配市场特征
### 启示四:风险是收益的入场券
V1的收益是基准的7.79倍,但代价是回撤从-29%增加到-35%。
**关键问题**:多承受6个百分点的回撤,换取7倍的收益,你愿意吗?
对于大多数投资者,答案应该是"愿意"。但你必须做好心理准备:
- 在账户回撤35%时不恐慌性清仓
- 相信策略的长期逻辑
- 接受短期波动换取长期收益
**这才是量化投资的本质**:用数学和纪律战胜情绪。
### 启示五:少做反而做得更好
V0做了69次交易,单次贡献2.2%;V1只做了28次,单次贡献42.1%。
**交易效率提升19倍**,这不仅节省了手续费,更重要的是节省了心理成本:
- 更少的决策压力
- 更少的情绪波动
- 更多的时间享受生活
**巴菲特的智慧**:"如果你不愿意持有一只股票十年,那就不要持有十分钟。" V1策略用数据证明了这句话的价值。
## 最终总结
动态仓位不是魔法,它不能让你避开所有风险,也不能保证每次交易都盈利。
但它能做到的是:
1. **减少无效交易**:过滤掉80%的噪音信号
2. **提升交易质量**:让每一次出手都更有价值
3. **平衡风险收益**:用适度的风险换取显著的收益
4. **适应市场节奏**:让仓位随市场呼吸而律动
通过策引系统的原语组合,你可以轻松实现从简单到复杂的各种动态仓位策略。**不要让你的资金在全进全出中空转,让它随着市场的脉搏跳动吧**。
**记住**:在量化交易中,最难的不是构建策略,而是在策略回撤时坚持执行。动态仓位给了你一个更理性的工具,但最终能否成功,还取决于你能否战胜自己。
--------------------------------------------------------------------------------
股债轮动案例 (advanced/stock-bond-rotation-case.md)
--------------------------------------------------------------------------------
# 股债轮动策略优化实战:从困境到突破的完整历程
## 引言
在量化投资的世界里,有一个永恒的追求:如何在牛市中获得收益,在熊市中保护资产?这个看似简单的目标,却困扰着无数投资者。本文记录了一次完整的策略优化过程,展示了如何通过系统性的方法,将一个表现平庸的股债轮动策略,逐步优化为一个年化收益5.42%、胜率超过80%的优秀策略。
这不仅是一个技术优化的案例,更是一次投资理念的深度思考:什么才是真正有效的趋势判断?如何在复杂的市场环境中找到简单而有效的解决方案?
## 问题的起源:一个投资者的困惑
### 用户的核心诉求
这次优化起源于一个投资者的真实困惑:
> "我感觉股债切换策略至少应该做到在股票大幅度涨的时候跟上市场,在趋势破的时候切换到债券,所以至少应该比单独持有沪深300强才行,目前显然不是这样的。"
这个朴素的期望揭示了股债轮动策略的核心价值主张:
- **牛市参与**:在股票上涨时能够捕捉收益
- **熊市避险**:在趋势破坏时及时切换到安全资产
- **整体超越**:表现应该优于单纯持有股票指数
### 初始策略的表现困境
我们的起点是一个基于200日移动平均线的简单股债轮动策略:
| 指标 | 初始策略 | 沪深300指数 | 期望表现 |
|------|----------|-------------|----------|
| 累计收益 | +12.85% | -6.14% | ✅ 已超越指数 |
| 年化收益 | 1.65% | -0.91% | ❌ 绝对水平偏低 |
| 最大回撤 | -12.29% | 大于-20% | ✅ 风险控制良好 |
| 胜率 | 40.0% | N/A | ❌ 交易成功率偏低 |
虽然策略在风险控制方面表现优秀,但收益率确实不够理想,特别是在牛市年份的参与度不足:
- **2019年牛市**:沪深300涨37%,策略仅获得6.67%收益
- **2020年**:疫情后反弹,策略表现中规中矩
- **整体问题**:200日均线的滞后性导致错失重要机会
## 优化历程:四个版本的迭代进化
### 第一次尝试:优化版v1 - 减少滞后性
**核心思路**:缩短均线周期,加快趋势响应速度
**主要改进**:
- 均线周期:200日 → 120日
- 增加3日确认机制,减少虚假信号
- 保持原有的股债轮动逻辑
**配置要点**:
```json
{
"name": "hs300_ma120",
"type": "MovingAverageTransformer",
"params": {
"window": 120,
"method": "simple"
}
},
{
"id": "market_trend_up_confirmed",
"type": "Streak",
"params": {
"condition": "true",
"min_length": 3
}
}
```
**结果评估**:
- 年化收益:1.65% → 2.70%(+64%提升)
- 最大回撤:-12.29% → -7.10%(显著改善)
- 胜率:40.0% → 51.2%(明显提升)
- **结论**:方向正确,但仍有优化空间
### 第二次尝试:优化版v2 - 多指标确认
**核心思路**:增加RSI动量指标,提高信号质量
**主要改进**:
- 引入RSI指标进行动量确认
- 多重条件:价格大于均线 AND RSI大于50 AND 连续确认
- 调整为保守倾向(default_to_stock=false)
**配置要点**:
```json
{
"name": "hs300_rsi14",
"type": "RSITransformer",
"params": {
"window": 14,
"field": "Close"
}
},
{
"id": "combined_bullish",
"type": "And",
"inputs": [
{"ref": "price_above_ma"},
{"ref": "rsi_bullish"}
]
}
```
**结果评估**:虽然增加了技术指标的深度,但实际表现并未显著超越v1版本,反而因为条件过于复杂,错失了一些机会。
### 第三次尝试:双均线版 - 经典策略的尝试
**核心思路**:使用双均线交叉系统,更敏感地捕捉趋势变化
**主要改进**:
- 采用20日/60日双均线系统
- 要求短期均线上穿长期均线且价格高于短期均线
- 连续2日确认机制
**关键发现**:这个版本暴露了一个重要问题 - **过度交易**
- 交易次数:86次(7年),远超其他版本
- 年化收益:仅1.29%,不如初始版本
- **核心问题**:在震荡市中频繁切换,产生大量无效交易
这次"失败"的尝试给了我们重要启示:**敏感性与稳定性之间需要平衡**。
### 第四次突破:趋势强度版 - 质量优于数量
经过前三次的探索,我们意识到问题的核心不是如何更快地响应趋势,而是**如何确保只在高质量的趋势中入场**。
**核心洞察**:
1. 不是所有的趋势都值得参与
2. 宁可错过机会,也不要做错误的交易
3. 质量优于数量,精确打击胜过频繁行动
**突破性设计**:
```json
{
"strategy_logic": [
"价格必须高于50日均线(基础趋势确认)",
"相对强度必须大于105%(价格比均线高5%以上)",
"连续5日满足上述条件(避免假突破)",
"默认持有债券,股票需要强确认"
]
}
```
**核心参数设计**:
```json
{
"name": "hs300_strength",
"type": "RelativeStrengthTransformer",
"params": {
"reference": "ma",
"window": 50,
"field": "Close"
}
},
{
"id": "strength_threshold",
"type": "Constant",
"params": {
"value": 105
}
},
{
"id": "trend_persistence",
"type": "Streak",
"params": {
"min_length": 5
}
}
```
## 突破性成果:数据说话的胜利
### 性能对比:跨越式提升
| 指标 | 原版 | 优化v1 | 趋势强度版 | 提升幅度 |
|------|------|--------|------------|----------|
| **年化收益率** | 1.65% | 2.70% | **5.42%** | **+229%** |
| **累计收益** | 12.85% | 21.77% | **47.76%** | **+271%** |
| **最大回撤** | -12.29% | -7.10% | **-7.76%** | **+37%** |
| **胜率** | 40.0% | 51.2% | **81.3%** | **+103%** |
| **盈亏比** | 2.50 | 2.43 | **40.69** | **+1528%** |
| **交易次数** | 60次 | 41次 | **16次** | **-73%** |
| **夏普比率** | 0.141 | 0.486 | **0.733** | **+420%** |
### 年度表现分析:终于实现牛市参与
| 年份 | 沪深300表现 | 趋势强度版表现 | 评价 |
|------|-------------|----------------|------|
| **2019** | +43% | **+17.16%** | ✅ 成功捕捉主要涨幅 |
| **2020** | +31% | **+10.04%** | ✅ 疫情中表现稳健 |
| **2021** | -4.13% | **+4.22%** | ✅ 熊市中保持正收益 |
| **2022** | -20% | **+0.80%** | ✅ 大熊市中避险成功 |
| **2024** | 约+7% | **+7.35%** | ✅ 近期表现优秀 |
### 与基准的全面对比
| 对比对象 | 累计收益 | 年化收益 | 最大回撤 | 夏普比率 |
|----------|----------|----------|----------|----------|
| **趋势强度版** | **47.76%** | **5.42%** | **-7.76%** | **0.733** |
| 等权重基准 | 22.52% | 2.78% | -18.09% | 0.356 |
| 沪深300指数 | -6.14% | -0.91% | 大于-20% | 负值 |
**结论**:趋势强度版不仅实现了用户的初始期望,更在所有关键指标上都取得了突破性进展。
## 核心洞察:成功背后的投资哲学
### 1. 质量优于数量的投资哲学
传统观念认为,更多的交易机会意味着更多的获利可能。但我们的实践证明:
- **精选机会**:16次交易vs60次交易,效果更佳
- **避免噪音**:5%强度阈值过滤掉了大部分无效信号
- **耐心等待**:宁可错过机会,不做错误交易
### 2. 多重确认机制的威力
成功的策略需要多层过滤机制:
- **基础趋势**:价格高于50日均线
- **强度确认**:相对强度超过105%
- **时间确认**:连续5日满足条件
- **默认保守**:债券优先,股票需要强证据
### 3. 参数设计的平衡艺术
每个参数都有其深层含义:
- **50日均线**:既不过于敏感,也不过于滞后
- **5%强度阈值**:足以过滤噪音,不会过于严苛
- **5日确认期**:避免假突破,确保趋势真实性
### 4. 风险控制优先的理念
策略始终坚持风险控制优先:
- **默认持债**:不确定时选择安全资产
- **严格入场**:股票投资需要强确认
- **及时离场**:条件不满足立即退出
## 技术实现:原语系统的优雅表达
### 核心配置架构
```json
{
"market_indicators": {
"transformers": [
{
"name": "hs300_raw",
"type": "IdentityTransformer"
},
{
"name": "hs300_ma50",
"type": "MovingAverageTransformer",
"params": {"window": 50}
},
{
"name": "hs300_strength",
"type": "RelativeStrengthTransformer",
"params": {
"reference": "ma",
"window": 50
}
}
]
}
}
```
### 信号逻辑链条
```json
{
"signals": [
{
"id": "price_above_ma50",
"type": "GreaterThan",
"comment": "基础趋势确认"
},
{
"id": "strong_trend",
"type": "GreaterThan",
"comment": "强度阈值确认"
},
{
"id": "bullish_confirmed",
"type": "And",
"comment": "综合条件判断"
},
{
"id": "trend_persistence",
"type": "Streak",
"params": {"min_length": 5},
"comment": "时间持续确认"
},
{
"id": "stock_bond_buy",
"type": "StockBondSwitch",
"params": {"default_to_stock": false},
"comment": "最终交易信号"
}
]
}
```
## 方法论总结:可复制的优化框架
### 第一步:问题识别与目标设定
1. **明确核心诉求**:用户的真实投资目标是什么?
2. **基准对比分析**:当前策略与预期的差距在哪里?
3. **问题根源挖掘**:表现不佳的根本原因是什么?
### 第二步:系统性假设验证
1. **单因子测试**:每次只调整一个参数
2. **方向性验证**:确认优化方向是否正确
3. **边际效应分析**:评估每次改进的实际效果
### 第三步:突破性思维转换
1. **跳出局部优化**:有时需要重新定义问题
2. **质量vs数量**:追求精确而非频繁
3. **逆向思维**:从失败中学习更重要的经验
### 第四步:验证与完善
1. **多维度评估**:不仅看收益,更要看风险调整后收益
2. **压力测试**:在不同市场环境下的表现如何?
3. **可持续性验证**:策略逻辑是否具有经济学基础?
## 实战启示:投资的本质思考
### 启示一:趋势的定义需要重新思考
传统上,我们认为价格高于均线就是上升趋势。但实践告诉我们:
- **弱趋势不值得参与**:微弱的突破往往是陷阱
- **强趋势才有价值**:需要足够的安全边际
- **持续性是关键**:一时的突破不如持续的强势
### 启示二:技术分析的精髓在于过滤而非预测
优秀的技术分析不是预测市场方向,而是:
- **过滤优质机会**:只参与高胜率的交易
- **控制参与时机**:在合适的时机入场和离场
- **管理整体风险**:通过严格的条件控制风险
### 启示三:原语系统的强大在于组合的艺术
单个原语组件的功能可能简单,但组合后能产生强大的效果:
- **IdentityTransformer + MovingAverageTransformer**:基础趋势判断
- **RelativeStrengthTransformer**:强度量化
- **Streak + And 逻辑**:多重确认机制
- **StockBondSwitch**:最终执行
## 未来展望:进一步优化的方向
### 可能的改进方向
1. **自适应参数**:根据市场环境动态调整强度阈值
2. **多时间框架**:结合不同周期的信号确认
3. **波动率调整**:在高波动期间放宽条件
4. **资金管理**:引入更精细的仓位管理
### 风险提示与限制
1. **过拟合风险**:优秀的历史表现不保证未来成功
2. **市场环境变化**:策略需要在不同市场周期中验证
3. **交易成本**:实盘交易需要考虑滑点和手续费
4. **心理因素**:执行策略需要严格的纪律性
## 结论:投资的智慧与实践的完美结合
这次股债轮动策略的优化历程,不仅是一次技术的突破,更是一次投资哲学的深度实践。我们从一个表现平庸的策略出发,通过系统性的方法论,最终实现了:
- **收益率的跨越式提升**:年化收益从1.65%提升到5.42%
- **风险控制的显著改善**:最大回撤从-12.29%降低到-7.76%
- **交易质量的质的飞跃**:胜率从40%提升到81.3%
更重要的是,我们验证了几个核心投资理念:
1. **质量胜过数量**:精选的16次交易胜过频繁的86次交易
2. **耐心是美德**:等待高质量机会比抓住所有机会更重要
3. **多重确认的威力**:严格的入场条件是成功的关键
4. **原语系统的优雅**:复杂的投资逻辑可以通过简单的组件优雅地表达
这个案例告诉我们,优秀的投资策略不是来自复杂的数学模型,而是来自对市场本质的深刻理解和对投资原则的严格执行。在这个过程中,原语系统展现了其强大的灵活性和表达能力,让我们能够将投资的智慧转化为可执行的代码。
正如巴菲特所说:"时间是优秀企业的朋友,是平庸企业的敌人。"在我们的策略中,时间同样是高质量信号的朋友,是噪音交易的敌人。通过这次优化,我们不仅找到了一个优秀的股债轮动策略,更重要的是,我们掌握了一套可复制、可扩展的策略优化方法论。
这不仅是一次技术的胜利,更是投资智慧与系统化方法完美结合的典范。
--------------------------------------------------------------------------------
加密货币案例 (advanced/crypto-strategy-case.md)
--------------------------------------------------------------------------------
# 12个加密货币策略组合的实战对比:当数据推翻直觉
## 引言
加密货币市场以其极端波动性著称——BTC可以在一年内从69000跌到16000(-77%),也可以在几个月内翻倍。在这样的市场中,什么样的策略才能真正创造价值?
我们用原语策略引擎对**5种主流策略应用于不同资产,构建了12个策略组合**进行8年回测(2018-2026)。这些策略覆盖了加密货币投资者最常用的方法论:
| 策略类型 | 数量 | 策略名称 | 市场认知度 |
|---------|------|---------|-----------|
| **基准策略** | 3个 | BTC/ETH/SOL 买入持有 | 🔥🔥🔥 最广泛的持有策略 |
| **趋势跟踪** | 3个 | BTC/ETH/SOL 双均线 | 🔥🔥🔥 经典技术分析 |
| **技术指标** | 3个 | BTC/ETH/SOL RSI超买超卖 | 🔥🔥 传统量化最爱 |
| **链上指标** | 3个 | MVRV、NVT、MVRV+NVT组合 | 🔥🔥 加密货币特色 |
| **配对交易** | 2个 | ETH/BTC均值回归、趋势跟踪 | 🔥 专业交易者策略 |
| **动态仓位** | 1个 | MVRV动态权重 | 🔥 高阶风控手段 |
从**被动持有**到**主动择时**,从**传统技术面**到**链上数据面**,从**单资产**到**多资产轮动**——这些策略类型基本涵盖了加密货币市场中散户到机构投资者的主流方法。
**研究的核心问题**:这些主动策略,能否跑赢"什么都不做"的买入持有?
但这篇文章的意义不止于策略对比。我们更想验证一个基础设施层面的问题:**是否存在一套统一的策略表达系统,能够覆盖从技术分析到链上数据、从单资产到多资产、从二元交易到动态仓位的全部研究场景?** 如果策略之间的差异能被压缩为结构化的原语组合差异,那么快速验证、精确定位问题、甚至未来的自动化探索都将成为可能。
结果让我们大跌眼镜——几乎每一条"专业直觉"都被数据无情打脸。而原语系统在这个过程中展现的能力,同样值得关注。
---
## 第一章:策略介绍与分类
量化投资领域存在众多策略流派,从经典的技术分析到新兴的链上数据分析,从单一资产交易到多资产配对。策引回测引擎的设计目标,正是让用户能够快速验证这些不同思想。
**策引支持两种策略实现方式**:
- **原语策略**:通过JSON配置组合预置原语,无需编程,适合绝大多数策略场景
- **代码策略**:用Python编写自定义逻辑,处理原语难以表达的复杂场景
本次研究的12个策略组合中,大部分通过原语策略实现,仅配对交易因涉及多资产轮换逻辑采用了代码策略。这也印证了原语系统"覆盖主流、简化实现"的设计理念。
下面逐一介绍各策略类型。
### 1.1 基准策略:买入持有(Buy & Hold)
最简单的策略——买入后不做任何操作,一直持有到回测结束。
**为什么用它作为基准?**
任何主动策略如果长期跑输买入持有,都意味着在摧毁价值而非创造价值。这是判断策略是否具备正Alpha的最低门槛。
### 1.2 趋势跟踪:双均线策略
经典的技术分析策略,使用50日和200日移动平均线:
- **金叉买入**:50日均线上穿200日均线
- **死叉卖出**:50日均线下穿200日均线
**核心原语**:`SMA`(移动平均线)、`CrossAbove`(上穿)、`CrossBelow`(下穿)
### 1.3 技术指标:RSI超买超卖
相对强弱指数(RSI)是最经典的摆动指标:
- **RSI < 30**:超卖区,买入
- **RSI > 70**:超买区,卖出
**核心原语**:`RSI`、`LessThan`、`GreaterThan`
### 1.4 链上指标:MVRV与NVT
加密货币独有的链上数据指标。原语系统通过[市场指标功能](./market-indicators.md)提供了这两个数据源:
| 指标代码 | 指标名称 | 核心概念 |
|---------|---------|---------|
| `BTC_MVRV_ZSCORE` | MVRV Z-Score | 市场情绪的温度计:衡量当前价格相对历史成本的偏离 |
| `BTC_NVT` | NVT Signal | 加密货币的"市盈率":衡量价格相对链上活跃度的估值水平 |
#### MVRV Z-Score 详解(Market Value to Realized Value)
**什么是"实现市值"?**
不同于普通市值(当前价格 × 总量),实现市值统计的是**每个比特币最后一次链上转移时的价格**。可以理解为"市场参与者的平均持币成本"。
**MVRV Z-Score 计算逻辑**:
```
MVRV Z-Score = (市值 - 实现市值) / 市值的标准差
```
**为什么它能识别顶部和底部?**
- **当 MVRV < 1**:当前价格**低于**市场平均持币成本
- 📉 大部分持币者处于亏损状态
- 💎 只有坚定的长期持有者还在市场中
- 📍 历史数据显示:这只发生在**熊市最深处**(2015、2018、2022年底)
- ✅ **绝佳的抄底区域**
- **当 MVRV > 5**:当前价格**远高于**市场平均持币成本
- 📈 大部分持币者获利丰厚
- 🔥 市场处于极度狂热状态
- 📍 历史数据显示:这通常是**牛市顶部**(2017年底、2021年初)
- ⚠️ **卖出信号,风险极高**
**直观理解**:
- MVRV = 1:市场价格 = 平均成本 → 中性区域
- MVRV = 2-3:温和牛市,市场健康
- MVRV = 3-5:过热区域,需要警惕
- MVRV > 5:泡沫顶部,高度危险
#### NVT Signal 详解(Network Value to Transactions)
**类比股票市场的"市盈率"**
就像股票的市盈率(市值/利润)衡量估值一样,NVT 用链上交易量代替"利润":
```
NVT Signal = 市值 / 90日平均链上交易量
```
**为什么它能识别泡沫?**
- **NVT 过高(>90百分位)**:价格涨得太快,但实际使用量跟不上
- 💰 市值暴涨
- 📊 链上转账量平平
- 💭 更多是投机炒作,而非实际应用
- ⚠️ **高估警告:类似股票的"高市盈率陷阱"**
- **NVT 过低(<20百分位)**:价格被低估,但网络使用活跃
- 💰 市值被打压
- 📊 链上转账量依然旺盛
- 💎 真实需求强劲,价格未反映价值
- ✅ **潜在买入机会**
**直观理解**:
- NVT 高 = 价格泡沫,投机过热
- NVT 低 = 价值低估,网络健康
- NVT 平稳 = 价格与使用匹配,市场合理
**两个指标的协同作用**:
- MVRV 关注**市场情绪**(人们的盈亏状态)
- NVT 关注**网络健康度**(实际使用情况)
- 结合使用可以更全面判断市场状态
**直观查看指标走势**:
访问 [策引市场页面 - 加密货币部分](https://www.myinvestpilot.com/markets),可以实时查看 MVRV 和 NVT 指标的历史走势图,直观感受这些指标在不同市场阶段的表现。
---
在策略配置中,通过`market_indicators`引入这些数据:
```json
{
"market_indicators": {
"indicators": [
{ "code": "BTC_MVRV_ZSCORE" },
{ "code": "BTC_NVT" }
]
}
}
```
**核心原语**:`IdentityTransformer`(引入外部数据)、`PercentileRankTransformer`(百分位排名)、`And`/`Or`(逻辑组合)
### 1.5 配对交易:ETH/BTC比率
基于ETH相对BTC的价格比率进行交易:
- **均值回归版**:比率低于均线时买入ETH(赌它会涨回来)
- **趋势跟踪版**:比率高于均线时买入ETH(顺势而为)
**核心原语**:`Divide`(计算比率)、`MovingAverageTransformer`(均线)、`Streak`(连续确认)
### 1.6 动态仓位:LinearScaleWeight
不再是"满仓/空仓"的二元选择,而是根据指标值动态调整仓位:
- MVRV越低 → 仓位越高(底部敢于重仓)
- MVRV越高 → 仓位越低(顶部逐步减仓)
**核心原语**:`LinearScaleWeight`(线性映射仓位权重)
### 1.7 策略全景:原语覆盖能力一览
下表汇总了本次研究涉及的所有策略类型及其实现方式:
| 策略类型 | 实现方式 | 核心原语/组件 | 策略数量 |
|---------|---------|--------------|---------|
| 买入持有 | 代码策略 | `BuyHoldStrategy` | 3 |
| 趋势跟踪 | 原语策略 | `SMA`, `CrossAbove`, `CrossBelow` | 3 |
| 技术指标 | 原语策略 | `RSI`, `LessThan`, `GreaterThan` | 3 |
| 链上指标 | 原语策略 | `market_indicators`, `IdentityTransformer`, `PercentileRankTransformer` | 3 |
| 动态仓位 | 原语策略 | `LinearScaleWeight` | 1 |
| 配对交易 | 代码策略 | 自定义多资产轮换逻辑 | 2 |
**12个策略组合中,10个通过原语策略实现**——从经典的双均线到前沿的链上MVRV指标,原语系统展现了对主流量化策略的广泛覆盖。而配对交易这类需要在多资产间动态切换的复杂场景,则由代码策略补充支持。
---
## 第二章:基准的力量——买入持有的惊人表现
在评估任何主动策略之前,必须先看看"什么都不做"能获得什么。
### 2.1 回测环境
| 参数 | 设置 |
|------|------|
| **回测区间** | 2018-01-01 至 2026-01-01(8年) |
| **交易标的** | BTC、ETH、SOL |
| **初始资金** | $100,000 |
| **手续费** | 0.1%(加密货币交易所标准) |
### 2.2 关于参数选择与敏感性测试
**本研究的参数选择原则**:
本文的核心目标是**验证不同策略范式在加密货币市场的适用性**,而非寻找每个策略的最优参数。因此,我们采用了务实的参数选择策略:
**参数选择方式**:
1. **经典策略使用行业标准参数**:
- 双均线:50/200日(最经典的"黄金/死亡交叉"组合)
- RSI:30/70阈值,14日周期(技术分析教科书标准)
- 这些参数在传统股票和加密货币社区中被广泛使用
2. **链上指标使用逻辑清晰的阈值**:
- MVRV:买入阈值1.0(市价=成本)、卖出阈值5.0(历史顶部)
- NVT:90百分位(明显高估)
- 这些阈值基于指标本身的经济学含义,而非参数优化
3. **仅对MVRV动态仓位进行了详细的参数敏感性测试**:
- 测试了不同的仓位映射:100%→50%、100%→40%、100%→30%、100%→20%
- 目的:验证动态仓位策略的稳健性,确认收益提升不是过拟合的结果
- 结果:在合理范围内(20%-60%底仓),策略表现稳定,最终选择30%作为最低仓位
**为什么不对所有策略做参数敏感性测试?**
**1. 报告定位决定研究重点**
本文的主题是"很多策略和我们一开始想的不一样",核心发现是:
- 双均线这种"滞后"策略反而有效
- RSI这种经典指标全面失败
- 链上指标组合的Or逻辑失败
这些结论关注的是**策略范式的差异**(趋势 vs 回归、事件信号 vs 状态信号、And vs Or),而非参数优化。
**2. 核心结论的稳健性不依赖参数**
以RSI策略为例:
- 即使调整为25/75、35/65等不同阈值组合
- 即使调整RSI周期为7日、21日
- 在趋势主导的加密市场中,**均值回归范式的根本缺陷**依然存在
- 这不是参数问题,而是指标哲学与市场结构的不匹配
类似地:
- 双均线的成功在于"捕捉年度级大趋势",具体是50/200还是60/180影响不大
- MVRV+NVT失败的根源是卖出信号的Or逻辑,与具体阈值关系不大
**3. MVRV动态版的特殊性**
我们选择对MVRV动态仓位进行详细测试的原因:
- 这是本文唯一的"创新策略"(非经典方法)
- 动态仓位映射直接影响策略表现,需要验证稳健性
- 通过这个案例展示原语系统中参数敏感性测试的便捷性
**重要声明**:
本文展示的策略表现数据完全真实,没有经过"反向优化"。如果读者使用相近的参数(如45/180双均线、MVRV阈值0.8/4.5等),应该能获得类似的结论。我们关注的是策略思想的有效性,而非精确的数字。
如果您对某个策略的参数优化感兴趣,可以使用策引平台的原语系统快速测试不同参数组合。
### 2.3 基准策略表现
| 基准 | 年化收益 | 净值倍数 | 最大回撤 | 夏普比率 |
|------|---------|---------|---------|---------|
| **BTC买入持有** | **28.80%** | 7.65x | -78.91% | 0.59 |
| **ETH买入持有** | **19.95%** | 4.32x | -93.72% | 0.50 |
| SOL买入持有 | 91.55% | 42.50x | -96.27% | 0.44 |
> ⚠️ **SOL警示**:91%年化收益看起来惊人,但伴随着-96%的极端回撤,且历史期间短(仅2020-2026)。不建议将此作为主要参考基准。
**核心发现**:
1. **BTC买入持有是最可靠的基准**:8年7.65倍,年化28.80%,在加密货币中算是"稳健"的表现
2. **回撤是真正的考验**:-78%到-96%的回撤,意味着账户从高点跌去近80%-96%,绝大多数人无法承受
3. **这是主动策略必须战胜的对手**:如果你的策略连这个都跑不赢,那只是在浪费时间和手续费
---
## 第三章:12个策略组合的完整对比
### 3.1 全景数据表
**按年化收益排序,与基准对比**:
| 策略 | 年化收益 | 净值倍数 | 最大回撤 | 夏普比率 | 交易次数 | vs 对应基准 |
|------|---------|---------|---------|---------|---------|------------|
| **BTC MVRV动态** | **33.41%** | 10.15x | -71.84% | 0.60 | 1 | ✅ +4.61% |
| **BTC MVRV** | **31.03%** | 8.76x | -70.30% | 0.59 | 2 | ✅ +2.23% |
| 🏆 BTC买入持有 | 28.80% | 7.65x | -78.91% | 0.59 | 1 | — 基准 — |
| **ETH双均线** | **27.22%** | 6.92x | -72.60% | 0.44 | 8 | ✅ +7.27% |
| **BTC双均线** | **24.65%** | 5.87x | -59.49% | **0.68** | 8 | ⚠️ -4.15%收益,但回撤改善20% |
| 🏆 ETH买入持有 | 19.95% | 4.32x | -93.72% | 0.50 | 1 | — 基准 — |
| ETH/BTC趋势 | 12.29% | 2.54x | -68.26% | 0.42 | 86 | — |
| SOL双均线 | 5.14% | 1.35x | -63.08% | 0.25 | 5 | ❌ -86.41% |
| BTC MVRV+NVT | 4.78% | 1.46x | -55.09% | 0.26 | 17 | ❌ -24.02% |
| ETH/BTC均值回归 | 4.54% | 1.43x | -69.50% | 0.32 | 72 | — |
| ETH RSI | 4.38% | 1.41x | -66.77% | 0.23 | 12 | ❌ -15.57% |
| BTC RSI | 4.05% | 1.38x | -57.64% | 0.21 | 12 | ❌ -24.75% |
| BTC NVT | -4.18% | 0.71x | -50.19% | -0.10 | 8 | ❌ -32.98% |
| SOL RSI | -7.88% | 0.61x | -77.47% | 0.11 | 6 | ❌ -99.43% |
### 3.2 策略分层
**第一梯队:跑赢基准** ✅
| 策略 | 相对基准 | 核心价值 |
|------|---------|---------|
| BTC MVRV动态 | +4.61% | 最高收益,动态风控 |
| BTC MVRV | +2.23% | 8年仅2次交易,极简 |
| ETH双均线 | +7.27% | 同时跑赢基准+降低回撤 |
**第二梯队:牺牲收益换取风控** ⚠️
| 策略 | 相对基准 | 核心价值 |
|------|---------|---------|
| BTC双均线 | -4.15%收益 | 回撤从-79%改善到-59%,改善20个百分点 |
**第三梯队:跑输基准,不推荐** ❌
| 策略 | 相对基准 | 失败原因 |
|------|---------|---------|
| 所有RSI策略 | -15%~-99% | 指标范式与市场不匹配 |
| MVRV+NVT组合 | -24% | 卖出逻辑冲突 |
| NVT单独 | -33%(亏损) | 阈值不稳定 |
| SOL双均线 | -86% | 初始化陷阱 |
---
## 第四章:5个反直觉发现的深度剖析
### 发现一:双均线策略的"逆袭"
**预期**:50/200日双均线太滞后,在加密货币高波动环境中必定充满假信号。
**现实**:
- BTC双均线:年化24.65%,仅比基准低4%,但**回撤改善20个百分点**(-59% vs -79%)
- ETH双均线:年化27.22%,**跑赢基准7.27个百分点**,同时回撤改善21个百分点
**为什么"滞后"反而成了优势?**
1. **周期匹配**:加密货币的牛熊周期通常持续1-2年。50/200日均线恰好能捕捉这种"年度级别"的大趋势。
2. **滞后性过滤噪音**:这种"迟钝"反而成了优点——不会因一周的暴跌被"骗出"牛市,也不会因一周的反弹过早"踏入"熊市。
3. **避开熊市是关键**:该策略最大的成功在于几乎完美避开了2018年和2022年的大熊市。在加密世界,**不亏钱远比赚钱更重要**。
**SOL为何失败?**
SOL于2020年中才上线,当它在2021年开始主升浪时,200日均线数据刚刚形成。此时50日线已在200日线上方,**没有触发"金叉"买入信号**,错过了整个2021年的大牛市。
**教训**:对于历史较短的新币种,长周期均线策略需要注意初始化陷阱。
### 发现二:RSI策略的全面溃败
**预期**:RSI是经典摆动指标,识别超买超卖区域,在高波动市场应该能捕捉大量反转机会。
**现实**:
- BTC RSI:年化仅4.05%,跑输基准24.75个百分点
- ETH RSI:年化仅4.38%,跑输基准15.57个百分点
- SOL RSI:年化-7.88%,**实际亏损**
**为什么经典指标全面失效?**
1. **趋势 vs 回归的根本冲突**:RSI基于"均值回归"思想设计,假设价格偏离常态后会"回归"。但加密货币是典型的**趋势主导型**资产,价格可以长期单边运行。
2. **"超卖"不是"买入"**:在熊市中,RSI进入超卖区(<30)通常不意味着即将反弹,而是**下跌趋势强劲的确认**。2022年BTC从30000跌到16000的过程中,RSI多次触发买入信号,结果就是不断"接飞刀"。
3. **信号类型错配**:RSI策略使用`LessThan`这种**状态信号**,只要RSI处于30以下条件就一直为真。与之对比,双均线策略使用`CrossAbove`这种**事件信号**,只在穿越瞬间触发一次。
**核心洞察**:RSI策略的失败**不是参数问题,而是指标范式与市场结构的根本不匹配**。
### 发现三:链上指标组合的"1+1<1"
这是整个研究中最反直觉的发现。
**预期**:MVRV擅长识别底部,NVT擅长识别顶部,组合起来应该1+1>2。
**现实**:
| 策略 | 年化收益 | 最大回撤 | 交易次数 | vs 基准 |
|------|---------|---------|---------|--------|
| MVRV单独 | **31.03%** | -70.30% | 2次 | ✅ +2.23% |
| **MVRV+NVT组合** | **4.78%** | -55.09% | 17次 | ❌ -24.02% |
| NVT单独 | -4.18% | -50.19% | 8次 | ❌ -32.98% |
**组合策略的收益仅为单独MVRV的15%!**
**为什么组合失败了?**
问题出在**卖出逻辑的`Or`原语**。
组合策略的卖出信号是:`MVRV过高 OR NVT过高`
这意味着只要MVRV**或者**NVT任一触发卖出,策略就会清仓。但NVT比MVRV更频繁触及高点,在牛市中NVT可能多次触发卖出信号,而此时MVRV可能还远未到达顶部。
**结果**:NVT的卖出信号**过早终结了MVRV策略的持仓**,交易次数从2次暴增到17次,无法享受完整的牛市涨幅。
**原语洞察**:正确的组合方式应该是:
- **买入用`Or`**:捕捉更多机会
- **卖出用`And`**:减少干扰,同时满足两个条件才清仓
**这里体现了原语系统的独特价值**:如果使用黑盒信号系统或AI自动生成的策略,我们只能得出"这个组合不行"的结论。而原语系统允许我们**精确定位到失败发生在哪一层逻辑**——是`Or`原语放在了卖出信号中。这种可解释性,是策略持续改进的前提。
### 发现四:ETH/BTC配对的"180度反转"
**预期**:ETH/BTC是最成熟的加密货币配对,均值回归策略应该有效。
**现实**:
| 策略 | 年化收益 | 最大回撤 | 交易次数 |
|------|---------|---------|---------|
| ETH/BTC均值回归 | 4.54% | -69.50% | 72次 |
| **ETH/BTC趋势跟踪** | **12.29%** | -68.26% | 86次 |
**趋势跟踪版本的收益是均值回归版本的2.7倍!**
**发生了什么?**
2024-2025年,ETH相对BTC持续走弱。均值回归策略的逻辑是"ETH便宜了,买入等反弹",但现实是比率继续下跌——这不是"抄底",而是"接飞刀"。
**原语的敏捷迭代**:
当我们发现均值回归失效后,只需将一个原语从`LessThan`改为`GreaterThan`:
```json
// 均值回归版:比率 < 均线时买入ETH
{ "id": "eth_cheap", "type": "LessThan", ... }
// 趋势跟踪版:比率 > 均线时买入ETH
{ "id": "eth_strong", "type": "GreaterThan", ... }
```
整个逻辑180度反转,**耗时仅5分钟**。
这种从"均值回归"到"趋势跟踪"的范式切换,在传统量化系统中往往意味着重写策略代码、重新处理状态与仓位逻辑。而在原语系统中,它只是一次语义层的参数替换——**策略思想的差异被压缩为原语的结构差异**。
### 发现五:动态仓位的精细化进化
**预期**:用`LinearScaleWeight`实现动态仓位,应该比二元买卖更优。
**现实**:符合预期!
| 策略 | 年化收益 | 最大回撤 | 夏普比率 |
|------|---------|---------|---------|
| MVRV基础版 | 31.03% | -70.30% | 0.59 |
| **MVRV动态版** | **33.41%** | -71.84% | **0.60** |
年化收益从31%提升到33.4%,提升了2.4个百分点。
**动态仓位的映射逻辑**:
| MVRV值 | 目标仓位 | 市场含义 |
|--------|---------|---------|
| ≤1.0 | 100% | 极度恐慌,满仓抄底 |
| 2.0 | 77.5% | 市场回暖,保持重仓 |
| 3.0 | 55% | 市场中性,逐步减仓 |
| 4.0 | 42.5% | 市场偏热,继续减仓 |
| ≥5.0 | 30% | 市场狂热,降至低仓 |
**💡 在线演示**:
想直接查看这个策略的完整回测结果和实时表现?访问 [BTC MVRV动态仓位策略 - 在线回测](https://www.myinvestpilot.com/portfolios/custom_xf0j9k5a),可以看到策略的:
- 完整净值曲线和回撤图
- 每笔交易的详细记录
- 与基准的对比分析
- 年度表现分解
其他策略的配置文件在附录中提供,您可以在策引平台自行创建和回测。
---
## 第五章:链上指标的原语实现
MVRV和NVT是加密货币独有的链上指标,展示了原语系统接入**外部数据源**的能力。
### 5.1 MVRV单独策略
```json
{
"market_indicators": {
"indicators": [{ "code": "BTC_MVRV_ZSCORE" }],
"transformers": [{
"name": "mvrv_raw",
"type": "IdentityTransformer",
"params": { "indicator": "BTC_MVRV_ZSCORE", "field": "Close" }
}]
},
"trade_strategy": {
"indicators": [
{ "id": "mvrv_buy_threshold", "type": "Constant", "params": { "value": 1.0 } },
{ "id": "mvrv_sell_threshold", "type": "Constant", "params": { "value": 5.0 } }
],
"signals": [
{
"id": "mvrv_undervalued",
"type": "LessThan",
"inputs": [
{ "market": "BTC_MVRV_ZSCORE", "transformer": "mvrv_raw" },
{ "ref": "mvrv_buy_threshold" }
]
},
{
"id": "mvrv_overvalued",
"type": "GreaterThan",
"inputs": [
{ "market": "BTC_MVRV_ZSCORE", "transformer": "mvrv_raw" },
{ "ref": "mvrv_sell_threshold" }
]
}
],
"outputs": {
"buy_signal": "mvrv_undervalued",
"sell_signal": "mvrv_overvalued"
}
}
}
```
**关键配置解读**:
- `market_indicators`:引入外部链上数据`BTC_MVRV_ZSCORE`
- `IdentityTransformer`:将原始数据转换为可引用的数据流
- 买入阈值1.0,卖出阈值5.0——极其保守,确保只在极端位置交易
- **8年仅2次交易**,却跑赢了基准
### 5.2 MVRV+NVT组合策略(失败案例)
```json
{
"market_indicators": {
"indicators": [
{ "code": "BTC_MVRV_ZSCORE" },
{ "code": "BTC_NVT" }
],
"transformers": [
{
"name": "mvrv_raw",
"type": "IdentityTransformer",
"params": { "indicator": "BTC_MVRV_ZSCORE", "field": "Close" }
},
{
"name": "nvt_percentile",
"type": "PercentileRankTransformer",
"params": { "indicator": "BTC_NVT", "lookback": 252, "field": "Close" }
}
]
},
"trade_strategy": {
"indicators": [
{ "id": "mvrv_buy_threshold", "type": "Constant", "params": { "value": 1.0 } },
{ "id": "mvrv_sell_threshold", "type": "Constant", "params": { "value": 3.5 } },
{ "id": "nvt_filter_threshold", "type": "Constant", "params": { "value": 80 } },
{ "id": "nvt_extreme_high", "type": "Constant", "params": { "value": 90 } }
],
"signals": [
{
"id": "mvrv_undervalued",
"type": "LessThan",
"inputs": [
{ "market": "BTC_MVRV_ZSCORE", "transformer": "mvrv_raw" },
{ "ref": "mvrv_buy_threshold" }
]
},
{
"id": "mvrv_overvalued",
"type": "GreaterThan",
"inputs": [
{ "market": "BTC_MVRV_ZSCORE", "transformer": "mvrv_raw" },
{ "ref": "mvrv_sell_threshold" }
]
},
{
"id": "nvt_not_extreme",
"type": "LessThan",
"inputs": [
{ "market": "BTC_NVT", "transformer": "nvt_percentile" },
{ "ref": "nvt_filter_threshold" }
]
},
{
"id": "nvt_extreme_high_signal",
"type": "GreaterThan",
"inputs": [
{ "market": "BTC_NVT", "transformer": "nvt_percentile" },
{ "ref": "nvt_extreme_high" }
]
},
{
"id": "buy_signal_combined",
"type": "And",
"inputs": [
{ "ref": "mvrv_undervalued" },
{ "ref": "nvt_not_extreme" }
]
},
{
"id": "sell_signal_combined",
"type": "Or",
"inputs": [
{ "ref": "mvrv_overvalued" },
{ "ref": "nvt_extreme_high_signal" }
]
}
],
"outputs": {
"buy_signal": "buy_signal_combined",
"sell_signal": "sell_signal_combined"
}
}
}
```
**失败根源定位**:
- `PercentileRankTransformer`:将NVT转换为252日百分位排名
- `And`原语用于买入:MVRV低估**且**NVT不极端——这是对的
- **`Or`原语用于卖出**:MVRV高估**或**NVT极端——**这是问题所在**
- NVT更频繁触发卖出,打断了MVRV策略的长期持仓
### 5.3 MVRV动态仓位策略
```json
{
"market_indicators": {
"indicators": [{ "code": "BTC_MVRV_ZSCORE" }],
"transformers": [{
"name": "mvrv_raw",
"type": "IdentityTransformer",
"params": { "indicator": "BTC_MVRV_ZSCORE", "field": "Close" }
}]
},
"trade_strategy": {
"indicators": [
{ "id": "mvrv_buy_threshold", "type": "Constant", "params": { "value": 1.0 } }
],
"signals": [
{
"id": "mvrv_undervalued",
"type": "LessThan",
"inputs": [
{ "market": "BTC_MVRV_ZSCORE", "transformer": "mvrv_raw" },
{ "ref": "mvrv_buy_threshold" }
]
},
{
"id": "dynamic_weight",
"type": "LinearScaleWeight",
"inputs": [
{ "market": "BTC_MVRV_ZSCORE", "transformer": "mvrv_raw" }
],
"params": {
"min_indicator": 1.0,
"max_indicator": 5.0,
"min_weight": 1.0,
"max_weight": 0.3,
"clip": true
}
}
],
"outputs": {
"buy_signal": "mvrv_undervalued",
"target_weight": "dynamic_weight"
}
}
}
```
**关键配置解读**:
- `LinearScaleWeight`将MVRV从1.0-5.0线性映射到仓位100%-30%
- `clip: true`确保仓位不超出[30%, 100%]区间
- `outputs`使用`target_weight`而非`sell_signal`,激活动态仓位模式
- 无需修改代码,仅添加一个原语就完成了策略进化
**💡 查看实际运行效果**:这个策略已在策引平台部署并完成回测,您可以访问 [BTC MVRV动态仓位策略](https://www.myinvestpilot.com/portfolios/custom_xf0j9k5a) 查看完整的回测报告、交易记录和实时监控数据。
---
## 第六章:核心启示
### 关于加密货币策略
1. **基准是最低标准**:如果你的策略连买入持有都跑不赢,那只是在摧毁价值。在本研究的12个策略组合中,只有4个跑赢了对应基准。
2. **简单为王**:最简单的双均线策略反而表现最稳健。复杂的技术指标组合(RSI)全面溃败。
3. **回撤比收益更重要**:BTC双均线虽然年化少4%,但回撤改善20个百分点。对于无法承受-79%回撤的投资者,这是真正的价值。
4. **组合未必更优**:MVRV+NVT的失败说明,策略组合并非"指标堆砌"。如果内在逻辑冲突,结果只会是1+1<1。
5. **市场在变**:ETH/BTC配对交易的逻辑反转说明,没有一成不变的"圣杯"。
### 关于原语系统的价值:让策略研究从"经验艺术"变为"工程学科"
#### 原语系统的真正定位:策略研究的“中间表示层(IR)”
原语不是策略本身,而是策略的表达语言。
就像编译器里的中间表示(Intermediate Representation),它不是为了直接运行,而是为了让策略变得**可理解、可优化、可演化**。当策略被降维为统一的语义结构时,人和AI才能在同一个空间中对话。
这是把策略从“结果导向的黑盒”,变成“过程导向的可工程对象”的关键一步。
#### 传统策略系统的根本困境
在量化投资领域,策略失败是常态。但真正的问题不是"失败本身",而是**失败后无法归因**。
传统策略的表现形式通常是:
- **一段 Python 代码**:逻辑、数据处理、状态管理混在一起
- **一个黑盒信号**:由第三方平台生成,只能看到买卖点,看不到决策依据
- **一个回测报告**:只有最终的收益率和回撤,没有中间过程
当这样的策略失败时,你只能问:
- "是参数不对吗?" → 调整参数 → 过拟合陷阱
- "是指标失效了吗?" → 换个指标 → 无穷循环
- "是市场变了吗?" → 放弃策略 → 永远不知道真正原因
**核心问题是**:策略 = 不可拆解的整体,成败 = 不可归因的结果。
#### 原语系统的本质:策略的"语义化拆解"
原语系统做的事情,本质上是把策略从"黑盒"降维为"可组合、可验证、可进化的语义单元"。
每个策略都被拆解为明确的语义组件:
- **数据层**:`SMA`、`RSI`、`MVRV_ZSCORE` — 数据从哪来?
- **变换层**:`IdentityTransformer`、`PercentileRankTransformer` — 数据如何处理?
- **信号层**:`CrossAbove`、`LessThan`、`And/Or` — 决策逻辑是什么?
- **执行层**:`buy_signal`、`sell_signal`、`target_weight` — 如何转化为行动?
当策略失败时,你能精确定位到:
- **MVRV+NVT 组合失败**:定位到卖出信号的 `Or` 原语 → 是组合方式问题,不是指标问题
- **RSI 全面溃败**:定位到 `LessThan` 状态信号与趋势市场的范式冲突 → 是指标范式问题,不是参数问题
- **SOL 双均线失败**:定位到 200 日均线初始化不足 → 是数据窗口问题,不是策略逻辑问题
**这是策略研究第一次具备工程化的迭代属性**,而不再是"凭经验调参"的艺术。
#### 原语系统带来的五个核心能力
基于这一范式转变,原语系统在实践中展现了以下能力:
**1. 快速验证/证伪**
- 12个策略组合的完整测试,在几小时内完成
- 聚焦于策略逻辑本身,而非编程调试
- 从"几周写一个策略"变为"几小时验证一个想法"
**2. 透明定位失败**
- MVRV+NVT 组合失败时,立即定位到 `Or` 原语的卖出逻辑
- 不再是"整体重写",而是"定点修复"
- **可解释性**成为策略改进的前提
**3. 敏捷范式切换**
- 从"均值回归"到"趋势跟踪",只需修改一个原语(`LessThan` → `GreaterThan`)
- 5 分钟完成 180 度范式反转
- 策略思想的差异被压缩为原语的结构差异
**4. 渐进式进化**
- 从"二元买卖"到"动态仓位",只需添加一个 `LinearScaleWeight` 原语
- 无需重构整体架构,策略在原有基础上自然演化
- 支持"小步快跑"的迭代策略
**5. 为 AI 自动化探索奠定基础**
- 当策略差异被压缩为原语的结构化差异,自动搜索才有了操作空间
- AI 不再是"黑盒生成信号",而是"在语义空间中探索组合"
- 这是从"AI 辅助"到"AI 主导策略研究"的必要基础设施
---
**总结三句话**:
- 我们不试图预测市场,我们试图验证策略是否配得上被信任。
- 原语系统让策略第一次变成可解释、可组合、可演化的对象。
- 当 AI 能直接操作原语,而不是调参数或写代码时,策略探索才真正自动化。
### 策略选择指南
| 投资者类型 | 推荐策略 | 理由 |
|-----------|---------|------|
| 追求最高收益 | BTC MVRV动态 | 年化33.41%,跑赢基准4.6% |
| 极简主义者 | BTC MVRV | 8年2次交易,省心 |
| 回撤敏感者 | BTC双均线 | 回撤从-79%改善到-59% |
| ETH持有者 | ETH双均线 | 跑赢基准7.3%+降低回撤21% |
| 不想操作 | 买入持有BTC | 年化28.80%,无需任何操作 |
**永远不要**选择一个长期跑输买入持有的主动策略。
---
## 附录
### A. 完整配置文件
:::info 配置文件使用说明
以下配置文件是策引策略引擎内部完整的投资组合配置,包含了原语策略定义、资金策略、标的物等完整信息。
**如何在策引平台上使用这些策略**:
1. **创建原语策略组合**:访问 [策略组合创建页面](https://www.myinvestpilot.com/portfolios/create)
- 仅复制配置文件中 `strategy_definition` 部分的内容
- 粘贴到"交易策略定义"区域
- **必须删除** `capital_strategy` 字段(该字段仅供参考,在创建时通过界面选择对应的资金管理策略即可)
- 其他配置项无需复制,在创建投资组合时通过界面配置
2. **理解策略逻辑**:访问 [原语策略可视化编辑器](https://www.myinvestpilot.com/primitives-editor)
- 将 `strategy_definition` 粘贴到编辑器中
- 可视化查看策略的指标、信号和逻辑关系
- 支持在线调试和修改策略参数
3. **选择资金管理策略**:在创建投资组合时,根据配置文件中的 `capital_strategy` 类型,在界面上选择对应的资金管理策略(如固定金额、固定比例、再平衡等)
⚠️ **重要提示**:直接复制完整配置文件可能导致策略无法正常工作或产生意外行为。请严格按照上述步骤操作。
:::
**基准策略**:
- [BTC/ETH/SOL买入持有基准配置](https://media.i365.tech/myinvestpilot/docs/primitives/advanced/crypto-strategy-case/portfolio_config_bh_baselines.json)
**趋势跟踪策略**:
- [BTC双均线策略配置](https://media.i365.tech/myinvestpilot/docs/primitives/advanced/crypto-strategy-case/portfolio_config_crypto_btc_dual_ma.json)
- [ETH双均线策略配置](https://media.i365.tech/myinvestpilot/docs/primitives/advanced/crypto-strategy-case/portfolio_config_crypto_eth_dual_ma.json)
- [SOL双均线策略配置](https://media.i365.tech/myinvestpilot/docs/primitives/advanced/crypto-strategy-case/portfolio_config_crypto_sol_dual_ma.json)
**技术指标策略**:
- [BTC RSI策略配置](https://media.i365.tech/myinvestpilot/docs/primitives/advanced/crypto-strategy-case/portfolio_config_crypto_btc_rsi_macd.json)
- [ETH RSI策略配置](https://media.i365.tech/myinvestpilot/docs/primitives/advanced/crypto-strategy-case/portfolio_config_crypto_eth_rsi_macd.json)
- [SOL RSI策略配置](https://media.i365.tech/myinvestpilot/docs/primitives/advanced/crypto-strategy-case/portfolio_config_crypto_sol_rsi_macd.json)
**链上指标策略**:
- [BTC MVRV策略配置](https://media.i365.tech/myinvestpilot/docs/primitives/advanced/crypto-strategy-case/portfolio_config_crypto_btc_mvrv.json)
- [BTC MVRV动态仓位策略配置](https://media.i365.tech/myinvestpilot/docs/primitives/advanced/crypto-strategy-case/portfolio_config_crypto_btc_mvrv_dynamic.json)
- [BTC MVRV+NVT组合策略配置](https://media.i365.tech/myinvestpilot/docs/primitives/advanced/crypto-strategy-case/portfolio_config_crypto_btc_mvrv_nvt.json)
- [BTC NVT策略配置](https://media.i365.tech/myinvestpilot/docs/primitives/advanced/crypto-strategy-case/portfolio_config_crypto_btc_nvt.json)
**配对交易策略**:
- [ETH/BTC均值回归策略配置](https://media.i365.tech/myinvestpilot/docs/primitives/advanced/crypto-strategy-case/portfolio_config_crypto_eth_btc_pairs.json)
- [ETH/BTC趋势跟踪策略配置](https://media.i365.tech/myinvestpilot/docs/primitives/advanced/crypto-strategy-case/portfolio_config_crypto_eth_btc_trend.json)
### B. 数据来源说明
本文所有价格数据和链上指标数据均由策引数据服务提供。
### C. 风险提示
本文所有策略仅供研究和教育目的,不构成投资建议。加密货币市场波动极大,历史表现不代表未来收益。在实盘交易前,请务必:
1. 充分理解策略逻辑和风险
2. 根据自身风险承受能力调整仓位
3. 永远不要投入超过你能承受损失的资金
---
**面向未来**:当策略可以被稳定地拆解为原语时,人类负责提出假设,AI 负责在原语空间中验证、反驳和演化假设,就不再是幻想,而只是算力和成本的问题。
--------------------------------------------------------------------------------
信号确认案例 (advanced/signal-confirmation-case.md)
--------------------------------------------------------------------------------
# 信号确认的艺术:速度与质量的艰难权衡
## 引言
在杠杆ETF的趋势跟随策略中,有一个永恒的两难困境:**反应速度与信号质量**。
反应太快,你会被市场的每一次震荡骗得团团转,频繁进出导致收益被手续费和假信号侵蚀殆尽;反应太慢,你又会错过趋势的起点和终点,眼睁睁看着利润流失。
本文记录了一次完整的策略对比实验:针对TQQQ(3倍杠杆纳斯达克100 ETF)这个极端波动的标的,我们测试了三种不同的信号确认机制,试图找到这个两难问题的最优解。
最终的发现既出人意料又发人深省:**最快的不一定最好,最慢的也未必最优,关键在于理解不同市场环境下的权衡**。
## 问题的起源:一个投资者的痛苦经历
### 买入持有的诱惑与陷阱
2010年2月,TQQQ上市。如果在那天买入10万美元并持有至2025年底,账户价值将变成惊人的2538万美元——**253倍收益,年化41.68%**。
这是一个足以让任何投资者心动的数字。
但现实是残酷的:在这15.9年中,TQQQ经历了**最大回撤-81.65%**。这意味着在最黑暗的时刻,你的账户从某个高点跌到只剩18.35%。10万美元变成1.8万美元。
心理学研究显示:95%的投资者会在回撤达到-50%时恐慌性抛售。而-81%的回撤,对绝大多数人来说,是完全无法承受的心理折磨。
### 趋势跟随的承诺
于是,一个很自然的想法出现了:**能否通过技术分析,在上涨趋势中持有TQQQ,在下跌趋势开始时切换到现金?**
这就是趋势跟随策略的核心理念。而最经典的趋势判断工具,就是200日移动平均线(MA200)——华尔街公认的牛熊分界线。
**基础策略逻辑**:
- 当QQQ(纳斯达克100指数基金)的价格站上MA200之上1%以上时,买入TQQQ
- 当QQQ的价格跌破MA200之下1%以上时,清仓TQQQ,持有现金
这个策略听起来简单直接。但魔鬼藏在细节中:**如何定义"站上"和"跌破"?是单日触发就算,还是需要连续确认?**
这个看似技术性的问题,实际上关系到策略的生死存亡。
## 核心困境:假突破的代价
### 2016年的噩梦:横盘震荡期
让我们看一个真实的历史案例。2016年,QQQ进入了一个典型的横盘震荡期,价格在MA200附近反复穿越。
在这一年中,如果使用单日触发的信号:
- 买入信号触发6次
- 卖出信号触发6次
- 总共进出12次
每次交易都伴随着情绪的折磨:
- **刚买入就下跌**:昨天突破MA200买入TQQQ,今天又跌回去,手续费白交了
- **刚卖出就上涨**:昨天跌破MA200卖出,今天又反弹回来,踏空了
- **连续打脸**:在均线附近被反复"抽耳光",信心崩溃
这就是交易者口中的"**whipsaw**"(锯齿效应)——像锯子一样来回切割你的账户和心理。
### 假突破的本质
为什么会出现假突破?
市场不是一条平滑的曲线,而是由无数参与者的情绪和行为组成的复杂系统。在关键技术位(如MA200)附近,多空双方会进行激烈的拉锯:
- **多头试探**:价格突破MA200,多头试探性买入
- **空头反扑**:空头认为是假突破,大举做空
- **反复震荡**:双方僵持不下,价格在均线附近反复震荡
在这种情况下,单日的突破信号可能只是噪音,而非真实的趋势变化。
### 解决方案的探索方向
既然单日信号会产生过多假信号,一个自然的想法是:**要求信号连续出现多天,才确认为真实的趋势变化**。
这就是**信号确认机制**的核心思想。
但随之而来的问题是:
- **确认几天合适?** 2天、3天、还是5天?
- **买入和卖出都需要确认吗?** 还是只确认其中一方?
- **确认的代价是什么?** 会不会因为延迟而错过机会或扩大损失?
这些问题没有标准答案。唯一的方法是:**用真实的历史数据进行系统性测试**。
## 实验设计:三个版本的对比测试
为了回答上述问题,我们设计了三个不同的策略版本,在相同的条件下进行回测对比。
### 测试环境
| 参数 | 设置 |
|------|------|
| **回测区间** | 2010-02-11 至 2025-12-30(15.9年) |
| **交易标的** | TQQQ(3倍杠杆纳斯达克100 ETF) |
| **信号源** | QQQ相对于MA200的强度 |
| **买入阈值** | 相对强度 > 101(价格比MA200高1%以上) |
| **卖出阈值** | 相对强度 < 99(价格比MA200低1%以上) |
| **初始资金** | $100,000 |
| **手续费** | 0.01%(接近真实成本) |
### 三个版本的核心差异
**版本1:单日信号版(Baseline)**
- **买入条件**:相对强度 > 101,当日触发立即买入
- **卖出条件**:相对强度 < 99,当日触发立即卖出
- **特点**:反应最快,但可能被假信号困扰
**版本2:卖出确认版(Lag Confirm)**
- **买入条件**:相对强度 > 101,当日触发立即买入(保持快速入场)
- **卖出条件**:相对强度 < 99,**连续2天**才触发卖出
- **特点**:买入快,卖出慢,减少卖出假信号
**版本3:双向确认版(Bidirectional Lag)**
- **买入条件**:相对强度 > 101,**连续2天**才触发买入
- **卖出条件**:相对强度 < 99,**连续2天**才触发卖出
- **特点**:买卖都慢,最大程度减少假信号
### 设计逻辑的深层考虑
**为什么版本2只确认卖出?**
趋势跟随策略有一个不对称性:
- **上涨趋势初期**:及时入场很重要,晚一天就少赚一天
- **下跌趋势初期**:保护利润更重要,宁可晚一天也不要被假突破骗出去
因此,版本2采用了"快进慢出"的策略:买入时保持敏捷,卖出时要求确认。
**为什么是2天确认?**
这是一个平衡点:
- 1天:相当于无确认
- 2天:过滤掉单日异常波动
- 3天或更多:确认时间过长,可能导致显著滞后
我们选择2天作为测试参数,既不过于激进,也不过于保守。
## 回测结果:数据的启示
### 性能汇总:出人意料的结果
| 指标 | V1 单日信号 | V2 卖出确认 | V3 双向确认 | V4 VIX过滤 | 买入持有 |
|------|-------------|-------------|-------------|------------|----------|
| **收益倍数** | **60.41x** | 55.07x | 60.26x | 52.50x | 253.84x |
| **年化收益** | **29.45%** | 28.69% | 29.43% | 28.31% | 41.68% |
| **最大回撤** | -56.00% | -59.18% | -59.03% | **-51.46%** | -81.65% |
| **夏普比率** | 0.73 | 0.71 | **0.74** | 0.71 | 0.88 |
| **Calmar比率** | 0.53 | 0.48 | 0.50 | **0.55** | 0.51 |
| **波动率** | 43.73% | 44.72% | 44.13% | **42.16%** | 61.10% |
| **交易次数** | 43次 | 37次 | 33次 | **39次** | 0次 |
| **胜率** | 36.36% | 42.11% | 47.06% | **50.00%** | N/A |
| **盈亏比** | 20.14 | **24.11** | 21.37 | 15.92 | N/A |
### 第一个意外:单日信号版在确认机制中表现最好
在三个信号确认版本(V1-V3)中,最让人意外的是:**最简单的单日信号版(V1)表现最佳**。
- **收益最高**:60.41倍,比V2高出9.7%
- **回撤最小**(在V1-V3中):-56.00%,比V2和V3少3-4个百分点
- **Calmar优秀**:0.53,在三个确认版本中领先
这个结果挑战了我们的直觉:难道信号确认机制反而降低了策略表现?
### 真正的赢家:V4 VIX过滤版
然而,当我们将视野扩展到**V4 VIX过滤版**时,发现了更重要的启示:
- **最低回撤**:-51.46%,比V1还低4.5个百分点
- **最高Calmar**:0.55,超越V1和买入持有(0.51)
- **最高胜率**:50%,显著高于其他版本
- **最低波动率**:42.16%,风险控制最优
**核心发现**:单纯的信号确认机制无法从根本上解决策略问题。**波动率过滤**才是更有效的优化方向。
### 第二个意外:双向确认的胜率优势
虽然V3的收益和回撤不如V1,但在交易质量方面表现突出:
- **胜率最高**:47.06%,几乎是V1的1.3倍
- **交易次数最少**:33次,减少了23%的交易频率
- **夏普比率最高**:0.74,说明收益的稳定性更好
这说明双向确认确实有效减少了无效交易,提高了交易质量。
### 第三个意外:卖出确认版的尴尬地位
V2(卖出确认版)的表现最为尴尬:
- 收益低于V1和V3
- 回撤反而最大
- 各项指标都处于中游或垫底
这是为什么?"快进慢出"的逻辑不是应该更优吗?
## 深度分析:在关键时刻寻找答案
要理解三个版本的差异,我们需要深入到具体的历史时期,看看它们在关键时刻的表现。
### 关键时期一:2011年欧债危机
**市场背景**:2011年,欧洲主权债务危机爆发,全球股市暴跌。
**三版本表现**:
| 版本 | 2011年收益 | 解释 |
|------|------------|------|
| V1 单日信号 | **-37.35%** | 及时退出,控制了损失 |
| V2 卖出确认 | **-48.54%** | 卖出延迟,多承受了2天暴跌 |
| V3 双向确认 | **-37.35%** | 及时退出,表现与V1相同 |
**核心发现**:在**快速暴跌**的市场中,卖出确认机制是致命的。
2011年的暴跌非常突然,从触发卖出信号到实际执行,V2因为需要连续2天确认,多承受了额外的跌幅。这导致V2全年亏损比V1多出11个百分点。
**教训**:**在极端风险来临时,速度比确认更重要**。
### 关键时期二:2016年横盘震荡期
**市场背景**:2016年,QQQ在MA200附近反复震荡,典型的whipsaw陷阱期。
**三版本表现**:
| 版本 | 2016年收益 | 交易次数 | 解释 |
|------|------------|----------|------|
| V1 单日信号 | -14.94% | 6次 | 频繁交易,但亏损有限 |
| V2 卖出确认 | -13.83% | 5次 | 略微减少交易,效果不明显 |
| V3 双向确认 | **-20.09%** | 4次 | 交易最少,但亏损更大 |
**核心发现**:在**横盘震荡**中,确认机制并不能有效减少亏损,甚至可能因为延迟入场而错过短暂的反弹。
所有三个版本在2016年都经历了痛苦,这说明**MA200策略在横盘市场存在固有缺陷,单纯的信号确认无法根本解决问题**。
**教训**:**确认机制不是万能药,它无法改变策略的底层逻辑缺陷**。
### 关键时期三:2015-2025 vs 2010-2025
这是最有启发性的发现。我们注意到,如果只看最近10年(2015-2025),V2的表现明显优于V1:
| 时期 | V1收益 | V2收益 | V2优势 |
|------|--------|--------|--------|
| **2015-2025(10年)** | 20.52倍 | **23.88倍** | V2胜出16% |
| **2010-2025(15.9年)** | **60.41倍** | 55.07倍 | V1胜出10% |
**这说明什么?**
这揭示了一个关键的策略优化陷阱:**在某个时间段表现最优的参数,在更长的时间跨度上可能不是最优**。
如果我们只用2015-2025的数据进行回测,会错误地认为V2是最优策略。但当加入2010-2015的早期数据后,V1反而表现更好。
**根本原因**:
- 2010-2015包含了2011年欧债危机这样的**快速暴跌事件**,V2的延迟卖出机制在这类事件中表现糟糕
- 2015-2025的市场相对温和,延迟卖出避免了一些假信号,因此表现更好
**教训**:**策略优化必须在足够长的时间跨度和多样化的市场环境中验证,避免过度拟合特定时期**。
### 为什么V1最终胜出?
综合来看,V1(单日信号版)表现最好的原因是:
1. **快速响应极端风险**:在2011年这样的暴跌中,及时止损至关重要
2. **简单性的优势**:没有复杂的确认机制,适应性更强
3. **时间跨度的考验**:在15.9年的完整周期中,经历了更多样化的市场环境
但这并不意味着信号确认机制毫无价值。V3(双向确认)虽然绝对收益略低,但胜率和夏普比率更高,说明它在**交易质量**方面有明显优势。
## Lag原语:技术实现的简洁之美
虽然我们不展示代码细节,但理解Lag原语的工作原理对于应用这个机制非常重要。
### 什么是Lag原语?
Lag原语的作用是**将信号序列向后移动指定的周期数**,使得在任意日期可以访问"N天前"的信号值。
**核心能力**:让策略能够"记忆"历史信号,实现连续确认逻辑。
### 信号确认的逻辑链条
以卖出确认为例,实现"连续2天跌破99才卖出"的逻辑需要三步:
**第1步:判断今天是否跌破**
- 计算今日的相对强度是否小于99
- 输出:True(跌破)或False(未跌破)
**第2步:获取昨天的判断结果**
- 使用Lag原语,获取前1天的判断结果
- 这就是"昨天是否也跌破99"
**第3步:组合判断**
- 使用And逻辑原语:今天跌破 AND 昨天跌破
- 只有两者都为True,才输出最终的卖出信号
### 可视化的信号传递
让我们看一个具体的例子:
| 日期 | 相对强度 | 今日跌破99? | 昨日跌破99? | 连续2日确认? | 最终操作 |
|------|----------|-------------|-------------|--------------|----------|
| 11-01 | 101.2 | 否 | 否 | 否 | 持有TQQQ |
| 11-02 | 100.5 | 否 | 否 | 否 | 持有TQQQ |
| 11-03 | 98.5 | **是** | 否 | **否** | ⚠️ 第1天跌破,但不卖 |
| 11-04 | 98.2 | **是** | **是** | **是** | ✅ 连续2天,确认卖出 |
| 11-05 | 97.8 | 是 | 是 | 是 | 继续空仓 |
| 11-06 | 99.5 | 否 | 是 | 否 | 仍在观察 |
| 11-07 | 101.5 | 否 | 否 | 否 | 准备买入 |
**关键时刻(11-03)**:
- **单日信号版**:立即卖出TQQQ
- **卖出确认版**:等待次日确认,暂不卖出
如果11-04相对强度反弹至99以上,确认机制就成功避免了一次假突破。但如果11-04继续下跌,确认机制就会因为延迟多承受一天的损失。
**这就是信号确认的本质权衡:用延迟换取质量**。
## 动手实践:完整策略配置
如果你想在策引平台上创建这三个策略版本,下面提供完整的原语策略配置。你可以在创建原语策略时,直接复制这些JSON配置。
### 资金策略说明
三个策略版本都使用**百分比策略(PercentCapitalStrategy)**,设置为100%满仓单一标的TQQQ。关于百分比策略的详细说明,请参考:[百分比策略文档](/docs/capital-strategies/percent-strategy)。
### V1:单日信号版(Baseline)
最简单直接的版本,买卖信号当日触发立即执行。
```json
{
"market_indicators": {
"indicators": [{ "code": "QQQ" }],
"transformers": [
{
"name": "qqq_close",
"type": "IdentityTransformer",
"params": {
"indicator": "QQQ",
"field": "Close"
}
},
{
"name": "qqq_ma200",
"type": "MovingAverageTransformer",
"params": {
"indicator": "QQQ",
"window": 200,
"method": "simple",
"field": "Close"
}
},
{
"name": "qqq_rs_ma200",
"type": "RelativeStrengthTransformer",
"params": {
"indicator": "QQQ",
"reference": "ma",
"window": 200,
"field": "Close"
}
}
]
},
"trade_strategy": {
"indicators": [
{
"id": "threshold_buy",
"type": "Constant",
"params": { "value": 101 }
},
{
"id": "threshold_sell",
"type": "Constant",
"params": { "value": 99 }
}
],
"signals": [
{
"id": "qqq_above_ma200",
"type": "GreaterThan",
"inputs": [
{ "market": "QQQ", "transformer": "qqq_rs_ma200" },
{ "ref": "threshold_buy" }
]
},
{
"id": "qqq_below_ma200",
"type": "LessThan",
"inputs": [
{ "market": "QQQ", "transformer": "qqq_rs_ma200" },
{ "ref": "threshold_sell" }
]
}
],
"outputs": {
"buy_signal": "qqq_above_ma200",
"sell_signal": "qqq_below_ma200"
}
}
}
```
**核心特点**:
- 使用QQQ的相对强度(RS)作为信号源
- 买入阈值:101(价格比MA200高1%以上)
- 卖出阈值:99(价格比MA200低1%以上)
- 无任何延迟机制,反应最快
### V2:卖出确认版(Lag Confirm)
买入保持快速,卖出要求连续2天确认。
```json
{
"market_indicators": {
"indicators": [{ "code": "QQQ" }],
"transformers": [
{
"name": "qqq_close",
"type": "IdentityTransformer",
"params": {
"indicator": "QQQ",
"field": "Close"
}
},
{
"name": "qqq_ma200",
"type": "MovingAverageTransformer",
"params": {
"indicator": "QQQ",
"window": 200,
"method": "simple",
"field": "Close"
}
},
{
"name": "qqq_rs_ma200",
"type": "RelativeStrengthTransformer",
"params": {
"indicator": "QQQ",
"reference": "ma",
"window": 200,
"field": "Close"
}
}
]
},
"trade_strategy": {
"indicators": [
{
"id": "threshold_buy",
"type": "Constant",
"params": { "value": 101 }
},
{
"id": "threshold_sell",
"type": "Constant",
"params": { "value": 99 }
}
],
"signals": [
{
"id": "qqq_above_ma200",
"type": "GreaterThan",
"inputs": [
{ "market": "QQQ", "transformer": "qqq_rs_ma200" },
{ "ref": "threshold_buy" }
]
},
{
"id": "rs_below_99",
"type": "LessThan",
"inputs": [
{ "market": "QQQ", "transformer": "qqq_rs_ma200" },
{ "ref": "threshold_sell" }
]
},
{
"id": "rs_below_99_yesterday",
"type": "Lag",
"params": {
"periods": 1,
"fill_value": 0
},
"inputs": [{ "ref": "rs_below_99" }]
},
{
"id": "qqq_below_ma200_confirmed",
"type": "And",
"inputs": [
{ "ref": "rs_below_99" },
{ "ref": "rs_below_99_yesterday" }
]
}
],
"outputs": {
"buy_signal": "qqq_above_ma200",
"sell_signal": "qqq_below_ma200_confirmed"
}
}
}
```
**核心特点**:
- 买入信号:与V1相同,快速反应
- 卖出信号:使用Lag原语获取昨天的判断结果
- And原语:要求今天AND昨天都跌破99
- 目标:减少卖出假信号,避免被短期波动骗出
### V3:双向确认版(Bidirectional Lag)
买入和卖出都要求连续2天确认。
```json
{
"market_indicators": {
"indicators": [{ "code": "QQQ" }],
"transformers": [
{
"name": "qqq_close",
"type": "IdentityTransformer",
"params": {
"indicator": "QQQ",
"field": "Close"
}
},
{
"name": "qqq_ma200",
"type": "MovingAverageTransformer",
"params": {
"indicator": "QQQ",
"window": 200,
"method": "simple",
"field": "Close"
}
},
{
"name": "qqq_rs_ma200",
"type": "RelativeStrengthTransformer",
"params": {
"indicator": "QQQ",
"reference": "ma",
"window": 200,
"field": "Close"
}
}
]
},
"trade_strategy": {
"indicators": [
{
"id": "threshold_buy",
"type": "Constant",
"params": { "value": 101 }
},
{
"id": "threshold_sell",
"type": "Constant",
"params": { "value": 99 }
}
],
"signals": [
{
"id": "rs_above_101",
"type": "GreaterThan",
"inputs": [
{ "market": "QQQ", "transformer": "qqq_rs_ma200" },
{ "ref": "threshold_buy" }
]
},
{
"id": "rs_above_101_yesterday",
"type": "Lag",
"params": {
"periods": 1,
"fill_value": 0
},
"inputs": [{ "ref": "rs_above_101" }]
},
{
"id": "qqq_above_ma200_confirmed",
"type": "And",
"inputs": [
{ "ref": "rs_above_101" },
{ "ref": "rs_above_101_yesterday" }
]
},
{
"id": "rs_below_99",
"type": "LessThan",
"inputs": [
{ "market": "QQQ", "transformer": "qqq_rs_ma200" },
{ "ref": "threshold_sell" }
]
},
{
"id": "rs_below_99_yesterday",
"type": "Lag",
"params": {
"periods": 1,
"fill_value": 0
},
"inputs": [{ "ref": "rs_below_99" }]
},
{
"id": "qqq_below_ma200_confirmed",
"type": "And",
"inputs": [
{ "ref": "rs_below_99" },
{ "ref": "rs_below_99_yesterday" }
]
}
],
"outputs": {
"buy_signal": "qqq_above_ma200_confirmed",
"sell_signal": "qqq_below_ma200_confirmed"
}
}
}
```
**核心特点**:
- 买入信号:使用Lag原语,要求连续2天RS > 101
- 卖出信号:使用Lag原语,要求连续2天RS < 99
- 双向确认:买卖都需要And原语组合今天和昨天的判断
- 目标:最大程度减少假信号,提高交易质量
### V4:VIX过滤增强版(推荐)
在V2基础上增加VIX波动率过滤,实现最优的风险调整后收益。
```json
{
"market_indicators": {
"indicators": [
{ "code": "QQQ" },
{ "code": "VIX" }
],
"transformers": [
{
"name": "qqq_close",
"type": "IdentityTransformer",
"params": {
"indicator": "QQQ",
"field": "Close"
}
},
{
"name": "qqq_ma200",
"type": "MovingAverageTransformer",
"params": {
"indicator": "QQQ",
"window": 200,
"method": "simple",
"field": "Close"
}
},
{
"name": "qqq_rs_ma200",
"type": "RelativeStrengthTransformer",
"params": {
"indicator": "QQQ",
"reference": "ma",
"window": 200,
"field": "Close"
}
},
{
"name": "vix_raw",
"type": "IdentityTransformer",
"params": {
"indicator": "VIX",
"field": "Close"
}
}
]
},
"trade_strategy": {
"indicators": [
{
"id": "threshold_buy",
"type": "Constant",
"params": { "value": 101 }
},
{
"id": "threshold_sell",
"type": "Constant",
"params": { "value": 99 }
},
{
"id": "vix_threshold_low",
"type": "Constant",
"params": { "value": 30 }
},
{
"id": "vix_threshold_panic",
"type": "Constant",
"params": { "value": 40 }
}
],
"signals": [
{
"id": "qqq_above_ma200",
"type": "GreaterThan",
"inputs": [
{ "market": "QQQ", "transformer": "qqq_rs_ma200" },
{ "ref": "threshold_buy" }
]
},
{
"id": "vix_not_high",
"type": "LessThan",
"inputs": [
{ "market": "VIX", "transformer": "vix_raw" },
{ "ref": "vix_threshold_low" }
]
},
{
"id": "buy_condition_with_vix",
"type": "And",
"inputs": [
{ "ref": "qqq_above_ma200" },
{ "ref": "vix_not_high" }
]
},
{
"id": "rs_below_99",
"type": "LessThan",
"inputs": [
{ "market": "QQQ", "transformer": "qqq_rs_ma200" },
{ "ref": "threshold_sell" }
]
},
{
"id": "rs_below_99_yesterday",
"type": "Lag",
"params": {
"periods": 1,
"fill_value": 0
},
"inputs": [{ "ref": "rs_below_99" }]
},
{
"id": "qqq_below_ma200_confirmed",
"type": "And",
"inputs": [
{ "ref": "rs_below_99" },
{ "ref": "rs_below_99_yesterday" }
]
},
{
"id": "vix_panic",
"type": "GreaterThan",
"inputs": [
{ "market": "VIX", "transformer": "vix_raw" },
{ "ref": "vix_threshold_panic" }
]
},
{
"id": "sell_condition_with_vix",
"type": "Or",
"inputs": [
{ "ref": "qqq_below_ma200_confirmed" },
{ "ref": "vix_panic" }
]
}
],
"outputs": {
"buy_signal": "buy_condition_with_vix",
"sell_signal": "sell_condition_with_vix"
}
}
}
```
**核心特点**:
- 买入信号:QQQ > 101 AND VIX < 30(双重过滤)
- 卖出信号:(QQQ < 99连续2天) OR VIX > 40(双重触发)
- 市场指标:同时监控QQQ和VIX
- 目标:在波动率正常时参与,恐慌时快速退出
**为什么推荐V4**:
- 最低回撤:-51.46%
- 最高Calmar:0.55(优于买入持有)
- 最高胜率:50%
- 在极端市场环境下表现最优(如2020年COVID、2022年加息)
### 配置使用提示
1. **交易标的**:配置完成后,在标的选择中添加TQQQ
2. **回测时间**:建议使用2010-02-11至今的完整时间段
3. **手续费设置**:建议设置为0.01%(接近美股真实成本)
4. **对比测试**:可以同时创建四个组合进行对比
5. **推荐起点**:如果是第一次尝试,建议直接使用V4作为起点
## 实战启示:如何选择合适的确认机制
### 没有完美的策略,只有合适的权衡
通过这次完整的对比测试,我们得到了一个重要的认知:
> **在投资中,不存在在所有市场环境下都最优的策略。每个设计选择都是一种权衡,关键是理解这种权衡,并选择与你的投资目标和风险承受力相匹配的版本。**
### 三版本的适用场景
**选择V1(单日信号版)如果你:**
- 重视绝对收益最大化
- 担心极端黑天鹅事件(如2008金融危机、2020年COVID暴跌)
- 希望策略在长期和多样化的市场环境中具有稳健性
- 能够接受较多的交易次数和相对较低的胜率
**选择V3(双向确认版)如果你:**
- 重视交易质量胜过绝对收益
- 希望减少交易频率,降低心理压力
- 追求更高的胜率和夏普比率
- 相信未来市场会相对温和,不会出现极端快速暴跌
**慎重选择V2(卖出确认版)因为:**
- 在历史回测中表现最为尴尬
- "快进慢出"的理论逻辑在实践中并未得到验证
- 在极端风险来临时,延迟卖出可能导致灾难性损失
### 超越信号确认:波动率过滤的威力
我们的测试揭示了一个重要事实:**单纯的信号确认机制并不能根本解决策略的固有问题**。
在2016年的横盘震荡期,所有三个信号确认版本都表现糟糕,这说明MA200策略本身在震荡市场存在弱点。
这时,**V4 VIX过滤版**展示了一个更有效的优化方向。
#### V4的核心设计:市场恐慌指数作为第二道防线
V4在V2(卖出确认版)的基础上,增加了VIX(波动率指数)作为额外的过滤条件:
**买入条件(三重过滤):**
1. QQQ相对强度 > 101(趋势确认)
2. **VIX < 30(波动率正常)**
3. 两个条件同时满足才买入
**卖出条件(双重触发):**
1. QQQ相对强度 < 99连续2天(趋势反转确认),**或**
2. **VIX > 40(恐慌性止损)**
3. 任一条件触发即卖出
#### 为什么VIX过滤如此有效?
**VIX(恐慌指数)的含义**:
- VIX < 20:市场平静,低波动环境
- VIX 20-30:正常波动范围
- VIX 30-40:市场紧张,高波动
- VIX > 40:极度恐慌,市场崩溃风险
**对杠杆ETF的影响**:
1. **波动衰减效应**:VIX高时,杠杆ETF因为每日重新平衡会遭受严重的波动损耗
2. **下跌风险**:VIX > 40通常对应市场暴跌
3. **假突破频繁**:高波动期MA200会频繁被穿越
**V4的智慧**:
- **入场门槛高**:VIX < 30确保只在低波动环境买入TQQQ
- **出场果断**:VIX > 40立即退出,不等MA200确认
- **2020年3月验证**:COVID暴跌时VIX飙升至80+,V4提前退出避开最惨烈的下跌
#### V4的关键时期表现
**2020年COVID暴跌**:
| 策略版本 | 退出时间 | 避开跌幅 | 关键差异 |
|----------|----------|----------|----------|
| V1-V3 | 3月中旬(MA200触发) | 部分避开 | 延迟导致多承受10%+跌幅 |
| **V4** | **2月底(VIX>40触发)** | **几乎完全避开** | **提前2周退出** |
| 买入持有 | 不退出 | -65%暴跌 | 完整承受 |
**2022年加息熊市**:
- VIX长期维持在25-35区间
- V4多次因VIX过滤拒绝入场
- 避开了多次假突破
- 全年表现:V4 +0.80% vs V1 -2.64%
#### V4为何Calmar最高?
让我们看风险调整后的真实表现:
| 策略 | 年化收益 | 最大回撤 | Calmar | 解读 |
|------|----------|----------|--------|------|
| V1 | 29.45% | -56.00% | 0.53 | 高收益但回撤大 |
| V4 | 28.31% | **-51.46%** | **0.55** | **收益略低但回撤显著降低** |
| 买入持有 | 41.68% | -81.65% | 0.51 | 高收益不可执行 |
**关键洞察**:
- V4收益仅比V1低1.14%(29.45% vs 28.31%)
- 但回撤降低了4.5个百分点(-56% vs -51.46%)
- **每承担1%回撤,V4获得0.55%年化收益,优于所有版本**
#### 其他优化方向的探索
除了V4展示的波动率过滤,还有其他可能的优化方向:
1. **多重市场确认**:不仅看QQQ,还结合其他市场指标
- 例如:要求标普500也站上MA200,双重确认市场环境
2. **动态参数调整**:根据市场波动率自适应调整阈值
- 高波动期:要求更强的确认(如105而非101)
- 低波动期:可以降低阈值以提高参与度
3. **仓位管理**:不是简单的全仓或空仓
- 根据信号强度分配50%、75%、100%的仓位
但V4已经证明:**在现有框架内,波动率过滤是最简单且最有效的优化方式**。
## 方法论反思:策略优化的正确姿势
### 避免过度优化的陷阱
这次实验给我们的最大教训是:**策略优化必须在足够长的时间跨度和多样化的市场环境中验证**。
**常见的过度优化陷阱:**
1. **时间窗口过短**:只用最近3-5年的数据回测
- 问题:可能错过关键的极端事件(如2008、2011)
- 建议:至少使用10年以上的历史数据
2. **市场环境单一**:只在牛市或只在熊市中测试
- 问题:策略可能只适应特定环境
- 建议:确保测试期包含至少1-2个完整的牛熊周期
3. **参数过度精细**:追求小数点后两位的"最优"参数
- 问题:极可能是拟合噪音而非规律
- 建议:使用整数参数,保持策略简洁
4. **只看绝对收益**:忽略回撤、波动率、交易质量
- 问题:高收益可能伴随无法承受的风险
- 建议:使用风险调整后的指标(Sharpe、Calmar)
### 正确的策略评估框架
**评估一个策略不应只看单一指标,而应该综合考虑:**
| 维度 | 指标 | V1表现 | V3表现 | V4表现 | 最优 |
|------|------|--------|--------|--------|------|
| **收益能力** | 年化收益、累计倍数 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | V1 |
| **风险控制** | 最大回撤、波动率 | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | **V4** |
| **风险调整后收益** | Sharpe、Calmar | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | **V4** |
| **交易质量** | 胜率、盈亏比 | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | **V4** |
| **可执行性** | 交易频率、心理压力 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | V3/V4 |
| **综合评分** | - | 19/25 | 20/25 | **23/25** | **V4** |
**多层次结论**:
**第一层:信号确认机制的权衡(V1 vs V3)**
- **V1优势**:绝对收益最高(60.41倍),简单易执行
- **V3优势**:交易质量更高(胜率47%),夏普比率最优(0.74)
- **选择依据**:追求收益最大化选V1,追求交易质量选V3
**第二层:波动率过滤的跃升(V4 vs V1/V3)**
**V4在关键维度上实现了超越**:
- **最优风险控制**:回撤-51.46%,比V1低4.5个百分点
- **最优Calmar比率**:0.55,超越V1(0.53)和买入持有(0.51)
- **最高胜率**:50%,显著优于V1(36%)和V3(47%)
- **最低波动率**:42.16%,心理压力最小
**V4的代价**:
- 收益略低于V1(52.5倍 vs 60.4倍,差13%)
- 需要监控额外的VIX指标
**第三层:综合最优的选择(推荐V4)**
综合考虑收益、风险、质量、可执行性四个维度,**V4是最均衡的选择**:
- 用13%的收益损失,换来了37%的回撤改善
- 在所有策略中Calmar最高,证明风险调整后收益最优
- 50%的胜率和最低波动率,让策略更容易长期坚持
**最终建议**:
- **首选V4**:追求长期稳健,重视风险控制
- **备选V1**:追求收益最大化,能承受更高回撤
- **进阶V3**:重视交易质量,追求高胜率体验
### 理解比优化更重要
在策略开发中,有一个常被忽视的真理:
> **深刻理解一个简单策略的特性,远比盲目优化一个复杂策略更有价值。**
**理解的价值在于:**
1. **预期管理**:知道策略在什么情况下会失效
- 例如:所有MA200策略在2016年横盘期都会亏损,这是可接受的成本
2. **情绪控制**:当策略表现不佳时,不会恐慌性修改
- 例如:V1在某次卖出后市场继续上涨,这是正常现象,不是策略失效
3. **长期执行**:只有理解了策略逻辑,才能坚持执行10年、20年
- 例如:理解信号确认的权衡后,不会在亏损时怀疑策略设计
4. **合理改进**:知道优化的方向应该是什么
- 例如:理解横盘震荡是弱点后,考虑引入VIX过滤而非继续调整确认天数
## 公开组合:透明化的策略验证
为了让用户能够真实地看到这三个策略版本的历史表现和实时运行状态,我们在策引平台上创建了公开组合。
### 四版本组合链接
| 策略版本 | 公开组合 | 核心特点 |
|----------|----------|----------|
| **V1 单日信号版** | [查看组合](https://www.myinvestpilot.com/portfolios/custom_o8dibpoa) | 信号确认版本中收益最高 |
| **V2 卖出确认版** | [查看组合](https://www.myinvestpilot.com/portfolios/custom_74dwadkc) | 快进慢出的尝试 |
| **V3 双向确认版** | [查看组合](https://www.myinvestpilot.com/portfolios/custom_lbk38ltj) | 双向确认,胜率最高 |
| **V4 VIX过滤版(推荐)** | [查看组合](https://www.myinvestpilot.com/portfolios/custom_it18kt0f) | **综合最优,最低回撤** |
| **买入持有基准** | [查看组合](https://www.myinvestpilot.com/portfolios/custom_ikfbp5o4) | 最高收益但不可执行 |
### 如何使用公开组合
在这些公开组合页面中,你可以:
1. **查看完整的历史回测数据**:包括每一笔交易的详细信息
2. **观察实时运行状态**:看到策略当前的持仓和信号状态
3. **复制策略配置**:直接复制原语配置到你自己的组合中
4. **对比不同版本**:同时打开多个组合页面进行对比
**重要提示**:这些组合仅用于教育和研究目的。在实盘投资前,请务必:
- 充分理解策略的逻辑和风险
- 在纸面交易中验证至少3个月
- 根据自己的风险承受能力调整仓位
## 结论:从信号确认到波动率过滤的完整启示
这次完整的策略对比研究(V1-V4 + 买入持有),给我们带来了层层递进的深刻启示:
### 核心发现总结
#### 关于信号确认机制(V1-V3)
1. **简单的力量**:最简单的V1单日信号版在三个确认版本中表现最佳
2. **确认的代价**:信号确认机制提高了交易质量,但在极端情况下(如2011年欧债危机)可能延误止损时机
3. **时期依赖性陷阱**:V2在2015-2025表现最佳,但在完整的2010-2025周期反而落后——警示我们避免过度优化
4. **双向确认的价值**:V3虽然收益略低,但胜率47%和夏普0.74展现了交易质量的优势
#### 关于波动率过滤(V4)
**最重要的发现**:**V4 VIX过滤版才是真正的综合最优策略**
- **最优Calmar比率**:0.55,超越所有版本包括买入持有(0.51)
- **最低回撤**:-51.46%,比V1低4.5个百分点
- **最高胜率**:50%,唯一达到对半开的策略
- **最低波动率**:42.16%,心理压力最小
**关键洞察**:V4用仅1.14%的收益损失(29.45% vs 28.31%),换来了4.5%的回撤改善和最优的风险调整后收益。
### 投资哲学的升华
**在投资中,没有圣杯策略,只有合适的权衡。**
#### 三个层次的权衡
**第一层:信号确认的权衡(V1 vs V3)**
- 反应速度 vs 信号质量:V1选择速度,V3选择质量
- 绝对收益 vs 交易胜率:V1收益60.41x,V3胜率47.06%
- 简单性 vs 稳定性:V1最简单,V3夏普最高
**第二层:波动率过滤的跃升(V4)**
- 单纯信号确认有局限性(2016年横盘期所有V1-V3都亏损)
- VIX过滤提供了第二道防线(2020年COVID、2022年加息表现优异)
- 综合维度优于单一维度的优化
**第三层:可执行性的终极考量**
- 买入持有:253倍收益 + -81%回撤 = 理论富贵
- V1-V3策略:52-60倍收益 + -56%到-59%回撤 = 大多数人可能放弃
- **V4策略:52.5倍收益 + -51%回撤 = 更多人能够坚持**
### 实战建议:如何选择
#### 推荐方案
**首选:V4 VIX过滤版**
- 适合:追求长期稳健增长,重视风险控制
- 优势:综合最优,Calmar和胜率双高
- 代价:需要监控VIX指标
**备选:V1单日信号版**
- 适合:追求收益最大化,接受略高回撤
- 优势:最简单,收益最高(在V1-V3中)
- 代价:回撤-56%,需要更强心理承受力
**进阶:V3双向确认版**
- 适合:重视交易质量,追求高胜率
- 优势:胜率47%,夏普0.74
- 代价:收益与V1接近但回撤略大
#### 你的选择应该基于
1. **风险承受能力**:能否承受-51%(V4)还是-56%(V1)的回撤?
2. **投资时间跨度**:10年以上的长期投资者更适合V4
3. **心理舒适度**:追求收益最大化还是风险调整后收益最优?
4. **执行信心**:理解了策略逻辑后,能否在最黑暗时刻坚持?
### 最后的建议
如果你从这个案例中只能记住一句话,那就是:
> **策略优化不是追求历史回测的完美数字,而是找到一个你能够理解、接受并长期执行的系统。V4展示了在现有框架内,波动率过滤是最简单且最有效的优化方式。**
#### 在策引系统的帮助下
你可以:
- **透明化验证**:用15.9年完整历史数据验证策略
- **白盒化理解**:通过原语系统理解每一个信号的生成逻辑
- **实时化执行**:用公开组合追踪策略的实时运行状态
- **系统化优化**:基于V4继续探索(如动态VIX阈值、仓位管理等)
#### 真正的财富来源
**不是来自完美的策略,而是来自对合理策略的长期坚持。**
- V4的52.5倍(28.31% CAGR)虽然不如买入持有的253倍,但这是你真正能拿到的收益
- V4的-51%回撤虽然痛苦,但比-81%更可能让你坚持到最后
- **能坚持的策略,才是最好的策略**
当你理解了信号确认的权衡(V1-V3),掌握了波动率过滤的威力(V4),你就拥有了完整的策略优化工具箱。接下来,你可以根据自己的风险偏好,创造V5、V6——结合动态参数、多重市场指标、智能仓位管理等机制,继续这个探索之旅。
这就是量化投资的魅力:永远有新的问题等待探索,永远有新的权衡需要理解。而策引系统,正是你探索这个世界的最佳工具。
================================================================================
调试与优化
================================================================================
--------------------------------------------------------------------------------
故障排除 (troubleshooting.md)
--------------------------------------------------------------------------------
# 策略原语系统故障排除指南
本文档提供了使用策略原语系统时可能遇到的常见问题及其解决方案。通过检查这些常见问题,您可以更快地诊断和修复策略配置中的错误。
## 配置错误
### 1. 引用不存在的组件
**症状**:回测失败,错误消息提示找不到特定ID的组件。
**示例错误**:
```
KeyError: 'Component ID "rsi_indicator" not found in registry'
```
**解决方案**:
- 检查指标和信号ID的拼写与大小写
- 确保先定义组件,然后再引用它们
- 使用相对路径处理策略配置中组件ID引用
### 2. 参数类型不匹配
**症状**:组件初始化失败,通常伴随类型错误消息。
**示例错误**:
```
TypeError: Expected 'period' parameter to be an integer, got string
```
**解决方案**:
- 检查所有数值参数没有被引号包围
- 确保布尔值使用true/false(不带引号)
- 检查数组和对象的格式正确
### 3. 缺少必需参数
**症状**:组件初始化失败,错误提示缺少参数。
**示例错误**:
```
ValueError: Missing required parameter 'comparison' for Comparison signal
```
**解决方案**:
- 查阅每个组件的文档,确保提供所有必需参数
- 检查参数名称是否正确(例如,`period`而不是`periods`)
### 4. 输入数量不匹配
**症状**:信号评估失败,错误消息提示输入数量错误。
**示例错误**:
```
ValueError: Crossover requires exactly 2 inputs, got 1
ValueError: At least 3 inputs required when threshold is not provided
```
**解决方案**:
- 检查每个信号原语所需的输入数量
- 确保每个输入都有有效的引用或列名
- 对于数学运算组件,如需纯数学计算可使用 `return_calculation=true`
- 对于嵌套信号,确保内联常量格式正确:`{"type": "Constant", "value": N}`
### 5. 数学运算模式配置错误
**症状**:数学运算组件返回意外的结果类型或计算错误。
**常见问题和解决方案**:
1. **想要纯数学计算但得到布尔结果**:
```json
// 错误 - 默认为比较模式
{
"type": "Multiply",
"inputs": [{"ref": "indicator1"}, {"ref": "indicator2"}]
}
// 正确 - 使用纯数学模式
{
"type": "Multiply",
"params": {"return_calculation": true},
"inputs": [{"ref": "indicator1"}, {"ref": "indicator2"}]
}
```
2. **多操作数计算失败**:
```json
// 错误 - 比较模式不支持多操作数
{
"type": "Multiply",
"inputs": [{"ref": "a"}, {"ref": "b"}, {"ref": "c"}]
}
// 正确 - 纯数学模式支持多操作数
{
"type": "Multiply",
"params": {"return_calculation": true},
"inputs": [{"ref": "a"}, {"ref": "b"}, {"ref": "c"}]
}
```
3. **内联常量格式错误**:
```json
// 错误 - 不支持的格式
{
"type": "Add",
"inputs": [{"ref": "indicator"}, {"value": 10}]
}
// 正确 - 使用标准内联常量格式
{
"type": "Add",
"params": {"return_calculation": true},
"inputs": [{"ref": "indicator"}, {"type": "Constant", "value": 10}]
}
```
## 数据和信号问题
### 1. 信号不触发
**症状**:回测显示没有交易或交易次数远少于预期。
**可能原因**:
- 条件过于严格
- 使用了错误的信号类型
- 数据预处理问题
**解决方案**:
- 输出中间指标和信号,检查计算值是否符合预期
- 放宽阈值或条件
- 确保使用正确的信号类型(如Crossover而非GreaterThan)
- 检查指标是否正确计算(查看原始值与指标值)
### 2. 信号过于频繁
**症状**:策略产生过多交易,可能导致过度交易和高滑点/手续费。
**可能原因**:
- 条件过于宽松
- 误用状态比较作为信号(如GreaterThan而非Crossover)
- 阈值设置不合理
**解决方案**:
- 加入额外的过滤条件(如趋势过滤)
- 使用Crossover/Crossunder代替GreaterThan/LessThan
- 添加Streak组件要求连续确认
- 调整阈值更极端
### 3. 信号延迟问题
**症状**:交易信号总是在价格已经大幅走势后才触发。
**可能原因**:
- 使用过长周期的指标
- 多层级信号组合导致延迟累加
**解决方案**:
- 减少指标周期(如使用较短的移动平均)
- 简化信号链,减少不必要的组合层级
- 考虑添加预测性指标,如价格动量
### 4. NaN值处理问题
**症状**:策略在初始阶段不产生信号,或出现不一致的行为。
**可能原因**:
- 指标计算初期产生NaN值
- 未正确处理NaN传播
**解决方案**:
- 确保回测期足够长,涵盖指标预热期
- 检查指标原语是否正确处理NaN(如RSI通常用50填充初始NaN)
- 添加明确的NaN检查和处理步骤
## 策略行为异常
### 1. 不符合预期的持仓状态转换
**症状**:策略在不应该买入或卖出时生成信号,或未能在应该交易时生成信号。
**可能原因**:
- 状态机逻辑问题
- 信号时机不准确
- 条件组合逻辑错误
**解决方案**:
- 仔细检查SignalEvaluator中的状态转换逻辑
- 验证买入/卖出条件是否互斥
- 使用日志和信号表分析状态转换
### 2. 回测结果不一致
**症状**:相同配置的多次回测产生显著不同的结果。
**可能原因**:
- 随机性组件
- 数据加载问题
- 精度或浮点比较问题
**解决方案**:
- 确保策略中没有随机元素
- 验证数据源加载一致性
- 在GreaterThan/LessThan中使用epsilon处理浮点比较
### 3. 信号抖动
**症状**:策略在短时间内频繁切换买入/卖出状态。
**可能原因**:
- 使用价格或指标的绝对值比较
- 缺少状态持续性要求
- 条件太接近临界值
**解决方案**:
- 使用交叉事件而非状态比较
- 添加Streak要求确认持续一定时间
- 增加"滞后带"或双阈值(如RSI使用30/70而非单一50值)
## 性能优化问题
### 1. 过度拟合
**症状**:策略在历史回测中表现极佳,但在新数据上表现差。
**可能原因**:
- 参数过度优化
- 策略复杂度过高
- 回测样本选择偏差
**解决方案**:
- 使用更简单的策略
- 减少调整的参数数量
- 采用时间外样本验证
- 测试多个市场环境
### 2. 高回撤
**症状**:策略在某些市场环境下经历显著的资金损失。
**可能原因**:
- 缺少止损机制
- 缺乏适应市场变化的能力
- 仓位规模过大
**解决方案**:
- 添加移动止损原语(如ChandelierExit)
- 使用动态仓位大小(如基于波动性)
- 增加市场环境过滤器(如趋势强度)
### 3. 低收益率
**症状**:策略交易频率合理,但整体收益率不高。
**可能原因**:
- 获利太早
- 止损太近
- 信号质量不高
**解决方案**:
- 使用跟踪止盈
- 优化买入/卖出时机
- 增加额外的信号确认要求
- 测试不同的资金管理策略
## 系统和环境问题
### 1. 回测执行缓慢
**症状**:回测花费异常长的时间。
**可能原因**:
- 配置不当导致的计算冗余
- 大量无用的中间指标计算
- 使用过于复杂的原语组合
**解决方案**:
- 消除未使用的指标计算
- 简化信号链条
- 确保复杂计算不会重复执行
### 2. 内存消耗过高
**症状**:回测过程中内存使用激增,可能导致系统崩溃。
**可能原因**:
- 处理大量股票或超长时间序列
- 输出太多调试信息
- 存储了不必要的中间结果
**解决方案**:
- 减少输出的指标数量
- 限制回测的时间范围或股票数量
- 确保不保存不必要的中间计算结果
## 调试技巧
### 1. 输出关键指标
在策略的"outputs"部分配置中间指标输出:
```json
"outputs": {
"buy_signal": "buy_signal",
"sell_signal": "sell_signal",
"indicators": [
{ "id": "rsi_indicator", "output_name": "rsi" },
{ "id": "is_below_lower", "output_name": "is_oversold" }
]
}
```
### 2. 分解复杂信号
将复杂组合分解为多个中间信号,并输出每个组件:
```json
"signals": [
{ "id": "condition1", "type": "..." },
{ "id": "condition2", "type": "..." },
{ "id": "combined", "type": "And", "inputs": [
{ "ref": "condition1" },
{ "ref": "condition2" }
]}
]
```
### 3. 单元测试技巧
为测试特定组件,创建最小化测试配置:
```json
{
"indicators": [
{
"id": "test_indicator",
"type": "RSI",
"params": { "period": 14, "field": "Close" }
},
{
"id": "threshold",
"type": "Constant",
"params": { "value": 30 }
}
],
"signals": [
{
"id": "test_signal",
"type": "Crossunder",
"params": { "mode": "simple" },
"inputs": [
{ "ref": "test_indicator" },
{ "ref": "threshold" }
]
}
],
"outputs": {
"buy_signal": "test_signal",
"sell_signal": "false_signal",
"indicators": [
{ "id": "test_indicator", "output_name": "indicator" },
{ "id": "test_signal", "output_name": "signal" }
]
}
}
```
### 4. 验证回测数据
使用原始回测数据检查信号生成正确性:
- 检查信号触发的日期和条件
- 验证指标值是否符合预期的阈值穿越
- 确认买入卖出信号的逻辑正确性
## 常见组件错误模式
### 1. RSI使用陷阱
- **误区**:将RSI < 30作为买入信号,而不是RSI下穿30
- **结果**:只要RSI在30以下就持续发出买入信号
- **修正**:使用Crossunder而非LessThan
### 2. 移动平均线交叉问题
- **误区**:误解Crossover的输入顺序
- **结果**:买入卖出信号反转
- **修正**:确保正确的输入顺序(第一个输入应该上穿第二个输入)
### 3. 逻辑运算符混淆
- **误区**:混淆And/Or的语义
- **结果**:生成错误的组合信号
- **修正**:明确理解每个运算符的作用(And要求所有条件满足,Or只需一个满足)
### 4. 信号与状态混淆
- **误区**:使用状态指标作为交易触发
- **结果**:产生过度交易
- **修正**:区分状态指标与触发信号的不同用途
## 兼容性和升级问题
### 1. 版本兼容性
如果系统升级后策略不再工作:
- 检查原语组件名称是否变更
- 验证参数命名是否一致
- 查看输入/输出格式是否变更
### 2. 新原语集成
集成新添加的原语时:
- 确保了解新原语的确切行为和参数
- 开始时使用简单配置测试
- 逐步集成到复杂策略中
### 3. 配置迁移
将策略从旧格式迁移到新格式:
- 创建详细的映射表
- 保留原始配置作为参考
- 分阶段迁移并测试每个阶段
## 寻求帮助
如遇到无法解决的问题:
1. 查阅原语系统文档(本指南)
2. 检查示例策略配置
3. 阅读特定原语的实现代码和测试
4. 与团队其他成员讨论问题
5. 添加日志和调试输出以获取更多信息
--------------------------------------------------------------------------------
高级调试 (advanced/troubleshooting.md)
--------------------------------------------------------------------------------
# 原语组件高级故障排除指南
本文档提供了原语组件系统的高级故障排除技巧,重点介绍策引平台提供的信号分析工具和数据分析方法。通过这些工具,您可以深度分析策略信号,诊断问题并优化策略配置。
## 策引信号分析工具
策引平台提供了强大的在线信号分析功能,让您可以深度分析组合策略的交易信号数据库。
### 访问信号分析工具
1. **在线分析页面**:登录策引平台后,访问 **我的页面 → 我的策略组合 → 分析诊断 → 信号分析**
2. **信号分析手册**:访问 [信号分析查询手册](https://www.myinvestpilot.com/help/signal-analysis/) 获取详细的SQL查询示例
3. **数据库下载**:如果在线分析页面出现404错误,可以直接下载SQLite数据库进行本地分析
### 下载策略信号数据库
当在线分析工具不可用时,您可以直接下载SQLite数据库文件:
```
https://api.myinvestpilot.com/strategy_portfolio/portfolios/signals/[您的组合ID]
```
**使用步骤**:
1. 确保已登录策引平台
2. 将URL中的 `[您的组合ID]` 替换为实际的组合ID(如:`myinvestpilot_us_3_a`)
3. 在浏览器中访问该URL即可下载SQLite数据库文件
**示例**:
```
https://api.myinvestpilot.com/strategy_portfolio/portfolios/signals/myinvestpilot_us_3_a
```
## 信号分析SQL查询手册
以下是策引平台提供的9个专业SQL查询工具,用于全面诊断策略信号的质量和合理性。
### 数据表结构说明
- **主数据表**: `trade_signals` - 包含所有交易信号数据
- **信号类型**:
- `B` (Buy/买入)
- `S` (Sell/卖出)
- `H` (Hold/持有)
- `E` (Empty/空仓)
- **主要字段**: `date`(日期)、`symbol`(股票代码)、`signal`(信号类型)、`close`(收盘价)、`high`(最高价)、`low`(最低价)
### 1. 🏥 信号健康检查
**信号数据质量诊断** - 快速发现数据问题
检查项目:
- 数据完整性(记录数、时间范围、股票数量)
- 信号有效性(是否只包含B/S/H/E)
- 基本统计信息
```sql
-- 信号数据健康检查
WITH health_metrics AS (
SELECT
COUNT(*) as total_records,
COUNT(DISTINCT symbol) as symbol_count,
COUNT(DISTINCT date) as date_count,
MIN(date) as start_date,
MAX(date) as end_date,
COUNT(CASE WHEN signal NOT IN ('B','S','H','E') OR signal IS NULL THEN 1 END) as invalid_signals
FROM trade_signals
)
SELECT
'数据规模' as check_item,
total_records || ' records, ' || symbol_count || ' symbols' as result,
CASE WHEN total_records > 0 THEN '✅ 正常' ELSE '❌ 无数据' END as status
FROM health_metrics
UNION ALL
SELECT
'时间范围',
start_date || ' to ' || end_date || ' (' || date_count || ' days)',
CASE WHEN date_count > 0 THEN '✅ 正常' ELSE '❌ 无数据' END
FROM health_metrics
UNION ALL
SELECT
'信号有效性',
CASE WHEN invalid_signals = 0 THEN 'All signals are valid (B/S/H/E)'
ELSE invalid_signals || ' invalid signals found' END,
CASE WHEN invalid_signals = 0 THEN '✅ 正常' ELSE '❌ 发现无效信号' END
FROM health_metrics
UNION ALL
SELECT
'股票列表',
(SELECT GROUP_CONCAT(DISTINCT symbol) FROM trade_signals),
'📋 详细信息'
FROM health_metrics;
```
### 2. 🔄 信号切换逻辑检查
**信号状态切换逻辑验证** - 检测不符合交易逻辑的信号切换
正常切换逻辑:
- 标准流程: E -> B -> H -> S -> E
- 定投场景: H -> B (继续加仓)
- 必须卖出: H -> E 必须经过 S
异常切换检测:
- ❌ H -> E (跳过卖出直接空仓)
- ❌ B -> S (买入直接卖出)
- ❌ E -> S (空仓时卖出)
- ❌ S -> B (卖出直接买入)
```sql
-- 信号切换逻辑验证
WITH signal_transitions AS (
SELECT
date,
symbol,
signal as current_signal,
LAG(signal) OVER (PARTITION BY symbol ORDER BY date) as prev_signal
FROM trade_signals
),
transition_analysis AS (
SELECT
prev_signal || ' → ' || current_signal as transition,
COUNT(*) as count,
CASE
-- 异常切换
WHEN prev_signal = 'H' AND current_signal = 'E' THEN '❌ 异常: 持有直接空仓(应经过卖出)'
WHEN prev_signal = 'B' AND current_signal = 'S' THEN '❌ 异常: 买入直接卖出'
WHEN prev_signal = 'E' AND current_signal = 'S' THEN '❌ 异常: 空仓时卖出'
WHEN prev_signal = 'S' AND current_signal = 'B' THEN '❌ 异常: 卖出直接买入'
-- 正常切换
WHEN prev_signal = 'E' AND current_signal = 'B' THEN '✅ 正常: 空仓买入'
WHEN prev_signal = 'B' AND current_signal = 'H' THEN '✅ 正常: 买入后持有'
WHEN prev_signal = 'H' AND current_signal = 'S' THEN '✅ 正常: 持有后卖出'
WHEN prev_signal = 'S' AND current_signal = 'E' THEN '✅ 正常: 卖出后空仓'
WHEN prev_signal = 'H' AND current_signal = 'B' THEN '✅ 正常: 定投加仓'
WHEN prev_signal = current_signal THEN '⚪ 无变化: 状态保持'
ELSE '❓ 其他: ' || prev_signal || ' → ' || current_signal
END as logic_check
FROM signal_transitions
WHERE prev_signal IS NOT NULL
GROUP BY prev_signal, current_signal
)
SELECT
transition,
count,
ROUND(count * 100.0 / (SELECT SUM(count) FROM transition_analysis), 2) as percentage,
logic_check
FROM transition_analysis
WHERE count > 0
ORDER BY
CASE WHEN logic_check LIKE '❌%' THEN 1
WHEN logic_check LIKE '❓%' THEN 2
WHEN logic_check LIKE '✅%' THEN 3
ELSE 4 END,
count DESC
LIMIT 50;
```
### 3. 📊 信号分布分析
**策略交易特征分析** - 了解策略的交易风格和活跃度
分析维度:
- 信号分布:各信号类型占比
- 交易活跃度:主动交易 vs 被动持仓
- 策略风格评估
```sql
-- 信号分布和策略特征分析
WITH signal_stats AS (
SELECT
signal,
COUNT(*) as count,
ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM trade_signals), 2) as percentage
FROM trade_signals
GROUP BY signal
),
activity_summary AS (
SELECT
SUM(CASE WHEN signal IN ('B', 'S') THEN count ELSE 0 END) as active_count,
SUM(CASE WHEN signal IN ('H', 'E') THEN count ELSE 0 END) as passive_count,
SUM(count) as total_count
FROM signal_stats
)
SELECT
signal || ' (' ||
CASE
WHEN signal = 'B' THEN 'Buy'
WHEN signal = 'S' THEN 'Sell'
WHEN signal = 'H' THEN 'Hold'
WHEN signal = 'E' THEN 'Empty'
ELSE 'Unknown'
END || ')' as signal_type,
count,
percentage || '%' as percentage_str,
CASE
WHEN signal IN ('B', 'S') THEN '🔥 Active Trading'
WHEN signal IN ('H', 'E') THEN '💤 Passive Holding'
ELSE '❓ Unknown'
END as activity_style
FROM signal_stats
UNION ALL
SELECT
'--- 策略风格评估 ---',
NULL,
ROUND(active_count * 100.0 / total_count, 2) || '% Active, ' ||
ROUND(passive_count * 100.0 / total_count, 2) || '% Passive',
CASE
WHEN active_count * 100.0 / total_count > 10 THEN '🔥 激进型策略'
WHEN active_count * 100.0 / total_count > 2 THEN '⚖️ 平衡型策略'
ELSE '💤 保守型策略'
END
FROM activity_summary
ORDER BY count DESC NULLS LAST;
```
### 4. 📈 波动性分析
**价格波动性风险评估** - 识别高风险资产和杠杆特征
分析指标:
- 日收益率标准差(年化波动率)
- 最大单日涨跌幅
- 波动性排名和风险分级
- 杠杆ETF识别
风险等级:
- 🟢 低风险: 年化波动率 < 15%
- 🟡 中风险: 15% - 30%
- 🔴 高风险: > 30%
```sql
-- 波动性分析查询
WITH daily_returns AS (
SELECT
symbol,
date,
close,
LAG(close) OVER (PARTITION BY symbol ORDER BY date) as prev_close,
CASE
WHEN LAG(close) OVER (PARTITION BY symbol ORDER BY date) IS NOT NULL
THEN (close - LAG(close) OVER (PARTITION BY symbol ORDER BY date)) / LAG(close) OVER (PARTITION BY symbol ORDER BY date)
ELSE NULL
END as daily_return
FROM trade_signals
WHERE close IS NOT NULL AND close > 0
),
volatility_stats AS (
SELECT
symbol,
COUNT(*) as trading_days,
ROUND(AVG(daily_return) * 252 * 100, 2) as annualized_return_pct,
ROUND(SQRT(AVG(daily_return * daily_return) - AVG(daily_return) * AVG(daily_return)) * SQRT(252) * 100, 2) as annualized_volatility_pct,
ROUND(MAX(daily_return) * 100, 2) as max_daily_gain_pct,
ROUND(MIN(daily_return) * 100, 2) as max_daily_loss_pct,
ROUND((MAX(close) - MIN(close)) / MIN(close) * 100, 2) as total_range_pct
FROM daily_returns
WHERE daily_return IS NOT NULL
GROUP BY symbol
HAVING COUNT(*) >= 10 -- 至少10个交易日
)
SELECT
symbol,
trading_days,
annualized_return_pct || '%' as annual_return,
annualized_volatility_pct || '%' as annual_volatility,
max_daily_gain_pct || '%' as max_gain,
max_daily_loss_pct || '%' as max_loss,
total_range_pct || '%' as total_range,
CASE
WHEN annualized_volatility_pct < 15 THEN '🟢 低风险'
WHEN annualized_volatility_pct < 30 THEN '🟡 中风险'
ELSE '🔴 高风险'
END as risk_level,
CASE
WHEN annualized_volatility_pct > 50 OR ABS(max_daily_gain_pct) > 15 OR ABS(max_daily_loss_pct) > 15
THEN '⚠️ 疑似杠杆ETF'
ELSE '📊 普通资产'
END as leverage_indicator
FROM volatility_stats
ORDER BY annualized_volatility_pct DESC;
```
### 5. 🎯 信号有效性分析
**买卖信号成功率评估** - 验证信号的实际预测能力
分析维度:
- 短期成功率(5日后价格变化)
- 中期成功率(20日后价格变化)
- 平均收益率和风险收益比
- 信号可靠性评级
```sql
-- 分析买卖信号的有效性
WITH signal_performance AS (
SELECT
date,
symbol,
signal,
close as signal_price,
LEAD(close, 5) OVER (PARTITION BY symbol ORDER BY date) as price_5d_later,
LEAD(close, 20) OVER (PARTITION BY symbol ORDER BY date) as price_20d_later
FROM trade_signals
WHERE signal IN ('B', 'S')
),
effectiveness_stats AS (
SELECT
signal,
COUNT(*) as total_signals,
-- 5天后的成功率
COUNT(CASE
WHEN signal = 'B' AND price_5d_later > signal_price THEN 1
WHEN signal = 'S' AND price_5d_later < signal_price THEN 1
END) as successful_5d,
-- 20天后的成功率
COUNT(CASE
WHEN signal = 'B' AND price_20d_later > signal_price THEN 1
WHEN signal = 'S' AND price_20d_later < signal_price THEN 1
END) as successful_20d,
-- 平均收益率
AVG(CASE
WHEN signal = 'B' THEN (COALESCE(price_5d_later, signal_price) - signal_price) / signal_price * 100
WHEN signal = 'S' THEN (signal_price - COALESCE(price_5d_later, signal_price)) / signal_price * 100
END) as avg_return_5d
FROM signal_performance
GROUP BY signal
)
SELECT
CASE
WHEN signal = 'B' THEN '🟢 买入信号'
WHEN signal = 'S' THEN '🔴 卖出信号'
END as signal_type,
total_signals || ' 次' as signal_count,
ROUND(successful_5d * 100.0 / total_signals, 1) || '%' as success_rate_5d,
ROUND(successful_20d * 100.0 / total_signals, 1) || '%' as success_rate_20d,
ROUND(avg_return_5d, 2) || '%' as avg_return_5d,
CASE
WHEN successful_5d * 100.0 / total_signals > 70 THEN '🌟 优秀'
WHEN successful_5d * 100.0 / total_signals > 55 THEN '✅ 良好'
WHEN successful_5d * 100.0 / total_signals > 45 THEN '⚠️ 一般'
ELSE '❌ 较差'
END as reliability_rating
FROM effectiveness_stats
WHERE total_signals > 0;
```
### 6. ⏰ 交易时机分析
**策略交易节奏特征** - 了解策略的交易频率和持仓周期
分析维度:
- 信号间隔时间分布
- 持仓周期统计
- 交易活跃度评估
- 市场时机把握能力
```sql
-- 分析策略的时机特征
WITH signal_gaps AS (
SELECT
symbol,
date,
signal,
LAG(date) OVER (PARTITION BY symbol ORDER BY date) as prev_date,
LAG(signal) OVER (PARTITION BY symbol ORDER BY date) as prev_signal,
julianday(date) - julianday(LAG(date) OVER (PARTITION BY symbol ORDER BY date)) as days_gap
FROM trade_signals
WHERE signal IN ('B', 'S')
),
frequency_analysis AS (
SELECT
signal,
COUNT(*) as signal_count,
ROUND(AVG(days_gap), 1) as avg_gap_days,
MIN(days_gap) as min_gap_days,
MAX(days_gap) as max_gap_days,
COUNT(CASE WHEN days_gap < 7 THEN 1 END) as weekly_signals,
COUNT(CASE WHEN days_gap BETWEEN 7 AND 30 THEN 1 END) as monthly_signals,
COUNT(CASE WHEN days_gap > 30 THEN 1 END) as quarterly_signals
FROM signal_gaps
WHERE days_gap IS NOT NULL
GROUP BY signal
)
SELECT
CASE
WHEN signal = 'B' THEN '🟢 买入信号'
WHEN signal = 'S' THEN '🔴 卖出信号'
END as signal_type,
signal_count || ' 次' as total_count,
avg_gap_days || ' 天' as avg_interval,
min_gap_days || '-' || max_gap_days || ' 天' as gap_range,
weekly_signals || '/' || monthly_signals || '/' || quarterly_signals as frequency_distribution,
CASE
WHEN avg_gap_days < 14 THEN '🔥 高频交易 (< 2周)'
WHEN avg_gap_days < 60 THEN '⚖️ 中频交易 (2周-2月)'
ELSE '💤 低频交易 (> 2月)'
END as trading_style
FROM frequency_analysis
UNION ALL
SELECT
'📊 整体特征',
(SELECT COUNT(*) FROM signal_gaps WHERE signal IN ('B', 'S') AND days_gap IS NOT NULL) || ' 次交易',
ROUND((SELECT AVG(days_gap) FROM signal_gaps WHERE days_gap IS NOT NULL), 1) || ' 天',
'平均交易间隔',
'周/月/季度分布',
CASE
WHEN (SELECT AVG(days_gap) FROM signal_gaps WHERE days_gap IS NOT NULL) < 21 THEN '🔥 活跃策略'
WHEN (SELECT AVG(days_gap) FROM signal_gaps WHERE days_gap IS NOT NULL) < 90 THEN '⚖️ 平衡策略'
ELSE '💤 稳健策略'
END;
```
### 7. 🌍 市场适应性分析
**策略在不同市场环境下的表现** - 评估策略的适应性和局限性
分析维度:
- 趋势市场 vs 震荡市场表现
- 高波动 vs 低波动环境适应性
- 信号在不同市场条件下的分布
- 策略适用场景识别
```sql
-- 分析策略在不同市场环境下的表现
WITH market_conditions AS (
SELECT
date,
symbol,
close,
signal,
high,
low,
-- 计算20日移动平均来判断趋势
AVG(close) OVER (
PARTITION BY symbol
ORDER BY date
ROWS BETWEEN 19 PRECEDING AND CURRENT ROW
) as ma20,
-- 计算20日波动率
(MAX(high) OVER (
PARTITION BY symbol
ORDER BY date
ROWS BETWEEN 19 PRECEDING AND CURRENT ROW
) - MIN(low) OVER (
PARTITION BY symbol
ORDER BY date
ROWS BETWEEN 19 PRECEDING AND CURRENT ROW
)) / close as volatility_20d
FROM trade_signals
WHERE close IS NOT NULL AND high IS NOT NULL AND low IS NOT NULL
),
classified_signals AS (
SELECT
signal,
CASE
WHEN close > ma20 * 1.02 THEN '📈 上涨趋势'
WHEN close > ma20 * 0.98 THEN '📊 横盘整理'
ELSE '📉 下跌趋势'
END as market_trend,
CASE
WHEN volatility_20d > 0.15 THEN '🌊 高波动'
WHEN volatility_20d > 0.08 THEN '〰️ 中波动'
ELSE '📏 低波动'
END as volatility_level
FROM market_conditions
WHERE signal IN ('B', 'S') AND ma20 IS NOT NULL AND volatility_20d IS NOT NULL
),
adaptation_stats AS (
SELECT
signal,
market_trend,
volatility_level,
COUNT(*) as signal_count,
ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER (PARTITION BY signal), 1) as percentage
FROM classified_signals
GROUP BY signal, market_trend, volatility_level
)
SELECT
CASE
WHEN signal = 'B' THEN '🟢 买入信号'
WHEN signal = 'S' THEN '🔴 卖出信号'
END as signal_type,
market_trend,
volatility_level,
signal_count || ' 次' as count,
percentage || '%' as proportion,
CASE
WHEN signal = 'B' AND market_trend = '📈 上涨趋势' THEN '✅ 顺势而为'
WHEN signal = 'S' AND market_trend = '📉 下跌趋势' THEN '✅ 及时止损'
WHEN signal = 'B' AND market_trend = '📉 下跌趋势' THEN '⚠️ 抄底风险'
WHEN signal = 'S' AND market_trend = '📈 上涨趋势' THEN '⚠️ 过早获利'
ELSE '📊 中性策略'
END as strategy_assessment
FROM adaptation_stats
WHERE signal_count > 0
ORDER BY signal, signal_count DESC;
```
### 8. ⚠️ 风险信号识别
**策略潜在风险警示** - 识别可能影响策略表现的风险因素
风险维度:
- 连续错误信号
- 极端市场条件下的表现
- 信号密度过高警告
- 长期空仓风险
```sql
-- 识别策略中的潜在风险信号
WITH risk_analysis AS (
SELECT
symbol,
date,
signal,
close,
LAG(signal, 1) OVER (PARTITION BY symbol ORDER BY date) as prev_signal_1,
LAG(signal, 2) OVER (PARTITION BY symbol ORDER BY date) as prev_signal_2,
LAG(close, 1) OVER (PARTITION BY symbol ORDER BY date) as prev_close,
LEAD(close, 5) OVER (PARTITION BY symbol ORDER BY date) as future_close,
COUNT(CASE WHEN signal IN ('B', 'S') THEN 1 END) OVER (
PARTITION BY symbol
ORDER BY date
ROWS BETWEEN 29 PRECEDING AND CURRENT ROW
) as signals_30d
FROM trade_signals
),
risk_patterns AS (
SELECT
'🔄 频繁交易风险' as risk_type,
COUNT(*) as occurrence_count,
CASE
WHEN COUNT(*) > 10 THEN '❌ 高风险'
WHEN COUNT(*) > 5 THEN '⚠️ 中风险'
ELSE '✅ 低风险'
END as risk_level,
'30天内交易超过' || MAX(signals_30d) || '次' as description
FROM risk_analysis
WHERE signals_30d > 8
UNION ALL
SELECT
'📉 连续错误信号' as risk_type,
COUNT(*) as occurrence_count,
CASE
WHEN COUNT(*) > 3 THEN '❌ 高风险'
WHEN COUNT(*) > 1 THEN '⚠️ 中风险'
ELSE '✅ 低风险'
END as risk_level,
'发现' || COUNT(*) || '次买入后价格下跌' as description
FROM risk_analysis
WHERE signal = 'B' AND future_close < close * 0.95
UNION ALL
SELECT
'🔀 信号混乱' as risk_type,
COUNT(*) as occurrence_count,
CASE
WHEN COUNT(*) > 5 THEN '❌ 高风险'
WHEN COUNT(*) > 2 THEN '⚠️ 中风险'
ELSE '✅ 低风险'
END as risk_level,
'发现' || COUNT(*) || '次B-S-B短期切换' as description
FROM risk_analysis
WHERE signal = 'B' AND prev_signal_1 = 'S' AND prev_signal_2 = 'B'
UNION ALL
SELECT
'💤 长期空仓' as risk_type,
COUNT(*) as occurrence_count,
CASE
WHEN COALESCE(MAX(streak_days), 0) > 200 THEN '⚠️ 中风险'
WHEN COALESCE(MAX(streak_days), 0) > 100 THEN '📊 正常'
WHEN COALESCE(MAX(streak_days), 0) > 30 THEN '✅ 活跃'
ELSE '🚀 极活跃'
END as risk_level,
CASE
WHEN COUNT(*) = 0 THEN '未发现长期空仓'
ELSE '发现' || COUNT(*) || '次空仓期,最长' || COALESCE(MAX(streak_days), 0) || '天'
END as description
FROM (
WITH signal_groups AS (
SELECT
symbol,
date,
signal,
(ROW_NUMBER() OVER (PARTITION BY symbol ORDER BY date) -
ROW_NUMBER() OVER (PARTITION BY symbol, signal ORDER BY date)) as grp
FROM risk_analysis
WHERE signal IS NOT NULL
),
empty_streaks AS (
SELECT
symbol,
signal,
COUNT(*) as streak_days,
MIN(date) as start_date,
MAX(date) as end_date
FROM signal_groups
WHERE signal = 'E'
GROUP BY symbol, signal, grp
HAVING COUNT(*) > 30
)
SELECT
symbol,
streak_days,
start_date,
end_date
FROM empty_streaks
) long_empty_periods
)
SELECT
risk_type,
occurrence_count,
risk_level,
description
FROM risk_patterns
WHERE occurrence_count > 0
ORDER BY
CASE
WHEN risk_level = '❌ 高风险' THEN 1
WHEN risk_level = '⚠️ 中风险' THEN 2
ELSE 3
END,
occurrence_count DESC;
```
### 9. 🔍 自定义分析
**灵活的自定义查询** - 根据需要自由查询数据
使用方法:
- 在SQL编辑器中输入自定义查询
- 可查询任意时间段、股票、条件
常用查询示例:
- 特定日期: WHERE date = '2022-01-01'
- 特定股票: WHERE symbol = 'AAPL'
- 信号变化: 使用LAG()函数分析转换
```sql
-- 自定义查询模板 - 可根据需要修改
SELECT
date,
symbol,
signal
FROM trade_signals
ORDER BY date DESC
LIMIT 100;
```
## 实际案例分析
### 案例1:策略信号异常诊断
**问题现象**:策略频繁买入卖出,收益不佳
**分析步骤**:
1. **运行信号健康检查**,确认数据完整性
2. **运行信号切换逻辑检查**,发现异常切换模式:
```
B → S: 45次 (❌ 异常: 买入直接卖出)
```
3. **运行信号分布分析**,发现交易过于频繁:
```
策略风格评估: 35% Active, 65% Passive (🔥 激进型策略)
```
**解决方案**:调整策略参数,增加持有期限制,减少频繁交易。
### 案例2:策略长期空仓问题
**问题现象**:策略长期处于空仓状态,错失市场机会
**分析步骤**:
1. **运行最近信号状态查询**,确认当前全部为空仓信号
2. **运行信号分布分析**,发现:
```
E (Empty): 2847次, 89.5% (💤 Passive Holding)
B (Buy): 123次, 3.9% (🔥 Active Trading)
```
3. **分析指标数值**,发现买入条件过于严格
**解决方案**:放宽买入条件,调整技术指标参数。
## 故障排除最佳实践
### 1. 系统性分析流程
1. **数据完整性检查** → 运行信号健康检查
2. **逻辑一致性验证** → 运行信号切换逻辑检查
3. **策略特征分析** → 运行信号分布分析
4. **近期状态确认** → 运行最近信号状态查询
5. **深度诊断** → 根据具体问题运行专项分析
### 2. 常见问题及解决方案
| 问题类型 | 症状 | 分析方法 | 解决方案 |
|---------|------|----------|----------|
| 过度交易 | 买卖信号频繁切换 | 信号切换逻辑检查 | 增加信号确认机制 |
| 长期空仓 | E信号占比过高 | 信号分布分析 | 放宽买入条件 |
| 逻辑错误 | 异常信号切换 | 信号切换逻辑检查 | 修正策略逻辑 |
| 数据异常 | 信号数值异常 | 指标数值分析 | 检查数据源和计算 |
### 3. 性能优化建议
- **定期运行健康检查**:确保策略数据质量
- **监控交易频率**:避免过度交易影响收益
- **验证逻辑一致性**:确保信号切换符合预期
- **分析历史表现**:通过数据驱动优化策略
## 使用技巧
### SQL查询优化
- **时间范围限制**:使用 `WHERE date >= '2024-01-01'` 限制查询范围
- **符号筛选**:使用 `WHERE symbol = 'AAPL'` 分析特定标的
- **结果排序**:使用 `ORDER BY date DESC` 查看最新数据
- **限制记录数**:使用 `LIMIT 100` 控制返回结果数量
### 数据导出
- **CSV格式**:在Datasette中可以导出CSV格式数据
- **JSON格式**:支持导出JSON格式进行程序化分析
- **图表可视化**:结合数据可视化工具分析趋势
## 相关资源
**官方工具**:
- [信号分析查询手册](https://www.myinvestpilot.com/help/signal-analysis/) - 完整的SQL查询示例
- 策引平台 - 我的策略组合 - 分析诊断 - 信号分析
**相关文档**:
- [原语架构概述](/docs/primitives/architecture)
- [策略组合分析](/docs/guides/portfolio-analysis)
- [市场指标详解](/docs/primitives/advanced/market-indicators)
- [策略优化指南](/docs/primitives/advanced/optimization)
---
**免责声明**:本指南提供的所有分析工具和方法仅用于策略研究和学习,不构成任何投资建议。策略分析结果不代表未来表现,用户应独立做出投资决策并承担相应风险。
--------------------------------------------------------------------------------
策略优化 (advanced/optimization.md)
--------------------------------------------------------------------------------
# 原语策略优化实战指南:从案例到方法论
## 引言
优化交易策略不仅仅是调整几个参数那么简单,它是一门平衡艺术,需要在收益和风险之间找到适合自己的平衡点。本指南将通过一个实际的市场过滤策略优化案例,带您一步步了解如何优化原语策略,使其更好地符合您的风险偏好。
不同于理论指导,我们将从一个真实的策略配置开始,分析其表现,识别问题,然后逐步优化,最终达到更好的风险收益平衡。通过这个过程,您将学习到实用的原语策略优化技巧和方法论。
## 案例背景:市场过滤策略
我们要优化的是一个基于VIX指数(波动率指数)过滤的市场择时策略。这个策略的设计思路源于一个重要的市场观察:市场波动性与风险和回报之间存在密切关系。
### 策略设计思路
**1. 市场环境判断的重要性**
投资市场并非总是适合参与。历史数据表明,在极端波动的市场环境下(如2008年金融危机、2020年疫情暴发初期),盲目入市往往会导致严重亏损。因此,一个有效的策略应该首先判断当前市场环境是否适合参与。
**2. VIX指数作为市场情绪晴雨表**
VIX指数(芝加哥期权交易所波动率指数)被广泛认为是市场恐慌情绪的晴雨表,常被称为"恐慌指数"。它测量的是市场对未来30天S&P 500指数波动性的预期:
- 当VIX处于低位(通常低于20)时,表明市场相对平静,投资者情绪乐观
- 当VIX处于中等水平(20-30)时,表明市场存在一定不确定性
- 当VIX处于高位(大于30)时,表明市场恐慌情绪浓厚
- 当VIX极度飙升(大于40)时,通常意味着市场恐慌和剧烈抛售
研究表明,在VIX极高的环境下入市,虽然可能抓住市场底部,但风险也极大;而在VIX从高位回落时入市,往往能够在风险可控的情况下获得不错的回报。
**3. 百分位排名的应用**
原始VIX数值在不同时期的基准不同,例如2008年金融危机期间,VIX达到80以上被视为极端;而在2010年代的低波动环境中,VIX达到30就可能被视为较高。因此,我们使用百分位排名来标准化VIX指标,使其在不同市场周期中具有可比性。
**4. 结合价格技术指标**
仅依靠市场环境判断是不够的,还需要个股层面的技术确认。策略采用了两个经典的技术指标组合:
- **移动平均线**:用于确认价格趋势,当价格位于均线上方时,被视为上升趋势
- **吊灯止损(Chandelier Exit)**:基于ATR(平均真实波幅)的动态止损线,能够根据市场波动性自动调整止损位置
这种组合既考虑了趋势方向(移动平均线),又考虑了波动性(ATR止损),形成了一个相对全面的技术分析框架。
**5. 逻辑组合的艺术**
策略的核心在于如何组合市场环境判断和技术指标。采用"与"(And)逻辑要求两者同时满足,这提高了信号质量但减少了交易频率;采用"或"(Or)逻辑则相反。本策略在市场条件判断中采用了"或"逻辑(市场波动低或波动下降),在买入条件中采用了"与"逻辑(市场条件好且技术指标良好),这种组合旨在平衡信号质量和交易机会。
通过这种多层次的判断机制,策略旨在实现"在合适的市场环境下,买入技术面良好的资产"这一核心目标,从而在控制风险的同时,获取合理的市场回报。
### 初始策略配置
以下是我们要优化的策略:
```json
{
"market_indicators": {
"indicators": [
{
"code": "VIX"
}
],
"transformers": [
{
"name": "vix_raw",
"type": "IdentityTransformer",
"params": {
"indicator": "VIX",
"field": "Close"
}
},
{
"name": "vix_percentile",
"type": "PercentileRankTransformer",
"params": {
"indicator": "VIX",
"lookback": 252,
"field": "Close"
}
},
{
"name": "vix_ma",
"type": "MovingAverageTransformer",
"params": {
"indicator": "VIX",
"window": 20,
"method": "simple",
"field": "Close"
}
}
]
},
"trade_strategy": {
"indicators": [
{
"id": "ma_indicator",
"type": "SMA",
"params": {
"period": 250,
"column": "Close"
}
},
{
"id": "atr_indicator",
"type": "ATR",
"params": {
"period": 60
}
},
{
"id": "chandelier_exit_indicator",
"type": "ChandelierExit",
"params": {
"period": 60,
"multiplier": 4
}
},
{
"id": "constant_75",
"type": "Constant",
"params": {
"value": 75
}
}
],
"signals": [
{
"id": "price_gt_ma",
"type": "GreaterThan",
"inputs": [
{
"column": "Close"
},
{
"ref": "ma_indicator"
}
]
},
{
"id": "price_gt_ce",
"type": "GreaterThan",
"inputs": [
{
"column": "Close"
},
{
"ref": "chandelier_exit_indicator"
}
]
},
{
"id": "market_volatility_low",
"type": "LessThan",
"epsilon": 0.5,
"inputs": [
{
"market": "VIX",
"transformer": "vix_percentile"
},
{
"ref": "constant_75"
}
]
},
{
"id": "market_volatility_declining",
"type": "LessThan",
"inputs": [
{
"market": "VIX",
"transformer": "vix_raw"
},
{
"market": "VIX",
"transformer": "vix_ma"
}
]
},
{
"id": "price_lt_ma",
"type": "LessThan",
"inputs": [
{
"ref": "ma_indicator"
},
{
"column": "Close"
}
]
},
{
"id": "price_lt_ce",
"type": "LessThan",
"inputs": [
{
"ref": "chandelier_exit_indicator"
},
{
"column": "Close"
}
]
},
{
"id": "market_condition_good",
"type": "Or",
"inputs": [
{
"ref": "market_volatility_low"
},
{
"ref": "market_volatility_declining"
}
]
},
{
"id": "price_conditions",
"type": "And",
"inputs": [
{
"ref": "price_gt_ma"
},
{
"ref": "price_gt_ce"
}
]
},
{
"id": "technical_buy_conditions",
"type": "And",
"inputs": [
{
"ref": "price_conditions"
},
{
"ref": "price_gt_ma"
}
]
},
{
"id": "buy_signal_condition",
"type": "And",
"inputs": [
{
"ref": "technical_buy_conditions"
},
{
"ref": "market_condition_good"
}
]
},
{
"id": "price_conditions_sell",
"type": "And",
"inputs": [
{
"ref": "price_lt_ma"
},
{
"ref": "price_lt_ce"
}
]
},
{
"id": "sell_signal_condition",
"type": "And",
"inputs": [
{
"ref": "price_conditions_sell"
},
{
"type": "Not",
"inputs": [
{
"ref": "market_condition_good"
}
]
}
]
}
],
"outputs": {
"buy_signal": "buy_signal_condition",
"sell_signal": "sell_signal_condition",
"indicators": [
{
"id": "ma_indicator",
"output_name": "ma"
},
{
"id": "atr_indicator",
"output_name": "atr"
},
{
"id": "chandelier_exit_indicator",
"output_name": "chandelier_stop"
},
{
"id": "market_volatility_low",
"output_name": "vix_percentile_low"
},
{
"id": "market_volatility_declining",
"output_name": "vix_declining"
},
{
"id": "market_condition_good",
"output_name": "market_ok"
},
{
"id": "price_conditions",
"output_name": "price_conditions"
},
{
"id": "technical_buy_conditions",
"output_name": "tech_buy"
},
{
"id": "buy_signal_condition",
"output_name": "buy_condition"
},
{
"id": "sell_signal_condition",
"output_name": "sell_condition"
}
],
"market_indicators": [
{
"market": "VIX",
"transformer": "vix_raw",
"output_name": "vix_raw"
},
{
"market": "VIX",
"transformer": "vix_percentile",
"output_name": "vix_percentile"
},
{
"market": "VIX",
"transformer": "vix_ma",
"output_name": "vix_ma"
}
]
}
}
}
```
### 初始策略分析
运行初始策略后,我们得到以下关键指标:
| 指标 | 初始策略 | 等权重买入持有 |
|------|----------|----------------|
| 总回报 | 108.32% | 148.02% |
| 年化收益率 (CAGR) | 10.47% | 13.12% |
| 最大回撤 | -25.98% | -33.46% |
| 夏普比率 | 0.61 | 0.67 |
分析这些数据,我们可以发现:
1. **收益率不足**:策略的年化收益率(10.47%)低于等权重买入持有(13.12%)
2. **风险控制良好**:最大回撤(-25.98%)明显低于等权重买入持有(-33.46%)
3. **风险调整后收益一般**:夏普比率(0.61)略低于等权重买入持有(0.67)
这表明策略在风险控制方面表现良好,但在收益率方面有提升空间。我们的优化目标是:在保持良好风险控制的同时,提高策略的收益率。
## 优化过程:逐步改进
接下来,我们将通过一系列有针对性的调整,逐步优化这个策略。每一步调整都会解释调整的理由、具体的参数变化,以及预期的效果。
### 第一步:调整VIX百分位阈值
**问题分析**:
初始策略使用VIX百分位80作为阈值,这意味着只有当VIX处于历史80%以下的水平(市场相对平静)时,策略才会考虑入场。通过分析交易记录,我们发现:
1. 在2019年和2021年牛市期间,策略多次因VIX百分位超过80而错过了重要的上涨机会
2. 特别是在市场从调整中恢复的初期阶段,VIX往往仍处于相对高位,但这恰恰是入场的良好时机
3. 数据显示,VIX百分位在70-80区间的市场环境下,风险回报比仍然相当有吸引力
以2021年3月为例,当时市场从短暂调整中恢复,但VIX百分位仍在75-80区间波动,策略因此错过了一波重要上涨。
**调整方案**:
将VIX百分位阈值从80降低到75,使市场条件判断更加灵活,但仍保持一定的风险控制。这一调整基于以下数据分析:
| VIX百分位区间 | 年化收益率 | 最大回撤 | 夏普比率 | 交易次数 |
|--------------|-----------|---------|---------|---------|
| 低于70 | 12.3% | -31.2% | 0.65 | 42 |
| 低于75 | 11.8% | -28.5% | 0.63 | 36 |
| 低于80 (原始) | 10.5% | -26.0% | 0.61 | 28 |
| 低于85 | 9.2% | -23.8% | 0.58 | 22 |
从上表可以看出,将阈值从80降低到75可以在保持相似风险水平的同时,提高收益率并增加交易机会。
**具体修改**:
```json
{
"id": "constant_80",
"type": "Constant",
"params": {
"value": 80
}
}
```
修改为:
```json
{
"id": "constant_75",
"type": "Constant",
"params": {
"value": 75
}
}
```
同时,需要更新引用:
```json
{
"market_volatility_low",
"type": "LessThan",
"inputs": [
{ "market": "VIX", "transformer": "vix_percentile" },
{ "ref": "constant_80" }
]
}
```
修改为:
```json
{
"market_volatility_low",
"type": "LessThan",
"inputs": [
{ "market": "VIX", "transformer": "vix_percentile" },
{ "ref": "constant_75" }
]
}
```
**调整理由**:
- VIX百分位80是一个相对保守的阈值,只有在市场极度平静时才会触发
- 降低到75仍能过滤极端市场环境,但允许在更多相对平静的市场环境中参与
- 这一调整应该能增加交易频率,提高策略的参与度,从而有可能提高收益率
### 第二步:改进买入条件
**问题分析**:
初始策略的买入条件直接使用价格条件和市场条件的组合,缺乏中间层的技术确认,可能导致信号质量不高。通过分析交易记录,我们发现以下问题:
1. **假突破问题**:在2020年和2022年的震荡市场中,策略多次在价格短暂突破均线后立即买入,但随后价格又迅速回落,导致不必要的交易和亏损
2. **信号冗余**:当前的买入条件中,`price_gt_ma`(价格高于均线)已经包含在`price_conditions`中,但在最终的买入条件中没有得到充分利用
3. **缺乏技术确认**:仅依靠价格与均线和吊灯止损的关系,缺乏对趋势强度的确认
以2022年4月为例,策略在价格刚刚突破均线时买入,但由于缺乏动量确认,这些买入信号大多在市场继续下跌时导致了亏损。
**调整方案**:
添加技术买入条件作为中间层,确保只在技术面和市场条件都良好的情况下买入。具体来说:
1. 创建一个新的`technical_buy_conditions`节点,组合价格条件和价格动量确认
2. 修改最终的买入条件,要求同时满足技术买入条件和市场条件
这种分层结构不仅提高了信号质量,还使策略逻辑更加清晰,便于后续优化。我们对不同技术确认方法的回测结果如下:
| 技术确认方法 | 年化收益率 | 最大回撤 | 夏普比率 | 胜率 |
|------------|-----------|---------|---------|------|
| 无确认(原始) | 10.47% | -25.98% | 0.61 | 58.2%|
| 价格大于均线确认 | 11.05% | -26.32% | 0.63 | 61.5%|
| 均线斜率确认 | 10.89% | -25.76% | 0.62 | 63.8%|
| 价格大于均线+动量 | 11.23% | -26.85% | 0.64 | 65.2%|
从上表可以看出,添加价格大于均线的额外确认可以提高收益率和胜率,虽然会略微增加最大回撤,但风险调整后的收益(夏普比率)有所提高。
**具体修改**:
```json
{
"id": "buy_signal_condition",
"type": "And",
"inputs": [
{ "ref": "price_conditions" },
{ "ref": "market_condition_good" }
]
}
```
修改为:
```json
{
"id": "technical_buy_conditions",
"type": "And",
"inputs": [
{ "ref": "price_conditions" },
{ "ref": "price_gt_ma" }
]
},
{
"id": "buy_signal_condition",
"type": "And",
"inputs": [
{ "ref": "technical_buy_conditions" },
{ "ref": "market_condition_good" }
]
}
```
同时,需要更新输出指标列表:
```json
"indicators": [
{ "id": "ma_indicator", "output_name": "ma" },
{ "id": "atr_indicator", "output_name": "atr" },
{ "id": "chandelier_exit_indicator", "output_name": "chandelier_stop" },
{ "id": "market_volatility_low", "output_name": "vix_percentile_low" },
{ "id": "market_volatility_declining", "output_name": "vix_declining" },
{ "id": "market_condition_good", "output_name": "market_ok" },
{ "id": "price_conditions", "output_name": "price_conditions" },
{ "id": "technical_buy_conditions", "output_name": "tech_buy" },
{ "id": "buy_signal_condition", "output_name": "buy_condition" },
{ "id": "sell_signal_condition", "output_name": "sell_condition" }
]
```
**调整理由**:
- 添加技术买入条件作为中间层,可以提高买入信号的质量
- 通过要求价格不仅满足基本条件,还要强调动量确认,减少错误交易
- 这一调整应该能提高策略的稳定性,减少不必要的交易
### 第三步:改进卖出条件
**问题分析**:
初始策略的卖出条件是"当价格条件恶化且不满足买入条件时卖出",这可能导致过早退出趋势,因为买入条件包含了市场条件。通过分析交易记录,我们发现以下问题:
1. **过早退出趋势**:在2019年和2021年的强势市场中,策略多次因短期市场波动而过早卖出,错过了后续的上涨
2. **逻辑结构不合理**:当前的卖出条件直接否定整个买入条件,这意味着只要市场条件稍有变化,即使价格趋势仍然良好,也会触发卖出
3. **持仓时间短**:数据显示,策略的平均持仓时间仅为23个交易日,明显短于理想的趋势跟踪周期
以2021年10月为例,当时VIX指数短暂上升超过阈值,导致市场条件判断从"好"变为"不好",策略立即卖出所有持仓,但随后市场继续上涨,策略错过了约8%的收益。
**调整方案**:
修改卖出条件,使其更加灵活,只有当价格条件恶化且市场条件恶化时才卖出,而不是直接否定整个买入条件。具体来说:
1. 保留价格条件恶化(价格低于均线和吊灯止损)作为卖出的必要条件
2. 将"不满足买入条件"修改为"市场条件恶化",使卖出决策更加聚焦于市场环境
3. 这样,即使市场条件暂时恶化,只要价格趋势仍然良好,策略就会继续持有
我们对不同卖出条件的回测结果如下:
| 卖出条件 | 年化收益率 | 最大回撤 | 夏普比率 | 平均持仓天数 |
|---------|-----------|---------|---------|------------|
| 原始条件 | 10.47% | -25.98% | 0.61 | 23天 |
| 仅价格条件 | 12.35% | -29.87% | 0.63 | 42天 |
| 价格+市场条件 | 11.28% | -27.15% | 0.62 | 35天 |
从上表可以看出,修改卖出条件可以延长持仓时间,提高收益率,虽然会略微增加最大回撤,但整体风险收益比仍然合理。我们选择"价格+市场条件"作为最终方案,因为它在收益和风险之间取得了较好的平衡。
**具体修改**:
```json
{
"id": "sell_signal_condition",
"type": "And",
"inputs": [
{ "ref": "price_conditions_sell" },
{
"type": "Not",
"inputs": [{ "ref": "buy_signal_condition" }]
}
]
}
```
修改为:
```json
{
"id": "sell_signal_condition",
"type": "And",
"inputs": [
{ "ref": "price_conditions_sell" },
{
"type": "Not",
"inputs": [{ "ref": "market_condition_good" }]
}
]
}
```
**调整理由**:
- 原始策略在不满足买入条件时就卖出,可能导致过早退出趋势
- 新的卖出条件要求市场条件恶化且价格条件恶化时才卖出
- 这一调整应该能延长持仓时间,更好地捕捉趋势,减少不必要的交易成本
### 第四步:调整资金分配
**问题分析**:
初始策略的资金分配是每个资产33%,这是一个相对保守的设置,可能限制了策略的收益潜力。通过分析策略表现,我们发现以下问题:
1. **收益贡献不平衡**:在2019-2022年的回测期间,QQQ的表现明显优于SPY和IWM,但三者获得了相同的资金分配
2. **资金利用率不足**:由于策略设计,三个ETF很少同时满足买入条件,导致资金经常闲置,平均资金利用率仅为68%
3. **风险分散过度**:虽然分散投资有助于降低风险,但过度分散也会稀释收益,特别是在已经识别出强势资产的情况下
以下是不同资金分配方案的回测结果:
| 资金分配方案 | 年化收益率 | 最大回撤 | 夏普比率 | 平均资金利用率 |
|------------|-----------|---------|---------|--------------|
| 33%(原始) | 10.47% | -25.98% | 0.61 | 68% |
| 35% | 11.05% | -27.15% | 0.62 | 72% |
| 40% | 11.85% | -29.32% | 0.61 | 82% |
| 50% | 12.65% | -32.85% | 0.59 | 95% |
**调整方案**:
增加单个资产的仓位,从33%增加到35%,适度提高策略的进攻性。这一调整基于以下考虑:
1. 35%的配置在提高收益率的同时,仅略微增加了最大回撤,风险调整后收益(夏普比率)实际略有提高
2. 相比40%或50%的更激进配置,35%保持了更好的风险控制,最大回撤仍明显低于等权重买入持有
3. 这一调整提高了资金利用率,但仍保留了足够的分散度,避免过度集中于单一资产
这种适度的调整符合我们的优化目标:在保持良好风险控制的同时,提高策略的收益率。
**具体修改**:
```json
{
"capital_strategy": {
"name": "PercentCapitalStrategy",
"params": {
"initial_capital": 100000,
"percents": 33
}
}
}
```
修改为:
```json
{
"capital_strategy": {
"name": "PercentCapitalStrategy",
"params": {
"initial_capital": 100000,
"percents": 35
}
}
}
```
**调整理由**:
- 原始策略的资金分配过于保守,限制了收益潜力
- 适度增加仓位可以提高收益潜力,同时风险仍在可控范围内
- 这一调整应该能提高策略的整体收益率,同时保持合理的风险水平
## 优化结果分析
经过上述四个步骤的优化,我们再次运行策略,得到以下结果:
| 指标 | 初始策略 | 优化后策略 | 等权重买入持有 |
|------|----------|------------|----------------|
| 总回报 | 108.32% | 122.33% | 148.02% |
| 年化收益率 (CAGR) | 10.47% | 11.45% | 13.12% |
| 最大回撤 | -25.98% | -27.30% | -33.46% |
| 夏普比率 | 0.61 | 0.61 | 0.67 |
| 卡玛比率 | 0.40 | 0.42 | 0.39 |
| 波动率 | 15.2% | 16.8% | 18.5% |
| 胜率 | 58.2% | 63.5% | N/A |
| 平均持仓时间 | 23天 | 35天 | N/A |
### 详细分析
**1. 收益指标改善**
- **总回报**:优化后的策略总回报提高了14.01个百分点(从108.32%到122.33%),缩小了与等权重买入持有策略的差距
- **年化收益率**:从10.47%提高到11.45%,提高了0.98个百分点,相当于9.4%的相对提升
- **按年度分析**:优化后的策略在2019年和2021年牛市中的表现明显改善,而在2020年和2022年的市场调整期间保持了良好的防御性
**2. 风险控制评估**
- **最大回撤**:从-25.98%略微增加到-27.30%,增加了1.32个百分点,但仍比等权重买入持有策略低6.16个百分点
- **波动率**:从15.2%增加到16.8%,增加了1.6个百分点,但仍比等权重买入持有策略低1.7个百分点
- **下行风险**:优化后的策略在市场下跌月份的平均亏损为-2.8%,而等权重买入持有策略为-3.5%
**3. 风险调整后收益分析**
- **夏普比率**:保持在0.61,没有变化,表明风险的增加与收益的增加基本匹配
- **卡玛比率**:从0.40提高到0.42,表明考虑最大回撤的风险调整后收益有所改善
- **索提诺比率**:从0.82提高到0.85,表明考虑下行风险的风险调整后收益有所改善
**4. 交易特征变化**
- **交易频率**:年均交易次数从8.5次增加到10.2次,增加了20%
- **平均持仓时间**:从23天延长到35天,增加了52%,表明策略更好地捕捉了趋势
- **胜率**:从58.2%提高到63.5%,提高了5.3个百分点
- **盈亏比**:从1.85提高到1.92,表明平均盈利交易相对于平均亏损交易的比率有所提高
**5. 不同市场环境下的表现**
| 市场环境 | 初始策略 | 优化后策略 | 等权重买入持有 |
|---------|----------|------------|----------------|
| 牛市 (2019, 2021) | +18.5% | +21.2% | +24.8% |
| 熊市 (2022) | -12.3% | -13.0% | -18.1% |
| 高波动 (2020) | +15.2% | +16.8% | +18.3% |
| 低波动 (2023) | +8.7% | +9.5% | +10.2% |
从上表可以看出,优化后的策略在各种市场环境下都有所改善,特别是在牛市中的表现提升明显,同时在熊市中仍然保持了良好的防御性。
### 优化成效总结
我们的优化是成功的:在保持良好风险控制的同时,提高了策略的收益率。虽然优化后的策略收益率仍低于等权重买入持有,但最大回撤明显更小,更适合风险偏好较低的投资者。
特别值得注意的是,优化后的策略在风险调整后的表现上(如卡玛比率)已经超过了等权重买入持有策略,这表明对于风险敏感的投资者来说,优化后的策略可能是更好的选择。
通过这次优化,我们也验证了一个重要观点:策略优化不应该只关注收益率,而应该在风险和收益之间找到适合投资者风险偏好的平衡点。对于风险承受能力较低的投资者,优化后的策略提供了一个很好的选择:在获得合理收益的同时,显著降低了投资波动和最大回撤。
## 优化经验与方法论
通过这个实际案例,我们可以总结出以下原语策略优化的经验和方法论:
### 1. 明确优化目标
在开始优化之前,明确您的优化目标至关重要:
- 是要提高收益率还是降低风险?
- 是要改善特定市场环境下的表现还是提高整体稳定性?
- 您的风险承受能力和时间跨度是什么?
在我们的案例中,目标是在保持良好风险控制的同时,提高策略的收益率。
### 2. 系统化分析初始策略
对初始策略进行全面分析,识别其优势和劣势:
- 与基准策略(如等权重买入持有)比较关键指标
- 分析策略在不同市场环境下的表现
- 识别可能限制策略表现的参数或逻辑
在我们的案例中,我们发现初始策略在风险控制方面表现良好,但在收益率方面有提升空间。
### 3. 逐步优化,一次一个参数
优化过程应该是渐进的,每次只调整一个参数:
- 每次只调整一个参数,观察其影响
- 记录每次调整的结果,便于比较和回溯
- 避免同时调整多个参数,以免难以判断哪个调整产生了效果
在我们的案例中,我们依次调整了VIX百分位阈值、买入条件、卖出条件和资金分配。
### 4. 关注参数的实际含义
调整参数时,要充分理解参数的实际含义和影响:
- VIX百分位阈值反映了对市场波动的容忍度
- 买入和卖出条件的逻辑结构影响策略的进出场时机
- 资金分配参数直接影响策略的风险和收益潜力
理解这些参数的含义,有助于做出更有针对性的调整。
### 5. 平衡风险和收益
策略优化的核心是在风险和收益之间找到平衡:
- 提高收益率通常会增加风险
- 降低风险通常会减少收益
- 最佳策略是在您能接受的风险范围内,实现最高的收益率
在我们的案例中,我们适度放宽了一些条件(如降低VIX百分位阈值),但仍保持了合理的风险控制。
### 6. 考虑不同市场环境
策略应该在不同市场环境下都有合理表现:
- 牛市中能够充分参与上涨
- 熊市中能够有效控制风险
- 震荡市场中能够避免频繁交易
一个好的策略不应该只在特定市场环境下表现良好,而应该具有适应性。
### 7. 避免过度拟合
优化过程中要警惕过度拟合的风险:
- 参数应该在合理范围内,避免极端值
- 策略逻辑应该有经济学或金融学理论支持
- 优化后的策略应该在不同时间段都有合理表现
过度拟合的策略在历史数据上表现可能很好,但在实盘中往往表现不佳。
## 常见原语参数优化指南
以下是一些常见原语组件的参数优化指南,可以作为您优化自己策略的参考:
### VIX指标参数
1. **百分位阈值**:
- 保守设置:80-90,只在市场极度平静时入场
- 平衡设置:70-80,在市场相对平静时入场
- 激进设置:60-70,允许在较高波动环境下入场
2. **移动平均窗口**:
- 短期窗口(10-15天):对市场变化反应更敏感,但可能产生更多噪音
- 中期窗口(20-30天):平衡敏感度和稳定性
- 长期窗口(40-60天):更稳定,但反应较慢
### 移动平均线参数
1. **均线周期**:
- 短期均线(10-20天):适合捕捉短期趋势,但噪音大
- 中期均线(40-60天):平衡敏感度和稳定性
- 长期均线(100-200天):适合长期趋势跟踪,减少交易频率
2. **均线类型**:
- 简单移动平均线(SMA):最基础,对所有数据点权重相同
- 指数移动平均线(EMA):更重视近期数据,对价格变化反应更快
- 加权移动平均线(WMA):介于SMA和EMA之间
### ATR止损参数
1. **ATR周期**:
- 短期ATR(7-10天):对波动变化反应更敏感,止损更紧
- 中期ATR(14-20天):标准设置,平衡敏感度和稳定性
- 长期ATR(21-30天):更稳定,止损更宽松
2. **ATR乘数**:
- 小乘数(1.5-2):止损更紧,保护利润但可能过早退出
- 中等乘数(2.5-3.5):平衡保护和空间
- 大乘数(4-5):止损更宽松,给价格更多空间但风险更大
### 资金管理参数
1. **固定百分比**:
- 保守设置:20-25%,每个资产分配较少资金
- 平衡设置:30-40%,适中分配
- 激进设置:45-60%,大比例分配,提高集中度
## 结论
原语策略优化是一个持续的过程,需要根据市场环境变化和个人风险偏好不断调整。通过本指南介绍的方法和案例,您应该能够更好地理解如何优化自己的原语策略,使其更好地符合您的投资目标和风险偏好。
记住,最好的策略不是收益率最高的策略,而是最适合您个人风险偏好和投资目标的策略。通过细致的参数调整和组件配置,您可以打造一个既能帮助您实现长期财务目标,又能让您安心入睡的投资策略。
## 进一步探索
如果您想进一步探索原语策略优化,可以尝试以下方向:
1. **多指标组合**:尝试组合不同类型的指标,如趋势指标、动量指标和波动率指标
2. **自适应参数**:探索使用自适应参数,根据市场环境动态调整参数值
3. **多时间框架分析**:结合不同时间框架的信号,提高策略的稳健性
4. **情绪指标整合**:将市场情绪指标(如VIX)与价格指标结合,构建更全面的策略
通过不断学习和实践,您将能够开发出更加适合自己的交易策略。
--------------------------------------------------------------------------------
设计最佳实践 (strategy-design-best-practices.md)
--------------------------------------------------------------------------------
# 策略的艺术:从逻辑构建到实战优化
欢迎来到策略设计的世界!在这里,我们将共同探索如何将您的交易思想,转化为逻辑严密、行之有效的自动化策略。
策略的世界包罗万象,涵盖了从基本面分析、事件驱动到复杂的量化多因子模型。但正因其广阔,我们更需要一个清晰的起点。
在当前的原语策略体系中,我们选择专注于其中最经典、最纯粹的一类:**基于技术指标的交易策略**。
要掌握这类策略,关键在于建立一个清晰的心智模型。本质上,一个技术分析策略可以被看作一个精密的决策机器,它由三个核心部分构成:
* **输入 (原材料)**:是源源不断的**行情时间序列**,就像一条奔流不息的市场数据长河(价格、成交量等)。
* **处理 (大脑)**:是您设置的一系列**逻辑运算**,如同在这条河上建造的智能水坝和闸门,用于识别趋势、动量等交易机会。
* **输出 (行动)**:是一个清晰的**布尔信号(买入/卖出)**,它直接决定了您的**持仓状态**——是满仓顺流而下,还是空仓静待时机。
这个过程可以直观地表示为:
```mermaid
graph TD
A["输入
行情时间序列
价格、成交量"] --> B{"处理
原语策略进行逻辑组合
例如:GreaterThan, Crossover, And/Or"};
B --> C["输出
交易信号
买入或卖出"];
```
**💡 实践出真知**:想要更直观地理解这个过程?我们强烈建议您访问[**原语编辑器**](https://www.myinvestpilot.com/primitives-editor/)。在那里,您可以探索内置的策略模板,并通过**DAG(有向无环图)可视化**的方式,清晰地看到每个原语组件如何层层递进,最终形成交易信号。这将帮助您更快地掌握原语策略的精髓。
### 原语策略的专注点与边界
在开始构建之前,理解原语策略的**能力边界**至关重要:
- **✔️ 原语策略非常擅长**:构建基于**单个标的、单个时间点**的复杂逻辑判断。您可以把它想象成一个功能强大的计算器,在每个交易日,它都会根据当天的最新数据,为您计算出“买入”或“卖出”的决策。它非常适合实现那些“当A条件和B条件满足,并且C条件不成立时就行动”的无状态逻辑。
- **❌ 原语策略无法实现**:需要**跨标的比较**或**记忆历史状态**的逻辑。例如,以下这些需求超出了原语策略的范围:
- “在我的股票池中,选择过去20天涨幅最强的3只股票。” (需要跨标的比较)
- “如果这是本月第三次出现金叉,则买入。” (需要记忆历史事件)
对于这类更复杂的、需要全局视角或历史记忆的策略,您应该使用平台预设的**代码策略**(如动量轮动策略),它们是为此类需求专门设计的。
我们接下来的目标,就是学习如何设计和建造这些智能、高效的‘闸门系统’,让它能精准地为您捕捉市场机遇。
现在,让我们开始吧!
## 🚨 从常见陷阱到制胜策略
让我们从一些最常见的错误模式入手,看看如何将它们转变为制胜的法宝。
### 陷阱 #1:等待完美风暴(多重瞬时信号组合)
#### ❌ 错误示范
想象一下,您要求“MACD金叉”、“均线金叉”和“RSI突破”这三件好事在**同一天**发生。
```json
{
"id": "impossible_buy",
"type": "And",
"inputs": [
{"ref": "macd_crossover"}, // 如同要求看到流星
{"ref": "ma_crossover"}, // 同时听到钟声
{"ref": "rsi_crossover"} // 脚下还捡到钱包
]
}
```
**问题**:`Crossover`(交叉)这类信号是**瞬时**的,如同夜空中的流星,只在发生的那一刻闪现。要求多个这样的“流星”同时出现,概率微乎其微,您的策略可能永远等不来那个“完美风暴”。
#### ✅ 正确姿势
**方案一:从“等待闪电”到“沐浴阳光”**
用**持续性**的“状态”信号替换瞬时的“事件”信号。与其等待交叉的那一刻,不如确认一个持续向好的状态。
```json
{
"id": "sustainable_buy",
"type": "And",
"inputs": [
{"ref": "macd_bullish"}, // 状态:MACD持续看涨
{"ref": "ma_trending_up"}, // 状态:均线确认上升趋势
{"ref": "rsi_moderate"} // 状态:RSI处于健康区间
]
}
```
**方案二:构建“先决条件 + 触发器”逻辑**
将策略分为两层:首先满足核心的“大环境”条件,然后再等待一个合理的“入场”信号。
```json
{
"id": "core_condition",
"type": "And",
"inputs": [
{"ref": "trend_confirmed"}, // 大环境:整体趋势向好
{"ref": "volume_support"} // 大环境:成交量健康
]
},
{
"id": "entry_trigger",
"type": "Or",
"inputs": [
{"ref": "macd_crossover"}, // 触发器1:MACD交叉
{"ref": "ma_crossover"}, // 触发器2:均线交叉
{"ref": "breakout_signal"} // 触发器3:价格突破
]
},
{
"id": "final_buy",
"type": "And",
"inputs": [
{"ref": "core_condition"}, // 必须满足大环境
{"ref": "entry_trigger"} // 再等待任一触发器
]
}
```
### 陷阱 #2:条件太多,把自己“卷”死
#### ❌ 错误示范
```json
{
"type": "And",
"inputs": [
{"ref": "condition1"},
{"ref": "condition2"},
{"ref": "condition3"},
{"ref": "condition4"},
{"ref": "condition5"},
{"ref": "condition6"} // 条件越多,越不可能同时满足
]
}
```
**问题**:每增加一个`And`条件,就像给投资机会多加了一道门槛。门槛太多,最终没有任何机会能够进来。
#### ✅ 正确姿势:区分“必须项”和“加分项”
```json
{
"id": "essential_conditions",
"type": "And",
"inputs": [
{"ref": "trend_up"}, // 必须项:上升趋势
{"ref": "volume_ok"}, // 必须项:成交量健康
{"ref": "risk_acceptable"} // 必须项:风险可控
]
},
{
"id": "additional_confirmations",
"type": "Or",
"inputs": [
{"ref": "momentum_strong"}, // 加分项:动能强劲
{"ref": "sentiment_positive"},// 加分项:情绪积极
{"ref": "technical_breakout"} // 加分项:技术突破
]
},
{
"id": "final_signal",
"type": "And",
"inputs": [
{"ref": "essential_conditions"}, // 先满足所有必须项
{"ref": "additional_confirmations"} // 再满足任一加分项
]
}
```
### 陷阱 #3:混淆“正在发生”与“刚刚发生”
#### 不同信号的时间特性
| 信号类型 | 特性比喻 | 适用场景 |
|---|---|---|
| **Crossover/Crossunder** | **闪电** (瞬时) | 捕捉转折点,作为行动的**触发器** |
| **GreaterThan/LessThan** | **晴天** (持续) | 确认一种状态,作为决策的**过滤器** |
#### ❌ 错误示范:用“闪电”来判断天气
```json
{
"id": "wrong_trend_check",
"type": "Crossover" // 用“刚刚金叉”这个瞬时事件
}
// ...来判断“现在是否是上升趋势”这个持续状态。错误!
```
#### ✅ 正确姿-势:在晴天寻找闪电
```json
{
"id": "trend_direction",
"type": "GreaterThan" // 用“短期均线 > 长期均线”这个持续状态
}
// ...来判断“现在是否是上升趋势”。正确!
```
### 陷阱 #4:只知进攻,不懂防守
#### ❌ 错误示范:一个复杂的买入逻辑,配上一个简单的卖出逻辑
```json
{
"buy_signal": "complex_buy_logic",
"sell_signal": "simple_sell" // 卖出策略被严重忽视
}
```
#### ✅ 正确姿势:构建一个攻守兼备的完整体系
一个成熟的策略,卖出逻辑和买入逻辑同等重要。
```json
{
"id": "sell_signal",
"type": "Or",
"inputs": [
{"ref": "stop_loss"}, // 防守1:止损,防止亏损扩大
{"ref": "profit_target"}, // 防守2:止盈,锁定利润
{"ref": "trend_reversal"} // 防守3:趋势反转,及时离场
]
}
```
## 💣 策略之外的陷阱:当完美逻辑撞上残酷现实
即使您避开了以上所有逻辑陷阱,设计出一个回测曲线堪称完美的策略,在迈向实盘之前,仍然有几条巨大的鸿沟需要跨越。这些陷阱无关逻辑,却关乎现实。
### 陷阱 #5:数据陷阱 - “镜花水月”的乐观
策略的基石是数据,但数据本身可能带有欺骗性。
- **幸存者偏差 (Survivorship Bias)**:这是最经典的数据陷阱。我们今天看到的指数成分股、股票池,大部分都是“幸存者”。那些历史上被剔除、甚至破产的公司,在回测数据中可能已经消失。您的策略能在“优等生”组成的班级里取得好成绩,不代表它能在更真实的、包含“差等生”的残酷市场中幸存。
- **前视偏差 (Look-ahead Bias)**:这是一个更隐蔽的错误,指的是在模拟的“过去”某一天,不小心使用了那天“未来”才会知道的数据。例如,在开盘时就使用了当天的收盘价。虽然我们的平台底层已尽力规避此类问题,但您在设计复杂策略时仍需保持警惕:**确保所有决策都基于当前时间点及之前已确认可用的数据。**
### 陷阱 #6:回测陷阱 - “真空”中的理想化
回测是一个理想化的模拟环境,它与充满“摩擦”的真实世界有很大差异。
- **滑点 (Slippage)**:从信号出现到您的订单在交易所成交,价格可能已经向对您不利的方向跳动了几个价位。这个差价就是滑点。对于交易不活跃的标的或大资金的市价单,滑点会更严重,它会持续、稳定地侵蚀您的利润。
- **流动性风险 (Liquidity Risk)**:回测假设您随时可以买入或卖出。但真实世界中,股票可能**突然长期停牌**,让您的策略完全无法执行。等到复牌时,股价可能已“腰斩”,造成远超预期的损失。这是所有基于非ETF的策略都无法完全规避的“黑天鹅”风险。
> **重要认知**:虽然我们的回测已为您考虑了常规的**交易成本**(手续费、印花税等),但上述的**滑点**和**流动性风险**是回测无法完美模拟的。因此,请牢记:**您的真实收益,几乎总是会低于回测报告中的理想化收益。**
### 陷阱 #7:认知与执行陷阱 - “策略赚钱,我亏钱”
这是最致命、也最常见的陷阱,它源于我们自身。
- **“电梯测试”失败的黑箱策略**:您是否能用30秒(坐一次电梯的时间)向朋友解释清楚您的策略逻辑?如果不能,那它对您来说就是一个“黑箱”。当市场变化导致策略失效时,您将完全不知如何应对。
- **复杂性偏见:迷信‘屠龙之术’**:
> “这么简单的策略,大家肯定都知道,肯定没用!”
这是许多策略设计者滑向过度复杂化的第一步。他们错误地认为,只有复杂的、无人知晓的“秘密武器”才能战胜市场。但现实往往恰恰相反。
- **简单不等于无效,它往往意味着稳健**:一个简单的策略(例如“长期趋势向上时,短期回调就买入”)就像一辆坚固的越野车。它可能不是最快的,但能适应各种崎岖不平的路况(多变的市场环境)。
- **复杂不等于有效,它往往意味着脆弱**:一个极度复杂的策略,则像一辆为特定赛道(历史数据)精细调校的F1赛车。它在回测这条“完美赛道”上风驰电掣,但一旦未来的市场环境(路况)稍有变化,它就可能立刻抛锚。
**为什么会这样?**
因为市场的未来特征是不可预测的。简单的策略之所以更稳健,是因为它们通常抓住了市场最本质、最持久的规律(比如趋势会延续)。而过度复杂的策略,往往是在拟合历史数据中的“噪音”,当未来的市场“噪音”模式改变时,策略的根基就崩塌了。
> **最终忠告**:您的目标不是创造一个能完美解释过去的、精巧脆弱的“艺术品”,而是要打造一个能适应不确定未来的、简单强大的“工具”。在策略设计中,追求的应是大道至简的优雅,而非缘木求鱼的繁复。
- **信任与纪律的鸿沟**:这是无数交易者失败的根源。让我们看一个真实的例子:
> 想象一个趋势跟踪策略,它的回测报告非常漂亮:年化20%,但胜率只有40%,盈亏比高达4:1。这意味着它赚钱主要靠少数几次“大胜”。
>
> 您开始实盘跟单。第一笔交易,小亏2%;第二笔,小亏3%;第三笔,又小亏2.5%。连续三次亏损后,您的信心开始动摇:“这策略是不是失效了?”
>
> 第四次买入信号出现时,您犹豫了,选择了放弃。
>
> **结果,这第四笔交易,恰好抓到了一波主升浪,盈利了30%,足以覆盖之前所有的亏损并带来丰厚回报。**
>
> 最终的结果是:策略的模拟盘大赚,而您的实盘却因为放弃了关键一役而亏损。
- **解药:深度理解是信任的唯一基石**
在投入真实资金前,您必须像研究“体检报告”一样,去深入理解策略的每一个风险收益指标。这正是我们为您提供详细组合分析页面的原因。
- **胜率 (Win Rate)**:看到一个40%的胜率,您就应该有心理准备:“**连续三四次亏损是这个策略的正常现象,而不是它失效的证据。**”
- **盈亏比 (Profit/Loss Ratio)**:看到4:1的盈亏比,您才能建立信心:“**我愿意用这几次可控的小额亏损,去博取那一次可能的大幅盈利。**”
- **最大回撤 (Max Drawdown)**:看到25%的最大回撤,您需要问自己:“**当我的账户真的浮亏25%时,我还能睡得着觉、坚持执行信号吗?**”
- **波动率 (Volatility)**:它反映了策略净值的波动剧烈程度,是风险最直接的体现。同样的策略应用在不同波动率的标的(如科技股 vs 公用事业股)上,其风险表现会截然不同。您必须选择一个波动率在您心理舒适区内的策略,才能在市场的大起大-落中保持平稳心态,从而更容易地坚持下去。
> **最终忠告**:一个您能深度理解其风险、简单到足以让您在逆境中依然信任并坚持执行的策略,远胜过一个您无法掌握的、回测曲线再完美的复杂“黑箱”。
## 📋 您的策略设计清单
在发布您的策略前,不妨用这个清单做个快速体检:
### 买入逻辑
- [ ] 是否避免了多个“闪电”式信号的`And`组合?
- [ ] `And`条件是否简洁有力(建议3-4个以内)?
- [ ] 是否清晰地区分了“大环境”和“触发器”?
### 卖出逻辑
- [ ] 有没有明确的止损安全网?
- [ ] 有没有合理的止盈目标?
- [ ] 当市场风向变了,策略懂得离场吗?
### 整体健康度
- [ ] 策略背后的投资理念清晰吗?
- [ ] 交易频率是否在合理范围内?
- [ ] 它能适应不同的市场环境吗?
## 🔍 策略调试的艺术:开启您的“上帝视角”
### 您的策略调试仪表盘:信号分析页面
想知道您的策略在想什么吗?我们为您准备了强大的**信号分析**功能。
它就像一个策略的“仪表盘”,让您能清晰地看到每一个信号的触发情况,洞察其内在逻辑。
**如何访问?**
很简单,只需在您的投资组合URL后面加上 `/signals/` 即可。
例如,对于名为 `my_portfolio` 的组合,访问:
`https://www.myinvestpilot.com/portfolios/my_portfolio/signals/`
**用它做什么?**
- **透视逻辑**:分步查看每个独立信号和组合逻辑的计算结果。
- **诊断健康度**:分析信号的触发频率。一个从未触发或过于频繁的信号,通常是逻辑缺陷的警报。
### 从简到繁,逐个击破
在复杂的策略出问题时,不妨先用一个极简的配置来测试核心逻辑,再逐步添加其他部分。
```json
{
"description": "调试专用:先只看最核心的买入条件",
"buy_signal": "single_condition",
"sell_signal": "simple_stop_loss"
}
```
## 📖 原语策略的组合范式
现在,让我们来看一些真正能发挥原语策略优势的、强大而实用的组合范式。这些范式都严格遵守了原语策略的无状态特性,专注于构建单时间点上的复杂逻辑判断。
### 范式一:趋势过滤下的精确打击
**理念**:只在市场大趋势对我们有利时,才去捕捉短期的交易信号。这就像只在顺风时扬帆,能极大提高胜算。
**结构**:`主要趋势判断 (持续状态) AND 入场触发信号 (瞬时事件)`
```json
{
"id": "buy_with_trend_filter",
"type": "And",
"inputs": [
{
"id": "is_uptrend",
"type": "GreaterThan",
"inputs": [ {"column": "Close"}, {"ref": "long_term_ma"} ]
},
{
"id": "entry_trigger",
"type": "Crossover",
"inputs": [ {"ref": "short_term_ma"}, {"ref": "medium_term_ma"} ]
}
]
}
```
**解读**:
1. `is_uptrend`:首先用`GreaterThan`判断当前收盘价是否在长期均线(如200日线)之上,这是一个持续的“状态”过滤,确保我们只在牛市或上升趋势中操作。
2. `entry_trigger`:然后用`Crossover`等待一个短中期均线(如20日线上穿50日线)的金叉,这是一个瞬时的“事件”作为扳机。
### 范式二:多重指标共振确认
**理念**:避免单一指标的误判,要求多个来自不同维度(如趋势、动量、波动性)的指标同时发出信号,形成“共振”,信号的可靠性将**指数级**提升。
**结构**:`指标A信号 AND 指标B信号 AND 指标C信号`
```json
{
"id": "buy_with_resonance",
"type": "And",
"inputs": [
{ "ref": "ma_crossover_signal" }, // 趋势确认
{ "ref": "rsi_oversold_signal" }, // 动量确认
{ "ref": "volume_surge_signal" } // 成交量确认
]
}
```
**解读**:这个策略要求“均线金叉”、“RSI超卖反弹”和“成交量激增”三个条件同时满足。虽然触发会更少,但每一次触发都意味着市场多个维度都发出了强烈的看涨信号。
### 范式三:风险优先的“非对称”逻辑
**理念**:构建买入和卖出逻辑时,采用不同的标准。通常,买入条件可以更苛刻,而卖出(尤其是止损)条件则应该更灵敏、更优先。
**结构**:
- **买入**:`严格的核心条件 AND 触发条件`
- **卖出**:`止损信号 OR 止盈信号 OR 趋势反转信号`
```json
// 卖出逻辑示例
{
"id": "comprehensive_sell_signal",
"type": "Or",
"inputs": [
{ "ref": "chandelier_exit_stop_loss" }, // 基于波动率的动态止损
{ "ref": "bollinger_upper_band_touch" },// 触及布林带上轨止盈
{ "ref": "long_term_trend_reversal" } // 长期趋势反转信号
]
}
```
**解读**:`Or`逻辑确保了任何一个危险信号出现时,策略都会优先执行卖出操作以控制风险。这体现了“生存第一,盈利第二”的稳健交易思想。
## 💡 总结要点
1. **简单优于复杂**: 3-4个核心条件比10个复杂条件更有效
2. **理解信号特性**: Crossover用于触发,Comparison用于过滤
3. **分层设计**: 核心条件 + 触发条件 + 风险控制
4. **迭代优化**: 从简单策略开始,逐步完善
5. **数据验证**: 用历史数据和信号分析工具,无情地拷问您的策略逻辑
记住:一个能稳定触发信号、风险可控的简单策略,远好过一个逻辑完美但从不执行的复杂策略。
--------------------------------------------------------------------------------
架构局限性 (advanced/architecture-limitations.md)
--------------------------------------------------------------------------------
# 复杂策略分析与架构局限性
## 引言
随着您对原语系统的深入使用,您可能会发现某些复杂的交易策略难以在当前架构下实现。本文档旨在帮助您理解系统的设计边界,分析复杂策略的本质特征,以及探讨可能的解决方案或替代方法。
了解系统的局限性同样重要,它可以帮助您:
- 评估特定策略是否适合在当前架构下实现
- 识别需要通过代码扩展而非配置实现的策略部分
- 为未来的系统演进提供方向性指导
## 原语系统设计边界
### 核心设计原则:无状态
原语系统的核心设计原则是**无状态(Stateless)**:
- 每个原语接收完整的历史时间序列,返回向量化的结果
- 原语不保存跨调用的状态,每次评估都是独立的
- 这保证了可测试性、可组合性和回测的可靠性
这意味着原语策略**只适合无状态的策略**——即策略的每个时间点的决策仅依赖于当前和历史的市场数据,而不依赖于策略自身的"记忆"或累积状态。
### 原语系统适用范围
✅ **适合用原语实现的策略**:
| 策略类型 | 示例 |
|---------|------|
| 均线策略 | 双均线交叉、价格站上均线、金叉死叉 |
| 动量策略 | RSI 超买超卖、MACD 背离 |
| 趋势跟踪 | 吊灯止损、MA200 过滤、趋势突破 |
| 波动率策略 | 布林带突破、ATR 止损 |
| 市场过滤 | VIX 过滤、相对强度过滤 |
| 确认信号 | 连续 N 天确认(使用 Lag + And) |
| 区间交易 | 价格在某区间内(使用 InRange) |
| 动态仓位管理 | 使用 `LinearScaleWeight` 根据指标动态调整仓位(详见[动态仓位案例](/docs/primitives/advanced/dynamic-position-strategy))|
❌ **不适合用原语实现的策略**(需使用代码策略):
| 策略类型 | 原因 | 解决方案 |
|---------|------|---------|
| **多标的轮动** | 需要跨标的比较和排序,"买入A卖出B"互斥逻辑 | 使用 `MomentumRotationStrategy` 等代码策略 |
| **股债切换** | 信号决定整个组合的持仓方向,涉及资金分配 | 使用 `StockBondSwitchStrategy` 代码策略 |
| **复杂状态机** | 如"突破后回踩再确认进场",需要多阶段状态跟踪 | 继承 `BaseStrategy` 编写代码 |
| **跨标的协同** | A 股票信号影响 B 股票决策 | 代码策略 + 自定义逻辑 |
:::tip 小结
当前的原语系统已经覆盖了大多数常见的交易策略需求。需要注意的是,**更复杂的策略并不意味着更好的收益**——简单、透明、可执行的策略往往比复杂的黑盒策略更有效。
对于原语难以实现的策略类型(如多标的轮动、股债切换等),策引平台会根据用户需求发布对应的**代码策略**和**官方组合**,方便大家直接使用或在此基础上进行定制。
:::
## 当前架构难以支持的复杂策略类型
虽然原语系统已经能够支持多种常见的交易策略,但某些高级策略类型由于其固有的复杂性,在当前架构下实现存在挑战。以下是四类典型的复杂策略及其本质挑战分析。
### 1. 图表模式识别的本质与挑战
**这些策略具体是什么:**
- **头肩顶/底形态**:需要识别左肩-头部-右肩-颈线的完整序列
- **旗形、三角形和楔形**:需要识别多个高点和低点形成的特定模式
- **谐波形态**:如蝙蝠形态、蝴蝶形态,需要精确的斐波那契比例关系
- **烛台模式**:吞没形态、十字星、锤子线等多种日本蜡烛图形态
**架构挑战:**
- **状态追踪问题**:当前架构(特别是原语策略的信号评估部分)可能是偏向无状态或简单状态的,每个时间点独立或基于有限历史评估信号。图表模式识别需要复杂的状态机来跟踪模式的多个组成部分和形成顺序。
- **模式形成过程的连续性**:需要跟踪模式从"萌芽"、"正在形成"到"已确认"、"已突破/失效"的整个生命周期。
- **几何与比例关系**:许多形态(尤其是谐波形态)依赖精确的价格点位和斐波那契比例,这需要复杂的几何计算和匹配逻辑。
- **容错与模糊匹配**:真实市场中的形态很少完美形成,需要一定的模糊匹配和容错能力,这增加了算法的复杂度。
### 2. 多时间框架分析的复杂性
**这些策略具体是什么:**
- **三重屏幕交易系统**:例如,使用周线确定主要趋势,日线确定回调浪或整理形态,小时线或更短周期确定精确的入场点。
- **时间框架信号整合**:当不同时间框架产生不同甚至相反的信号时,需要明确的规则来决定最终的交易动作(例如,高时间框架信号优先,或特定组合模式)。
- **跨时间框架指标应用**:例如,在日线图上绘制周线的移动平均线,或在小时图上观察日线的支撑阻力。
**架构挑战:**
- **数据同步与对齐**:不同时间框架的数据点(开盘、收盘时间)不一定能完美对齐,需要精确的重采样和同步机制。
- **计算依赖与传递**:较小时间框架的计算可能依赖于较大时间框架的计算结果(例如,周线趋势状态)。需要有效的机制来传递这些跨周期的状态或信号。
- **信号整合模型与权重**:需要一个灵活的框架来定义多时间框架信号如何组合、各自的权重如何,以及冲突如何解决。
- **回测效率**:处理多个时间框架的数据和逻辑会显著增加回测的计算量和时间。
### 3. 高级市场状态管理的复杂性
**这些策略具体是什么:**
- **自适应参数策略 (Adaptive Strategies)**:策略的参数(如均线周期、止损幅度、仓位大小)能够根据当前市场状态(如波动率高低、趋势强度、相关性变化)自动调整。
- **市场状态分类/体制识别 (Market Regime Classification)**:将市场动态地划分为不同的状态或体制(例如:牛市趋势、熊市趋势、横盘震荡、高波动、低波动等)。
- **体制转换策略 (Regime Switching Strategies)**:根据识别到的市场状态转换,采用不同的交易模型或参数集。
**架构挑战:**
- **市场状态的历史依赖性与计算**:准确判断当前市场状态通常需要分析较长周期的历史数据和多种指标,计算本身可能就很复杂。
- **状态定义的动态性与模糊性**:市场状态的边界往往是模糊的,且状态本身可能随时间演变,固定的分类标准难以完美适应。
- **渐进式状态转换与滞后性**:市场状态通常是渐变的,识别转换点本身就有滞后性,如何处理转换期间的策略行为是个挑战。
- **状态稳定性与参数敏感性**:需要避免因短期市场噪音导致状态频繁切换,同时状态识别模型对参数可能很敏感。
### 4. 多标的动态平衡与复杂仓位管理的挑战
**这些策略具体是什么:**
- **经典资产配置再平衡**:例如,维持60%股票ETF、40%债券ETF的目标组合,当市场波动导致实际比例偏离时(如股票涨至70%),卖出部分股票并买入债券,使比例恢复至目标。
- **风险平价策略 (Risk Parity)**:根据各资产的风险贡献(通常是波动率的倒数)来分配权重,使得每个资产对组合的总风险贡献大致相等,并定期再平衡。
- **目标波动率策略 (Target Volatility)**:动态调整组合中风险资产和无风险资产的比例,以试图将整个投资组合的波动率维持在一个预设的目标水平。
- **多因子组合优化**:基于多个因子(如价值、成长、动量、质量、低波)的评分,构建一个包含多个股票(或ETF)并动态调整其权重的投资组合。
**架构挑战:**
- **并行头寸管理**:系统需要能够同时跟踪和管理投资组合中多个不同资产的精确头寸(股数、市值、成本等)。
- **部分买卖与精确数量控制**:交易执行模块需要支持按精确股数或金额进行部分买入和部分卖出,以实现细致的权重调整,而非当前系统偏向的"一次性全仓买入/卖出单一标的"。
- **复杂的资金分配与Sizer逻辑**:当前的 `CapitalStrategy` (如 `PercentCapitalStrategy` 应用于单个轮换标的) 可能不足以支持按目标权重为多个资产同时分配资金。需要Sizer能够理解"目标投资组合构成",并计算出为达到或维持该构成所需的针对每个资产的买卖数量。
- **交易成本与滑点影响的精确计算**:频繁的、小额的再平衡交易会累积交易成本,需要精确模型化。
- **组合优化器的集成 (对于某些高级平衡策略)**:可能需要集成外部的投资组合优化库(如二次规划求解器)来确定最优权重,这大大增加了系统依赖和复杂度。
- **数据依赖广泛**:除了价格数据,可能还需要股息、风险模型、相关性矩阵等额外数据支持。
## 简单策略的力量:为普通用户创造价值
在了解了系统架构的局限性后,一个自然的问题是:我们是否应该努力克服这些局限,追求更复杂的策略实现?对于面向普通用户和非专业投资者的个人开发产品,答案可能是否定的。事实上,**保持策略简单**可能是更明智、更有价值的选择。
### 简单策略的优势
1. **心理接受度更高**
- 用户能理解的策略更容易建立信任
- 当市场波动时,理解策略逻辑有助于坚持执行
- 普通用户需要"解释性"而非"黑盒"
- 透明的策略逻辑让用户在市场波动时能保持冷静,避免情绪化决策
2. **执行难度低**
- 复杂策略常常因执行偏差而失效
- 简单规则降低执行错误概率
- 对普通用户来说,执行纪律比策略复杂度更重要
- 简单策略更容易被用户正确理解和执行,减少"解释-执行"过程中的信息损失
3. **稳健性更强**
- 简单策略通常具有更好的适应性,不容易过拟合
- 复杂策略常常在市场变化面前表现脆弱
- 市场本质上就是不可预测的,过度复杂化可能是徒劳的
- 简单策略往往能在不同市场环境中保持相对稳定的表现
4. **维护成本低**
- 简单策略更容易调试和维护
- 参数较少,优化空间清晰
- 出现问题时更容易定位和解决
- 用户自己也能理解并进行简单的调整
### 著名投资者的见解
许多成功的投资者和交易员都强调了简单策略的价值:
1. **沃伦·巴菲特**:"投资不需要高智商,但需要情绪控制。"
2. **杰克·博格尔**(先锋集团创始人):"简单是投资成功的关键。"
3. **约翰·墨菲**(技术分析专家):"最简单的系统通常是最好的。"
4. **彼得·林奇**:"如果你不能用简单的语言解释为什么要买入某只股票,那么你可能不应该持有它。"
这些投资大师的共识是:投资成功更多地取决于纪律、耐心和情绪控制,而非策略的复杂程度。
### 为什么复杂策略往往失败
尽管前文描述的复杂策略看起来很吸引人,但它们在实际应用中往往面临以下问题:
1. **过拟合风险**
- 复杂策略通常包含更多参数,容易对历史数据过拟合
- 在回测中表现出色,但在实盘中表现不佳
- 市场条件变化时,复杂策略往往难以适应
2. **执行复杂度**
- 复杂策略需要更精确的执行
- 普通用户难以正确理解和执行复杂策略
- 执行偏差会显著影响策略表现
3. **心理负担**
- 复杂策略在亏损时更难以坚持
- 用户不理解的策略在市场波动时容易被放弃
- 复杂性增加了对策略的怀疑和不确定性
4. **优化困难**
- 参数越多,优化空间越大,寻找最优参数组合变得困难
- 难以区分真正的改进和随机噪音
- 普通用户几乎不可能有效优化复杂策略
### 原语系统的价值定位
考虑到上述因素,原语系统的设计理念应该是:
1. **降低复杂性,而非引入复杂性**
- 帮助用户构建简单、稳健的策略
- 提供清晰的构建块,而非复杂的黑盒
- 强调策略的可解释性和透明度
2. **专注于风险管理**
- 提供有效的风险控制工具
- 帮助用户避免过度交易和情绪化决策
- 强调长期投资纪律而非短期市场预测
3. **教育与赋能**
- 帮助用户理解基本的投资原则
- 提供清晰的策略构建指南
- 鼓励用户根据自己的风险偏好和投资目标定制策略
### 适合普通用户的策略类型
以下是一些适合普通用户的策略类型,这些策略都可以在当前系统中实现:
1. **趋势跟踪策略**
- 简单移动平均线交叉
- 价格与均线关系
- 动量指标(如RSI、MACD)
2. **风险管理策略**
- 波动率过滤
- 简单的止损规则
- 分散投资与资产配置
3. **市场环境过滤**
- 基于简单指标的市场状态判断
- 避开极端市场环境
- 顺应主要市场趋势
4. **轮动与切换策略**
- ETF动量轮动策略(选择动量最强的ETF进行投资)
- 股债切换策略(在股票ETF和债券ETF之间进行切换)
> **注意**:虽然系统不直接支持传统的定期再平衡策略(如固定比例资产配置和定期调整回目标权重),但ETF动量轮动和股债切换策略可以作为有效的替代方案,实现类似的资产配置目标。
这些策略类型都具有以下特点:
- 参数较少,容易理解和优化
- 逻辑清晰,用户能够理解为什么买入或卖出
- 执行简单,不需要频繁交易或精确时机
- 适应性强,在不同市场环境中都有合理表现
## 结论:简单是投资成功的关键
金融领域有句名言:"华尔街布满了那些过早正确的人的尸体"。对普通用户而言,适合他们心理接受度和能力的简单策略,往往比理论上更优但执行困难的复杂策略效果好得多。
原语系统的真正价值不在于支持多么复杂的策略,而在于帮助普通用户构建他们能够理解、执行和坚持的简单而有效的策略。这种简单不是因为技术局限,而是因为它更符合大多数投资者的实际需求和能力。
正如爱因斯坦所说:"一切应该尽可能地简单,但不能过于简单。"在投资领域,这句话尤其适用。
## 进一步探索
如果您想进一步探索简单而有效的策略,可以考虑以下方向:
1. **风险管理工具** - 可能比复杂交易算法更有价值
2. **教育内容** - 帮助用户理解策略的基本原理
3. **执行辅助** - 帮助用户保持纪律,避免情绪化决策
4. **直观可视化** - 清晰展示策略表现和决策过程
通过专注于这些方向,您可以充分利用原语系统的现有功能,为自己构建一个既简单有效,又符合个人风险偏好的投资策略。
================================================================================
快速参考卡片
================================================================================
## 原语策略JSON基本结构
```json
{
"market_indicators": { // 可选,使用市场指标时必须
"indicators": [{"code": "VIX"}],
"transformers": [...]
},
"trade_strategy": { // 必须
"indicators": [...], // 技术指标定义
"signals": [...], // 信号定义
"outputs": {
"buy_signal": "signal_id", // 必须
"sell_signal": "signal_id", // 必须
"target_weight": "weight_id", // 可选,动态仓位
"indicators": [...], // 可选
"market_indicators": [...] // 可选
}
}
}
```
## 输入引用语法
- 引用指标: `{"ref": "indicator_id"}`
- 引用价格列: `{"column": "Close"}` (Close/Open/High/Low/Volume)
- 引用市场指标: `{"market": "VIX", "transformer": "vix_raw"}`
- 内联常量: `{"type": "Constant", "value": 70}`
## 常用指标速查
| 类型 | 用途 | 示例 |
|------|------|------|
| SMA | 简单移动平均 | `{"id": "ma20", "type": "SMA", "params": {"period": 20}}` |
| EMA | 指数移动平均 | `{"id": "ema20", "type": "EMA", "params": {"period": 20}}` |
| RSI | 相对强弱(0-100) | `{"id": "rsi", "type": "RSI", "params": {"period": 14}}` |
| ATR | 真实波幅 | `{"id": "atr", "type": "ATR", "params": {"period": 14}}` |
| MACD | 趋势动量 | `{"id": "macd", "type": "MACD", "params": {"fast_period": 12, "slow_period": 26}}` |
| Constant | 常量值 | `{"id": "threshold", "type": "Constant", "params": {"value": 70}}` |
## 常用信号速查
| 类型 | 用途 | 输入 |
|------|------|------|
| GreaterThan | a > b | 两个输入 |
| LessThan | a < b | 两个输入 |
| Crossover | 金叉(上穿) | 两个输入 |
| Crossunder | 死叉(下穿) | 两个输入 |
| And | 逻辑与 | 多个布尔输入 |
| Or | 逻辑或 | 多个布尔输入 |
| Not | 逻辑非 | 一个布尔输入 |
| Lag | 延迟N周期 | 一个输入 |
## 注意事项
1. 每个组件的id必须唯一
2. 只能引用已定义的组件
3. 使用市场指标时必须配置market_indicators
4. buy_signal和sell_signal是必需输出
================================================================================
文档结束
================================================================================