在 GitHub 上查看
FiveMinuteRsiCci 策略
FiveMinuteRsiCciStrategy 是 MetaTrader 4 专家顾问 5Mins Rsi Cci EA.mq4 的 StockSharp 版本。原脚本在 5 分钟周期上运行,通过 RSI 阈值突破、开盘价的平滑/指数均线过滤以及快慢 CCI 的正负性来决定方向。C# 移植版沿用相同逻辑,同时利用 StockSharp 的高级 API 完成数据订阅、指标绑定与风控管理。
交易逻辑
- 订阅配置的 K 线类型(默认 5 分钟),实时更新五个指标:RSI、开盘价的平滑移动平均、开盘价的 EMA,以及基于典型价的快/慢 CCI。
- 仅在当前仓位为零且买卖差价低于
MaxSpreadPoints(会换算为价格单位)时评估已收盘的 K 线。
- 多头信号需要满足:
- 平滑均线在 EMA 之上;
- RSI 在上一根与当前 K 线之间向上穿越
BullishRsiLevel;
- 快慢 CCI 均大于零。
- 空头信号为上述条件的反向组合(平滑均线在 EMA 之下、RSI 向下穿越
BearishRsiLevel、快慢 CCI 均小于零)。
- 下单手数复刻 EA 的动态头寸算法:
LotCoefficient × sqrt(Equity / EquityDivisor),并根据交易品种的 VolumeStep、VolumeMin、VolumeMax 进行取整与约束。
- 通过
StartProtection 自动附加止损、止盈与跟踪止损距离,所有距离都会从 MetaTrader 点值换算为绝对价格。
参数
| 参数 |
默认值 |
说明 |
CandleType |
TimeSpan.FromMinutes(5).TimeFrame() |
用于指标与信号评估的 K 线周期。 |
RsiPeriod |
14 |
RSI 计算所使用的周期数。 |
FastSmmaPeriod |
2 |
作用于开盘价的平滑移动平均周期。 |
SlowEmaPeriod |
6 |
作用于开盘价的 EMA 周期。 |
FastCciPeriod |
34 |
基于典型价 (H+L+C)/3 的快 CCI 周期。 |
SlowCciPeriod |
175 |
基于典型价的慢 CCI 周期。 |
BullishRsiLevel |
55 |
RSI 向上突破该值后才允许做多。 |
BearishRsiLevel |
45 |
RSI 向下跌破该值后才允许做空。 |
StopLossPoints |
60 |
止损距离(MetaTrader 点),0 表示关闭。 |
TakeProfitPoints |
0 |
止盈距离(MetaTrader 点),默认关闭以保持原始脚本行为。 |
TrailingStopPoints |
20 |
跟踪止损距离(MetaTrader 点),0 表示关闭。 |
LotCoefficient |
0.01 |
动态手数公式的基础系数。 |
EquityDivisor |
10 |
动态手数公式中平方根的分母 (sqrt(Equity / EquityDivisor))。 |
MaxSpreadPoints |
18 |
允许的最大点差(MetaTrader 点),超出时暂停开仓。 |
说明
- 点差过滤依赖一级行情,若尚未获得最优买/卖价则等待,不会立即开仓。
- 点值换算会自动结合
PriceStep 与报价精度;对于 5/3 位小数的品种会额外乘以 10,以匹配 MetaTrader 的 Point 定义。
- 止损、止盈与跟踪止损全部由 StockSharp 内置保护模块处理,并使用市价方式更新,等效于原 EA 中的
OrderModify 行为。
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Five Minute RSI CCI strategy: RSI momentum with CCI trend confirmation.
/// Buys when RSI above level and CCI positive, sells when RSI below level and CCI negative.
/// </summary>
public class FiveMinuteRsiCciStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<decimal> _bullishLevel;
private readonly StrategyParam<decimal> _bearishLevel;
private bool _wasBullish;
private bool _hasPrevSignal;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public decimal BullishLevel { get => _bullishLevel.Value; set => _bullishLevel.Value = value; }
public decimal BearishLevel { get => _bearishLevel.Value; set => _bearishLevel.Value = value; }
public FiveMinuteRsiCciStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "CCI period", "Indicators");
_bullishLevel = Param(nameof(BullishLevel), 55m)
.SetDisplay("Bullish RSI Level", "RSI above this for buy", "Signals");
_bearishLevel = Param(nameof(BearishLevel), 45m)
.SetDisplay("Bearish RSI Level", "RSI below this for sell", "Signals");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_wasBullish = false;
_hasPrevSignal = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrevSignal = false;
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, cci, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue, decimal cciValue)
{
if (candle.State != CandleStates.Finished) return;
var isBullish = rsiValue > BullishLevel && cciValue > 0;
if (_hasPrevSignal && isBullish != _wasBullish)
{
if (isBullish && Position <= 0)
BuyMarket();
else if (!isBullish && rsiValue < BearishLevel && cciValue < 0 && Position >= 0)
SellMarket();
}
_wasBullish = isBullish;
_hasPrevSignal = true;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import RelativeStrengthIndex, CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class five_minute_rsi_cci_strategy(Strategy):
def __init__(self):
super(five_minute_rsi_cci_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30)))
self._rsi_period = self.Param("RsiPeriod", 14)
self._cci_period = self.Param("CciPeriod", 14)
self._bullish_level = self.Param("BullishLevel", 55.0)
self._bearish_level = self.Param("BearishLevel", 45.0)
self._was_bullish = False
self._has_prev_signal = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsi_period.Value = value
@property
def CciPeriod(self):
return self._cci_period.Value
@CciPeriod.setter
def CciPeriod(self, value):
self._cci_period.Value = value
@property
def BullishLevel(self):
return self._bullish_level.Value
@BullishLevel.setter
def BullishLevel(self, value):
self._bullish_level.Value = value
@property
def BearishLevel(self):
return self._bearish_level.Value
@BearishLevel.setter
def BearishLevel(self, value):
self._bearish_level.Value = value
def OnReseted(self):
super(five_minute_rsi_cci_strategy, self).OnReseted()
self._was_bullish = False
self._has_prev_signal = False
def OnStarted2(self, time):
super(five_minute_rsi_cci_strategy, self).OnStarted2(time)
self._has_prev_signal = False
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
cci = CommodityChannelIndex()
cci.Length = self.CciPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, cci, self._process_candle).Start()
def _process_candle(self, candle, rsi_value, cci_value):
if candle.State != CandleStates.Finished:
return
is_bullish = float(rsi_value) > self.BullishLevel and float(cci_value) > 0
if self._has_prev_signal and is_bullish != self._was_bullish:
if is_bullish and self.Position <= 0:
self.BuyMarket()
elif not is_bullish and float(rsi_value) < self.BearishLevel and float(cci_value) < 0 and self.Position >= 0:
self.SellMarket()
self._was_bullish = is_bullish
self._has_prev_signal = True
def CreateClone(self):
return five_minute_rsi_cci_strategy()