在 GitHub 上查看

XRSI Histogram Vol Direct 策略

概览

  • 原始脚本Exp_XRSI_Histogram_Vol_Direct.mq5
  • 移植平台:StockSharp C# 高级策略 API
  • 核心思想:当体积加权的 RSI 直方图斜率翻转时执行反向交易
  • 数据来源:单标的、单时间框架(默认 H4)

该策略复制了原始 MT5 专家顾问的颜色缓冲区逻辑。它计算 RSI 与成交量(或点数)的乘积,并对其进行平滑处理。当平滑后的数值由升转降或由降转升时,策略会相应平仓并根据配置打开新的反向仓位。

指标与计算流程

  1. RSI 指标:使用 RsiPeriod 参数,在所选 K 线级别上计算 RSI,并减去 50,使其围绕零轴波动。
  2. 成交量选择Use Tick Volumetrue 时使用成交笔数,否则使用成交量。
  3. 体积加权震荡器:将居中的 RSI 乘以对应的体积,突出高活跃度时段的信号。
  4. 平滑处理:对震荡器以及原始体积同时应用长度为 SmoothLength 的移动平均(支持 SMAEMASMMAWMA)。只有当两个平滑值都准备好时才会继续执行。
  5. 斜率颜色:比较当前平滑值与上一根的数值,大于为颜色 0(上升),小于为 1(下降),相等时继承上一根的颜色。

参数

名称 默认值 说明
Candle Type H4 订阅的 K 线类型。
RSI Period 14 RSI 的回溯周期。
Smoothing Length 12 平滑 RSI×Volume 的移动平均长度。
Smoothing Method SMA 移动平均类型(SMAEMASMMAWMA)。
Use Tick Volume true 是否使用成交笔数。
Allow Buy Open true 允许开多。
Allow Sell Open true 允许开空。
Allow Buy Close true 允许在反向信号时平多。
Allow Sell Close true 允许在反向信号时平空。

提示:原脚本中的 JJMA、VIDYA 等平滑方式在 StockSharp 中不存在,代码提供了最接近的替代方案。

交易逻辑

  1. 等待两个平滑指标都形成有效数值。
  2. 读取最近两根已完成 K 线的颜色(斜率方向)。
  3. 较旧颜色为 0(上升)
    • 若允许,则平掉当前空头仓位。
    • 若允许开多且最新颜色为 1(下降),则在当前 K 线收盘时开多。
  4. 较旧颜色为 1(下降)
    • 若允许,则平掉当前多头仓位。
    • 若允许开空且最新颜色为 0(上升),则在当前 K 线收盘时开空。

整个流程完全复现了 MT5 专家顾问中“颜色翻转即交易”的思想。

使用建议

  • 根据品种和波动率测试不同的时间框架,以匹配原系统的节奏。
  • 仅依靠斜率方向时,建议结合 StartProtection 设置止损/止盈,增强风险控制。
  • 在调试阶段,可在图表上绘制 RSI 曲线并对比 MT5 指标输出,确认移植正确性。

与 MQL 版本的差异

  • 未移植 TradeAlgorithms.mqh 中的资金管理函数,策略依赖基类的下单量设置。
  • 仅保留 StockSharp 支持的移动平均类型,其他模式退化为 SMA 行为。
  • 不再使用 SignalBarTimeShiftSec,策略直接在已完成的 K 线执行指令。
  • 止损止盈逻辑需用户自行通过 StartProtection 添加。

限制

  • 需要行情源提供成交笔数或成交量,以正确还原震荡器的幅度。
  • 策略本身不绘制原指标的直方图,仅实现交易逻辑和可选的 RSI 显示。
using System;
using System.Collections.Generic;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// XRSI Histogram Vol Direct strategy. Uses RSI 50-line crossover.
/// </summary>
public class XrsiHistogramVolDirectStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;
	private decimal? _prevRsi;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }

	public XrsiHistogramVolDirectStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
		_rsiPeriod = Param(nameof(RsiPeriod), 14).SetGreaterThanZero().SetDisplay("RSI Period", "RSI lookback", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevRsi = null;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevRsi = null;
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(rsi, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsiVal)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!IsFormedAndOnlineAndAllowTrading()) { _prevRsi = rsiVal; return; }
		if (_prevRsi == null) { _prevRsi = rsiVal; return; }
		if (_prevRsi.Value < 45m && rsiVal >= 55m && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (_prevRsi.Value > 55m && rsiVal <= 45m && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
		_prevRsi = rsiVal;
	}
}