Auf GitHub ansehen

Easy Robot Strategy

Overview

Easy Robot is a momentum-following Expert Advisor that trades once per completed hourly candle. When the previous candle closes bullish the strategy opens a new long position; when it closes bearish it opens a short. Only one position can be active at any time, fully mirroring the original MetaTrader 4 logic.

Trade Rules

  1. Subscribe to the hourly candle type selected by the CandleType parameter (defaults to H1).
  2. Once a candle is finished, compare its close with the open:
    • Close > Open: send a market buy order if no position is open.
    • Close < Open: send a market sell order if flat.
  3. The position size uses the strategy Volume property, exactly like the MQL version that relied on CheckVolumeValue with a default of 0.01 lots.
  4. Stop-loss and take-profit levels rely on an Average True Range indicator with period AtrPeriod (default 14):
    • Stop distance = ATR * StopFactor.
    • Take distance = ATR * TakeFactor.
    • Both distances are normalised by the minimal tick/pip distance so protective orders are never placed closer than the broker allows.
  5. Protective orders are registered immediately after the market order through SetStopLoss and SetTakeProfit, providing the same behaviour as OrderSend with sl and tp parameters.
  6. Optional trailing is activated when UseTrailingStop is true. After the trade accumulates TrailingStartPips profit (MetaTrader pips, i.e. points adjusted for 3/5 decimal quotes), the stop is moved closer by TrailingStepPips and is pushed further only when new profit extremes are reached. Trailing respects the broker’s minimal stop distance to avoid invalid modifications.
  7. Quotes for stop calculations use the best bid/ask when available, falling back to the last price or candle close, matching the original Bid/Ask references.

Parameters

Name Default Description
TakeFactor 4.2 ATR multiplier for take-profit distance (maps to TakeFactor input in MQL).
StopFactor 4.9 ATR multiplier for stop-loss distance (maps to StopFactor).
UseTrailingStop true Enables MetaTrader-style trailing (UseTstop).
TrailingStartPips 40 Profit in pips before trailing can start (Tstart).
TrailingStepPips 19 Pip step applied when trailing updates (Tstep).
AtrPeriod 14 ATR calculation period for volatility sizing.
CandleType H1 Candle series used for signals and ATR input.

Notes

  • The strategy resets stored entry and stop prices whenever the position returns to zero, ensuring a clean state for the next signal.
  • Minimal stop distance is estimated via the instrument pip size (or price step when pip size is not available). This reproduces the SC helper from the MQL include file.
  • StartProtection() is called once at start so the platform can manage emergency exits if needed.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Easy Robot strategy: simple EMA + RSI trend following.
/// Buys when close above EMA and RSI above 50.
/// Sells when close below EMA and RSI below 50.
/// </summary>
public class EasyRobotStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _rsiPeriod;
	private bool _wasBullish;
	private bool _hasPrevSignal;

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

	public EasyRobotStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_emaPeriod = Param(nameof(EmaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA period", "Indicators");
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_wasBullish = false;
		_hasPrevSignal = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_hasPrevSignal = false;
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, rsi, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal ema, decimal rsi)
	{
		if (candle.State != CandleStates.Finished) return;
		var close = candle.ClosePrice;
		var isBullish = close > ema && rsi > 50;

		if (_hasPrevSignal && isBullish != _wasBullish)
		{
			if (isBullish && Position <= 0)
				BuyMarket();
			else if (!isBullish && close < ema && rsi < 50 && Position >= 0)
				SellMarket();
		}

		_wasBullish = isBullish;
		_hasPrevSignal = true;
	}
}