第三节:技术指标计算——从公式到实战的深度解析
技术指标这东西,说白了就是价格和成交量的数学变形。很多新手觉得指标越复杂越厉害,其实不然。我见过太多人把十几个指标堆在一起,结果信号互相打架,根本没法交易。今天咱们就把几个核心指标掰开揉碎,看看它们到底在算什么,以及怎么用才不会掉坑里。
3.1 移动平均线(MA)——最朴素也最实用
移动平均线是所有指标的基础。它的计算逻辑很简单:把过去N天的收盘价加起来除以N。但就是这个简单的公式,在不同场景下差别很大。
核心要点:MA的本质是平滑价格波动,过滤掉短期噪音。但平滑程度越高,滞后性越强。
我个人习惯用三种均线组合:
- 短期(5日/10日):捕捉短线趋势,适合日内或波段交易
- 中期(20日/30日):判断中期方向,我常用它做趋势过滤
- 长期(60日/120日):牛熊分界线,大资金参考线
这里有个坑要注意:均线的参数不是越大越好。我在项目中遇到过有人用200日均线做螺纹钢的短线交易,结果信号滞后了整整一周,亏得挺惨。你想想看,不同品种的波动周期不一样,参数得跟着调整。
// C++ 实现简单移动平均线
vector<double> calcMA(const vector<double>& prices, int period) {
vector<double> ma(prices.size(), 0.0);
double sum = 0.0;
for (int i = 0; i < prices.size(); i++) {
sum += prices[i];
if (i >= period - 1) {
ma[i] = sum / period;
sum -= prices[i - period + 1];
}
}
return ma;
}
3.2 MACD——趋势跟随的利器
MACD其实是均线的衍生品。它由三部分组成:DIF(快线)、DEA(慢线)、柱状图。计算过程分三步:
- 计算快线(12日EMA)和慢线(26日EMA)
- DIF = 快线 - 慢线
- DEA = DIF的9日EMA,柱状图 = 2 × (DIF - DEA)
嗯,这里要注意:MACD的默认参数(12,26,9)是股票市场传下来的,用在期货上不一定合适。我记得有一次做原油期货,波动特别剧烈,用默认参数信号频繁得没法看。后来我把参数调成了(8,21,5),效果好了很多。
实战技巧:MACD的金叉死叉信号在震荡行情中准确率很低。我建议配合趋势线或布林带一起用,能过滤掉不少假信号。
3.3 RSI——超买超卖的判断
RSI的计算公式看着复杂,其实核心就是比较N天内上涨和下跌的幅度。公式是:RSI = 100 - 100 / (1 + RS),其中RS = 平均上涨幅度 / 平均下跌幅度。
为什么RSI超过70算超买,低于30算超卖?说白了,这是统计规律。但我在实战中发现,强趋势行情里RSI可以长时间维持在80以上或20以下。如果你死板地按70/30来操作,很容易被趋势甩下车。
避坑指南:我曾经在焦炭的暴涨行情中,看到RSI到80就做空,结果连续被打了三次止损。后来我学乖了:在强趋势中,把超买超卖阈值调到85/15,或者干脆用RSI的背离信号。
3.4 布林带——波动率的可视化
布林带由三条线组成:中轨(20日均线)、上轨(中轨 + 2倍标准差)、下轨(中轨 - 2倍标准差)。它的核心思想是:价格在正负2个标准差范围内波动的概率约为95%。
我个人觉得布林带最有用的不是上下轨的支撑压力,而是带宽的变化。带宽收窄往往意味着变盘在即。我在做股指期货时,经常用这个特征来提前布局突破行情。
// 布林带计算
struct BollingerBands {
vector<double> upper;
vector<double> middle;
vector<double> lower;
};
BollingerBands calcBollinger(const vector<double>& prices, int period, double multiplier) {
BollingerBands bb;
vector<double> ma = calcMA(prices, period);
bb.middle = ma;
for (int i = 0; i < prices.size(); i++) {
if (i < period - 1) {
bb.upper.push_back(0);
bb.lower.push_back(0);
continue;
}
double sumSq = 0;
for (int j = i - period + 1; j <= i; j++) {
sumSq += pow(prices[j] - ma[i], 2);
}
double std = sqrt(sumSq / period);
bb.upper.push_back(ma[i] + multiplier * std);
bb.lower.push_back(ma[i] - multiplier * std);
}
return bb;
}
3.5 ATR——真实波动幅度
ATR(平均真实波幅)是用来衡量市场波动程度的。它的计算分两步:先算TR(真实波幅),再取TR的N日平均值。TR取三个值的最大值:
- 当日最高价 - 当日最低价
- 当日最高价 - 前一日收盘价的绝对值
- 当日最低价 - 前一日收盘价的绝对值
ATR最大的用处是设置止损和仓位管理。我习惯用2倍ATR作为止损距离,这样既不会被正常波动扫出去,又能控制最大亏损。举个例子,如果螺纹钢的ATR是30点,那我的止损就设在60点。
3.6 自定义指标实现
有时候现成的指标不够用,就得自己写。我做过一个叫「动量加速度」的指标,其实就是把价格的一阶导数和二阶导数结合起来。实现起来也不复杂:
// 自定义指标:动量加速度
struct MomentumAcceleration {
vector<double> momentum; // 动量
vector<double> acceleration; // 加速度
};
MomentumAcceleration calcMomentumAccel(const vector<double>& prices, int period) {
MomentumAcceleration ma;
for (int i = period; i < prices.size(); i++) {
double mom = (prices[i] - prices[i - period]) / prices[i - period];
ma.momentum.push_back(mom);
if (ma.momentum.size() >= 2) {
double accel = ma.momentum.back() - ma.momentum[ma.momentum.size() - 2];
ma.acceleration.push_back(accel);
}
}
return ma;
}
自定义指标的原则:逻辑要清晰,参数要少,最好不超过3个。参数越多,过拟合的风险越大。我一般先用逻辑推导出公式,再用历史数据验证,最后做参数敏感性分析。
3.7 指标参数优化的陷阱
这是今天最重要的部分。很多人在参数优化上栽过大跟头,我也不例外。常见的陷阱有:
| 陷阱类型 | 表现 | 后果 |
|---|---|---|
| 过拟合 | 参数在历史数据上表现完美,实盘一塌糊涂 | 资金曲线大幅回撤 |
| 数据窥探 | 反复用同一段数据调整参数 | 统计显著性丧失 |
| 未来函数 | 优化时用到了未来的数据 | 策略在实盘中失效 |
| 参数孤岛 | 最优参数附近性能急剧下降 | 参数稍微偏移就亏损 |
我曾经犯过一个典型的错误:用过去3年的数据优化MACD参数,找到了一个「完美」的参数组合。结果实盘第一个月就亏了8%。后来复盘发现,那个参数在优化集上表现好,但在验证集上完全不行。这就是典型的过拟合。
避坑指南:参数优化一定要做样本外测试。我现在的流程是:把数据分成三份——训练集(60%)、验证集(20%)、测试集(20%)。在训练集上优化参数,验证集上筛选,最后在测试集上做最终评估。只有三个数据集都表现稳定的参数,才敢上实盘。
另外,参数优化时别只看收益率。夏普比率、最大回撤、胜率、盈亏比这些指标都得看。我见过有人优化出一个年化200%的参数,但最大回撤60%,这种策略你敢用吗?
最后说一句:技术指标只是工具,不是圣杯。真正赚钱的交易员,靠的是对市场的理解、资金管理和纪律执行。指标用得再好,如果管不住手,照样亏钱。嗯,这话可能不好听,但确实是实话。