在 GitHub 上查看

RSI Sign 策略

该策略将 MQL5 的 iRSISign 智能交易系统转换为 StockSharp 的高级 API。它结合 RSI 和 ATR 指标来产生交易信号。

系统只处理选定时间框架的已完成K线。当 RSI 从下方穿越 DownLevel 时,策略开多或平空;当 RSI 从上方跌破 UpLevel 时,策略开空或平多。ATR 仅用于提供背景信息,类似原始指标使用 ATR 偏移显示信号箭头。

细节

  • 入场条件
    • 做多:先前 RSI 低于 DownLevel,当前 RSI 上穿该水平。
    • 做空:先前 RSI 高于 UpLevel,当前 RSI 跌破该水平。
  • 方向:支持多空,并可分别启用。
  • 出场条件
    • 相反信号在对应的关闭标志开启时平仓。
  • 止损:未实现,如有需要可外部添加。
  • 默认参数
    • RsiPeriod = 14
    • AtrPeriod = 14
    • UpLevel = 70
    • DownLevel = 30
    • CandleType = 1小时K线
  • 过滤器
    • 类别:动量
    • 方向:双向
    • 指标:RSI、ATR
    • 止损:无
    • 复杂度:基础
    • 时间框架:可变
    • 季节性:无
    • 神经网络:无
    • 背离:无
    • 风险等级:中等

参数

名称 说明
RsiPeriod RSI 周期
AtrPeriod ATR 周期
UpLevel RSI 上限阈值,触发卖出信号
DownLevel RSI 下限阈值,触发买入信号
CandleType 计算所用的K线时间框架
BuyOpen 允许开多
SellOpen 允许开空
BuyClose 在反向信号时允许平多
SellClose 在反向信号时允许平空

该策略主要用于演示如何将简单的 MQL5 逻辑迁移到 StockSharp 策略框架。

using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// RSI based signal strategy.
/// Opens long when RSI crosses above the down level.
/// Opens short when RSI crosses below the up level.
/// </summary>
public class RsiSignStrategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _upLevel;
	private readonly StrategyParam<decimal> _downLevel;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _previousRsi;

	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public decimal UpLevel { get => _upLevel.Value; set => _upLevel.Value = value; }
	public decimal DownLevel { get => _downLevel.Value; set => _downLevel.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public RsiSignStrategy()
	{
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "Length of RSI indicator", "Indicator");

		_upLevel = Param(nameof(UpLevel), 70m)
			.SetDisplay("RSI Upper Level", "Sell when RSI falls below this value", "Indicator");

		_downLevel = Param(nameof(DownLevel), 30m)
			.SetDisplay("RSI Lower Level", "Buy when RSI rises above this value", "Indicator");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe used for indicator calculations", "General");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

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

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_previousRsi = 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);
			DrawIndicator(area, rsi);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var prevRsi = _previousRsi;
		_previousRsi = rsiValue;

		if (prevRsi is null)
			return;

		// RSI crosses above lower level -> buy signal
		if (prevRsi <= DownLevel && rsiValue > DownLevel && Position <= 0)
			BuyMarket();
		// RSI crosses below upper level -> sell signal
		else if (prevRsi >= UpLevel && rsiValue < UpLevel && Position >= 0)
			SellMarket();
	}
}