PulseForce Dual Moving Average(双均线策略)算法解析

1. 概述

Dual Moving Average(双均线策略) 是最经典、最基础的趋势跟随策略之一。
它只依赖两条简单移动平均线(短期均线 ma_fast 与长期均线 ma_slow)之间的交叉关系:

  • 短均线从下往上突破长均线 → 黄金交叉(Golden Cross) → 产生买入信号
  • 短均线从上往下跌破长均线 → 死亡交叉(Death Cross) → 产生卖出信号

在 PulseForce 中,dual_moving_avg 策略是一个 极简但非常标准化 的趋势策略实现:

  • 使用 1 分钟 K 线(timeframe = "1m"
  • 仅使用 双均线 + 成交量 > 0 作为信号条件
  • 退出采用 “卖出信号 + 日级 SL/TP + 强制 SL/TP” 的统一风控框架
  • 支持 超参优化(HyperOpt),可搜索 ma_fast / ma_slow / daily_* / force_* 等参数
  • 策略参数全部通过 PulseForce App 的可视化界面进行配置

如果说 ma_crossover 是带有更多趋势过滤与波动调节的“加强版”,那么 dual_moving_avg 就是 更纯粹的双均线交叉版本,结构简洁、可解释性极强。


2. 策略起源与定位

双均线交叉策略的源头可以追溯到早期技术分析时代,随着计算机与程序化交易的发展,它几乎成为所有趋势策略中的“Hello World”:

  • 早期 CTA / 趋势基金
    大量使用均线交叉作为趋势信号核心模块。
  • 现代量化体系
    双均线依然是趋势跟随的基石,被嵌入到多因子模型、CTA 策略、趋势过滤器等模块中。
  • 策略教学与研究
    无论是入门教学还是研究讨论,双均线几乎是趋势策略的默认案例。

在 PulseForce 中,dual_moving_avg 的定位是:

“结构极其干净的趋势策略基线(baseline)”
用来对比更复杂的趋势策略(如 MA Crossover、Momentum、MACD Trend 等)的收益、回撤与交易风格。


3. 策略试图解决的问题

双均线策略本质上在解决三个问题:

  1. 如何简单直接地识别趋势方向变化?
    → 用短均线相对长均线的位置及交叉关系,作为趋势“多/空”判定。

  2. 如何避免过度依赖单根 K 线或局部形态?
    → 均线是价格的平滑,减少高频噪音、单根异常 K 线的影响。

  3. 如何构建一个“可调节”的趋势策略?
    → 通过调节 ma_fast / ma_slow 两个参数,可以轻松获得不同风格(更快 / 更稳)的策略版本。


4. 核心指标与信号逻辑

4.1 指标计算

策略中使用的是 简单移动平均线(SMA)

1
2
3
4
5
6
f = int(self._val(self.ma_fast))
s = int(self._val(self.ma_slow))

# 简单均线
df["ma_fast"] = ta.SMA(df, timeperiod=f)
df["ma_slow"] = ta.SMA(df, timeperiod=s)

所需的基础数据:

  • close / open / high / low:全部做 ffill 清洗
  • volume:填充为 0,避免缺失数据带来的错误信号

4.2 买入逻辑:黄金交叉(Golden Cross)

1
2
3
4
5
6
7
8
9
10
def populate_buy_trend(self, dataframe: DataFrame, metadata: Dict) -> DataFrame:
df = dataframe.copy()
cond = (
(df["ma_fast"].shift(1) < df["ma_slow"].shift(1)) & # 前一根短均线在长均线下方
(df["ma_fast"] > df["ma_slow"]) & # 当前短均线上穿长均线 → 黄金交叉
(df["volume"] > 0) # 必须有成交量
)
df.loc[:, "buy"] = 0
df.loc[cond, "buy"] = 1
return df

含义:

  • 必须是 从“短均线在下”到“短均线在上” 的状态变化,而不是简单的“大于”判断 → 避免重复触发。
  • 仅使用最纯粹的金叉定义,不叠加 RSI、突破、波动率等复杂条件 → 非常适合作为基准策略。
  • volume > 0 用于排除停牌或异常数据。

4.3 卖出信号层:死亡交叉(Death Cross)

策略通过静态方法 _has_sell_signal 检查是否出现“死亡交叉”:

1
2
3
4
5
6
7
8
9
@staticmethod
def _has_sell_signal(prev: Optional[pd.Series], curr: Optional[pd.Series]) -> bool:
try:
if prev is None or curr is None:
return False
return (float(prev.get("ma_fast", np.nan)) > float(prev.get("ma_slow", np.nan))) and \
(float(curr.get("ma_fast", np.nan)) < float(curr.get("ma_slow", np.nan)))
except Exception:
return False

条件:

  • 前一根:ma_fast > ma_slow(短期趋势仍在上方)
  • 当前:ma_fast < ma_slow(短期趋势向下跌破长期均线)

当这两个条件同时满足,即认为出现 “由多转空”的死亡交叉,但此时并不直接卖出,而是交由 custom_exit 结合 SL/TP 判定是否退出。


5. 统一的退出逻辑:卖出信号 + SL/TP

custom_exit 中,dual_moving_avg 完整实现了 PulseForce 的标准风控流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
def custom_exit(
self,
pair: str,
trade: Trade,
current_time: datetime,
current_rate: float,
current_profit: float,
**kwargs,
):
# ① 硬阈值优先(Force SL/TP)
if current_profit <= -self.force_stop_loss.value:
return "hard_sl"
if current_profit >= self.force_take_profit.value:
return "hard_tp"

# ② 获取 prev/curr 行并检查是否出现死亡交叉
df = self._get_analyzed_df(pair)
if df is None or df.empty:
return None
prev, curr = self._get_prev_curr_rows(df, current_time)
if not self._has_sell_signal(prev, curr):
return None

# ③ 仅在出现“卖出信号层”后,才按照日级 SL/TP 判定是否真正退出
th = self._pick_trend_thresholds()
sl = th["sl"]
tp = th["tp"]
if current_profit <= -sl:
return "sl_signal"
if current_profit >= tp:
return "tp_signal"
return None

可以总结为三层保护:

  1. Force SL/TP(硬阈值)

    • 无视任何信号,只要浮亏/浮盈达到硬阈值就立即平仓。
    • 用于防止极端行情(如闪崩/暴拉)带来不可控风险。
  2. 卖出信号层(死亡交叉)

    • 若没有出现死亡交叉,则即使价格短期波动,也不会因为 daily SL/TP 而离场。
    • 体现“趋势还在,就尽量拿着”的思想。
  3. 日级 SL/TP(基于趋势信号的退出)

    • 只有在出现死亡交叉后,才会启用 daily_stop_loss / daily_take_profit 做退出判断。
    • 比“只看盈亏比”更符合趋势策略逻辑。

6. PulseForce 参数配置与超参优化

PulseForce App(Apple AppStore & Google Play可下载)针对量化任务、量化回测以及超参优化,提供了可视化的配置界面,使策略可以完全参数化。

回测参数配置界面:

超参优化参数配置界面:

以下参数 可根据不同股票/加密货币自动搜索最优组合

6.1 Basic Parameters(基础参数)

这组参数决定 趋势信号本身的形态

参数 Key 名称 说明 可优化 建议初始搜索范围(otp_init_min ~ otp_init_max)
ma_fast Fast MA Period 短期均线周期,数值越小越敏感 8 ~ 25
ma_slow Slow MA Period 长期均线周期,数值越大越平滑 40 ~ 90

与代码中的 HyperOpt 空间对应:

1
2
ma_fast = IntParameter(3, 100, default=10, space="buy", optimize=True)
ma_slow = IntParameter(5, 200, default=30, space="buy", optimize=True)

你可以通过 HyperOpt 让 PulseForce 为每只股票自动寻找最合适的一组快/慢均线周期。


6.2 Capital Allocation(资金管理)

资金管理部分与其他策略保持一致,用于配置最大资金占用与趋势相关仓位比例,目前默认不参与超参优化,但可在 UI 中手动调整:

参数 Key 说明
max_funds_allowed_using 使用在该策略上的最大资金上限
allowable_funds_neutral 市场中性状态下使用的资金比例
allowable_funds_uptrend 上升趋势中使用的资金比例
allowable_funds_downtrend 下降趋势中使用的资金比例

6.3 Stop Loss(止损参数)

止损部分支持 HyperOpt 优化:

参数 Key 名称 含义 可优化 建议范围(配置 → 策略)
force_stop_loss Force Stop-Loss Ratio 强制止损阈值 0.005 ~ 0.30
daily_stop_loss Daily Stop-Loss Ratio 日级止损,只有在出现死亡交叉时才会触发 0.01 ~ 0.3

6.4 Take Profit(止盈参数)

止盈部分也完全支持 HyperOpt:

参数 Key 名称 含义 可优化 建议范围
force_take_profit Force Take-Profit Ratio 强制止盈阈值 0.005 ~ 0.30
daily_take_profit Daily Take-Profit Ratio 日级止盈,仅在出现死亡交叉时生效 0.01 ~ 0.3

结合强制止盈+日级止盈,可以实现多层次的收益保护。


7. Dual MA 策略适用场景

7.1 最适合的场景

  • 明显具有趋势特性的标的:
    如美股热门成长股、趋势性 ETF、部分大盘指数、波动较大的加密货币。
  • 希望使用 简单规则 + 简洁信号 的用户:
    不依赖多指标,不担心过度拟合。
  • 希望做 策略基线(baseline) 对比研究:
    例如对比 MA Crossover、MACD、Momentum 等策略的超额部分。

7.2 不适合的场景

  • 长期横盘、频繁来回震荡的标的
  • 极端高频噪音环境(如超短线级别的随机波动)
  • 对“入场非常精细”有强需求的应用(双均线更偏趋势中段)

8. 策略优势与不足

优势

  • 结构非常简单、透明,可解释性极强
  • 参数数量少,超参优化更稳定,不易过拟合
  • 非常适合用作:
    • 策略基线(Benchmark Strategy)
    • 教学与入门
    • 与更复杂策略比较优劣
  • 完全遵循 PulseForce 风控框架:
    • 硬阈值 SL/TP
    • 日级 SL/TP
    • 统一的 custom_exit 流程

不足

  • 不考虑 RSI、成交量、波动率等因素,对震荡市较为敏感,容易产生“假信号”
  • 相比更复杂的趋势策略(如带 AI 过滤的 Momentum),可能在某些标的上的性能略逊一筹
  • 无日级趋势过滤,在极端噪音环境下可能需要与其他过滤器配合使用

9. 总结

dual_moving_avg 是 PulseForce 中 最纯粹、最标准的双均线交叉策略实现

  • 短期均线 / 长期均线的黄金交叉 / 死亡交叉 作为唯一趋势信号
  • 使用 硬阈值 + 日级止损/止盈 统一风控
  • 支持对 ma_fast / ma_slow / daily_* / force_* 进行 HyperOpt 超参搜索
  • 通过 UI 配置 + 回测 + 超参优化,用户可以快速构建属于自己的“风格双均线策略”

它非常适合作为:

  • 你的第一套趋势策略
  • 与 Momentum / MA Crossover / MACD Trend 等策略做效果对比的基线
  • 在 PulseForce 中学习“策略-参数-风控-回测-超参优化”完整链路的示例策略。

想了解更多策略介绍与最新功能,请访问:
👉 PulseForce 官网: https://www.hiforce.ai