# 策引原语策略参考文档 (llm.txt)
# Plutus Primitive Strategy Reference for LLMs
#
# 版本: 核心版 (Core Version)
# 大小: ~150-200KB | Token: ~50-70K
# 适用模型: GPT-4, Claude 3.5, Gemini (所有主流模型)
# 内容: 核心原语参考 + 基础示例 + 调试指南
#
# 核心版文档地址: 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.102Z
================================================================================
目录结构
================================================================================
本文档包含以下部分:
【核心参考】
- 快速入门: 原语策略基础概念和JSON结构
- AI辅助开发: 完整的AI辅助策略开发工作流
- 架构概述: 系统设计原则
- 指标原语参考: 所有可用的技术指标 (SMA, EMA, RSI, MACD, ATR, etc.)
- 信号原语参考: 所有可用的信号类型 (比较、交叉、逻辑、数学运算、权重控制)
- 组合模式: 如何组合原语构建复杂策略
【高级功能】
- 市场指标: 使用外部市场数据 (VIX, SPX等) 进行决策
【实战案例】
- 策略示例: 基础到进阶的完整策略配置
(完整案例请参考 llm-full.txt 或在线文档)
【调试与优化】
- 故障排除: 常见问题诊断和解决
- 高级调试: 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. 参数名称必须正确,系统不会自动纠正错误的参数名称
================================================================================
调试与优化
================================================================================
--------------------------------------------------------------------------------
故障排除 (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是必需输出
================================================================================
文档结束
================================================================================