一、信号基础:什么是交易信号?信号在量化交易中的核心作用
1.1 交易信号到底是什么?
先问个问题:你打开交易软件,看到满屏的K线和指标,然后呢?
大多数人会盯着MACD金叉、RSI超买超卖,凭感觉下单。但量化交易不是这样玩的。
交易信号,说白了就是一个明确的、可执行的买卖指令。它告诉你:现在买,还是现在卖,或者什么都不做。
举个例子:
# 一个最简单的信号逻辑
if 收盘价 > 20日均线:
发出买入信号
else:
发出卖出信号
嗯,就是这么直白。但别小看它——我见过太多人把信号搞复杂了,结果回测漂亮,实盘一塌糊涂。
核心定义:交易信号 = 市场数据 + 规则引擎 + 执行指令
它必须满足三个条件:
- 确定性:同样的输入,永远得到同样的输出
- 可重复性:任何人在任何时间运行,结果一致
- 可执行性:信号发出后,能直接转化为订单
1.2 信号在量化交易中的核心作用
我个人习惯把量化交易系统比作一辆自动驾驶汽车。信号就是方向盘——没有它,你只能原地打转。
具体来说,信号承担了四个关键角色:
| 角色 | 说明 | 我踩过的坑 |
|---|---|---|
| 决策引擎 | 把市场数据转化为买卖决策 | 曾经用了一个信号,回测年化50%,实盘直接亏了20%。后来发现是信号逻辑里有个隐藏的future bias |
| 风险过滤器 | 过滤掉噪音交易,只在高概率机会出手 | 有段时间信号太敏感,一天交易几十次,手续费吃掉了所有利润 |
| 策略载体 | 把你的交易理念变成可执行的代码 | 我刚开始写策略时,总想把所有想法塞进一个信号里,结果哪个都不灵 |
| 回测基石 | 没有信号,回测就是空谈 | —— |
你想想看,如果没有信号,你的交易靠什么?靠感觉?靠消息?那跟赌博有什么区别。
1.3 信号的分类:从简单到复杂
我在项目中遇到过各种各样的信号,大致可以分成三类:
1.3.1 基于价格的信号
最基础的一类。只看价格本身,不看其他数据。
- 突破信号:价格突破某个关键位
- 均线信号:短期均线上穿长期均线
- 动量信号:过去N天的涨幅超过阈值
1.3.2 基于指标的信号
把价格数据加工成指标,再用指标生成信号。
- RSI超买超卖:RSI > 70 卖出,RSI < 30 买入
- MACD金叉死叉:DIF上穿DEA买入,下穿卖出
- 布林带突破:价格突破上下轨
1.3.3 基于机器学习的信号
这个就高级一些了。用模型预测未来涨跌,然后生成信号。
- 分类模型:预测涨/跌/平
- 回归模型:预测具体价格
- 强化学习:动态调整信号阈值
我的建议:新手先从基于价格的信号开始。别一上来就搞机器学习——我见过太多人连均线都没搞明白,就跑去调LSTM参数了。结果呢?过拟合得一塌糊涂。
1.4 信号的生命周期
一个信号从想法到实盘,要经历五个阶段。我画了张图,你看一眼就明白了:
这张图我画了好几次才满意。你看,从想法到实盘,每一步都不能跳过。我曾经跳过优化阶段,直接把回测好的信号上线,结果市场风格一变,亏得我怀疑人生。
1.5 信号的质量评估标准
不是所有信号都值得上实盘的。我总结了一套评估标准,你写信号的时候可以对照着看:
- 胜率:信号发出后,盈利的次数占比。但别只看胜率——我见过胜率70%的策略,亏得比赚的多。为什么?因为亏一次就把前面赚的全吐回去了。
- 盈亏比:平均盈利 / 平均亏损。这个比胜率重要得多。
- 信号频率:一天出几次信号?太频繁了手续费高,太少了赚不到钱。
- 稳定性:在不同市场环境下表现是否一致?
- 延迟:从信号产生到执行,需要多少时间?
避坑指南:我曾经写过一个信号,回测胜率65%,盈亏比2:1,看起来完美。结果实盘第一天就亏了5%。后来发现,信号在回测时用了未来数据——它偷偷看了明天的收盘价。这种错误,新手最容易犯。
1.6 一个完整的信号示例
说了这么多,来点实际的。下面是一个完整的信号生成代码:
import pandas as pd
import numpy as np
def generate_signal(df, short_window=20, long_window=50):
"""
双均线交叉信号生成器
参数:
df: DataFrame,必须包含'close'列
short_window: 短期均线窗口
long_window: 长期均线窗口
返回:
df: 包含信号列的DataFrame
"""
# 计算均线
df['ma_short'] = df['close'].rolling(window=short_window).mean()
df['ma_long'] = df['close'].rolling(window=long_window).mean()
# 生成信号
# 1: 买入, -1: 卖出, 0: 持仓
df['signal'] = 0
# 金叉买入
buy_condition = (df['ma_short'] > df['ma_long']) & \
(df['ma_short'].shift(1) <= df['ma_long'].shift(1))
df.loc[buy_condition, 'signal'] = 1
# 死叉卖出
sell_condition = (df['ma_short'] < df['ma_long']) & \
(df['ma_short'].shift(1) >= df['ma_long'].shift(1))
df.loc[sell_condition, 'signal'] = -1
return df
# 使用示例
# df = pd.read_csv('data.csv')
# result = generate_signal(df)
# print(result[result['signal'] != 0][['close', 'signal']])
这个代码看着简单吧?但就是这种简单的信号,在实盘里跑了好几年,收益稳稳的。为什么?因为它逻辑清晰,没有过度优化。
1.7 信号开发的常见误区
最后,我总结几个新手最容易踩的坑:
- 过度拟合:为了回测好看,加了十几个参数。结果换个时间段就废了。
- 忽略交易成本:信号频率太高,手续费吃掉所有利润。
- 未来函数:不小心用了未来的数据,回测结果全是假的。
- 幸存者偏差:只测试了上涨行情,没考虑下跌怎么办。
我的经验:写信号的时候,先问自己三个问题:
- 这个信号背后的逻辑是什么?能说清楚吗?
- 如果市场反转,这个信号会怎么表现?
- 我敢不敢拿真金白银去跑?
如果三个问题都能回答,那这个信号就值得继续往下做。
好了,关于信号的基础知识就讲到这里。记住一句话:好的信号,简单、稳定、可解释。别整那些花里胡哨的,先把基础打牢。