GitHub で見る

Robust EA Template Strategy

Strategy implementing the Robust EA Template from MQL. It uses Commodity Channel Index (CCI) and Relative Strength Index (RSI) to generate entry signals and applies fixed take profit and stop loss.

Logic

  • Buy when CCI is in -200..-150 or -100..-50 and RSI is between 0 and 25.
  • Sell when CCI is between 50 and 150 and RSI is between 80 and 100.
  • Stop loss and take profit are defined in pips and converted to price points.

Parameters

  • Candle Type – candle data series.
  • CCI Period – period of the CCI indicator.
  • RSI Period – period of the RSI indicator.
  • Take Profit (pips) – distance for profit target.
  • Stop Loss (pips) – distance for stop loss.
  • Volume – order volume.
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>
/// Strategy using CCI and RSI indicators to generate trading signals.
/// </summary>
public class RobustEaTemplateStrategy : Strategy
{
	private readonly StrategyParam<int> _cciPeriod;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _takeProfitPct;
	private readonly StrategyParam<decimal> _stopLossPct;
	private readonly StrategyParam<DataType> _candleType;

	public int CciPeriod
	{
		get => _cciPeriod.Value;
		set => _cciPeriod.Value = value;
	}

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

	public decimal TakeProfitPct
	{
		get => _takeProfitPct.Value;
		set => _takeProfitPct.Value = value;
	}

	public decimal StopLossPct
	{
		get => _stopLossPct.Value;
		set => _stopLossPct.Value = value;
	}

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

	public RobustEaTemplateStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(8).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles", "General");

		_cciPeriod = Param(nameof(CciPeriod), 14)
			.SetDisplay("CCI Period", "Commodity Channel Index period", "Indicators");

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetDisplay("RSI Period", "Relative Strength Index period", "Indicators");

		_takeProfitPct = Param(nameof(TakeProfitPct), 3m)
			.SetDisplay("Take Profit %", "Take profit percentage", "Risk");

		_stopLossPct = Param(nameof(StopLossPct), 2m)
			.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk");
	}

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

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var cci = new CommodityChannelIndex { Length = CciPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription.BindEx(cci, rsi, (candle, cciVal, rsiVal) =>
		{
			if (candle.State != CandleStates.Finished)
				return;

			if (!cciVal.IsFormed || !rsiVal.IsFormed)
				return;

			if (!IsFormedAndOnlineAndAllowTrading())
				return;

			var cciValue = cciVal.ToDecimal();
			var rsiValue = rsiVal.ToDecimal();

			// Wider signal conditions
			var longSignal = cciValue < -50m && rsiValue < 40m;
			var shortSignal = cciValue > 50m && rsiValue > 60m;

			if (longSignal && Position <= 0)
			{
				if (Position < 0) BuyMarket();
				BuyMarket();
			}
			else if (shortSignal && Position >= 0)
			{
				if (Position > 0) SellMarket();
				SellMarket();
			}
		}).Start();

		StartProtection(
			takeProfit: new Unit(TakeProfitPct, UnitTypes.Percent),
			stopLoss: new Unit(StopLossPct, UnitTypes.Percent),
			useMarketOrders: true);

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, rsi);
			DrawOwnTrades(area);
		}
	}
}