The ValidateMe strategy ports the basic validation framework from the original MQL4 expert advisor. The logic focuses on checking the availability of funds, verifying that stop-loss and take-profit distances respect exchange constraints, and then firing a single market order in the chosen direction. The strategy continuously monitors trade execution events and opens a new position only when no positions or active orders are present.
Trading Logic
The strategy subscribes to tick data of the configured security.
When the strategy is online, formed, and trading is allowed, it verifies that no open position and no active orders are present.
It then sends a market order in the configured direction (buy or sell) using the defined lot size.
A protective module immediately attaches take-profit and stop-loss orders calculated from pip distances, ensuring compliance with broker stop levels (adjusted for fractional pricing).
Once the position closes, the strategy waits for the next tick and repeats the validation before sending a new order.
Parameters
Parameter
Description
Take Profit (pips)
Distance from the entry price to the take-profit in pips. Must be greater than zero.
Stop Loss (pips)
Distance from the entry price to the stop-loss in pips. Must be greater than zero.
Lots
Trade volume in lots used for every market order.
Direction
Direction of the market order (Buy or Sell).
Risk Management
The strategy uses StartProtection with absolute offsets to register both take-profit and stop-loss orders.
Pip size is calculated from the security price step and decimal precision to mimic MetaTrader behavior (5- and 3-digit symbols use a tenfold point size).
The strategy fires new orders only if no existing orders are active, avoiding order stacking.
Usage Notes
Attach the strategy to a security and set the desired volume and direction.
Configure the take-profit and stop-loss distances in pips according to broker requirements.
The strategy does not rely on indicators and is intended as a validation framework rather than a full trading system.
Portfolio risk control (e.g., max drawdown) can be combined externally if required.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// ValidateMe strategy: RSI crossover at oversold/overbought levels.
/// Buys when RSI crosses above 30, sells when RSI crosses below 70.
/// </summary>
public class ValidateMeStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _period;
private decimal _prevRsi;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int Period { get => _period.Value; set => _period.Value = value; }
public ValidateMeStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_period = Param(nameof(Period), 14)
.SetGreaterThanZero()
.SetDisplay("Period", "RSI period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevRsi = 0;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var rsi = new RelativeStrengthIndex { Length = Period };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished) return;
if (_hasPrev)
{
if (_prevRsi < 30 && rsiValue >= 30 && Position <= 0)
BuyMarket();
else if (_prevRsi > 70 && rsiValue <= 70 && Position >= 0)
SellMarket();
}
_prevRsi = rsiValue;
_hasPrev = 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
from StockSharp.Algo.Strategies import Strategy
class validate_me_strategy(Strategy):
def __init__(self):
super(validate_me_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._period = self.Param("Period", 14)
self._prev_rsi = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def Period(self):
return self._period.Value
@Period.setter
def Period(self, value):
self._period.Value = value
def OnReseted(self):
super(validate_me_strategy, self).OnReseted()
self._prev_rsi = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(validate_me_strategy, self).OnStarted2(time)
self._has_prev = False
rsi = RelativeStrengthIndex()
rsi.Length = self.Period
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, self._process_candle).Start()
def _process_candle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
rsi_val = float(rsi_value)
if self._has_prev:
if self._prev_rsi < 30 and rsi_val >= 30 and self.Position <= 0:
self.BuyMarket()
elif self._prev_rsi > 70 and rsi_val <= 70 and self.Position >= 0:
self.SellMarket()
self._prev_rsi = rsi_val
self._has_prev = True
def CreateClone(self):
return validate_me_strategy()