The Maybeawo222 strategy replicates the MetaTrader expert advisor "maybeawo222" using StockSharp's high-level API. It trades a single instrument with a simple moving average (SMA) crossover on the previous candle and limits activity to a configurable time window. The conversion keeps the staged breakeven management that attempts to lock in profits as soon as the price advances by predefined distances.
Trading Logic
The strategy subscribes to the main candle series selected through CandleType and calculates a simple moving average with the period specified by MovingPeriod.
At the close of every candle the SMA value is shifted by MovingShift bars before being used in the decision. This reproduces the original iMA call with a shift parameter.
Trading signals are only evaluated when the closing time of the finished candle falls inside the [StartHour, EndHour) range. Outside of that window no new orders are created, although open positions continue to be managed.
A buy signal appears when the previous candle (the one that just closed) opens below the shifted SMA and closes above it. A sell signal requires the opposite crossover. The strategy reverses existing positions if necessary so only one direction remains open.
On every finished candle the engine checks the high/low extremes to detect stop-loss or take-profit hits. Whenever either level is touched, the corresponding market exit is triggered immediately.
The position also activates up to two staged breakeven adjustments. Once the floating profit exceeds BreakevenPips1, the stop moves closer to the entry according to DesiredBreakevenDistancePips1. A second stage repeats the process with BreakevenPips2 and DesiredBreakevenDistancePips2.
Risk Management
Initial stop-loss and take-profit distances are configured in pips. The conversion uses the instrument PriceStep and applies the conventional MetaTrader factor of 10 for three- and five-digit quotes.
Breakeven levels are only applied once per position side. Each new entry resets the flags, allowing the stop to trail twice during the lifetime of the trade.
Position exits use market orders so the engine can close trades even if the stop or target levels are not available on the broker side.
Parameters
Name
Default
Range / Notes
Description
MovingPeriod
14
Positive integer
SMA length used for the crossover check.
MovingShift
0
0 – 10 (suggested)
Number of completed candles to shift the SMA value backwards.
StopLossPips
100
0 disables
Distance from the entry price to the protective stop-loss, measured in pips.
TakeProfitPips
800
0 disables
Distance from the entry to the take-profit level, measured in pips.
BreakevenPips1
180
0 disables
Profit threshold (in pips) that triggers the first breakeven adjustment.
DesiredBreakevenDistancePips1
60
Any non-negative
New stop distance from the entry after breakeven stage 1 fires.
BreakevenPips2
500
0 disables
Profit threshold (in pips) that triggers the second breakeven adjustment.
DesiredBreakevenDistancePips2
350
Any non-negative
New stop distance from the entry after breakeven stage 2 fires.
StartHour
3
0 – 23
Inclusive start hour of the trading session, based on exchange time.
EndHour
22
0 – 23
Exclusive end hour of the trading session.
OrderVolume
0.5
Greater than 0
Volume sent with every market order before position netting.
CandleType
H1
Any candle data type
Candle series used for generating signals and calculating the SMA.
Notes for Use
Ensure the connected security provides a valid PriceStep; otherwise the pip conversion falls back to 1. Adjust the pip-related parameters accordingly if your instrument quotes in large ticks.
The strategy expects a single-symbol setup. Add it to a scheme with the desired instrument before starting the strategy.
For live trading consider enabling slippage allowances or protective stop orders through broker-specific extensions if market exits are not sufficient.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Moving average crossover strategy with price crossing the SMA line.
/// Buys when candle opens below MA and closes above it, sells vice versa.
/// </summary>
public class Maybeawo222Strategy : Strategy
{
private readonly StrategyParam<int> _movingPeriod;
private readonly StrategyParam<DataType> _candleType;
private ExponentialMovingAverage _ema;
private decimal? _prevClose;
private decimal? _prevMa;
public int MovingPeriod
{
get => _movingPeriod.Value;
set => _movingPeriod.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public Maybeawo222Strategy()
{
_movingPeriod = Param(nameof(MovingPeriod), 20)
.SetDisplay("MA Period", "Simple moving average period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Primary candle series", "General");
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_ema = new ExponentialMovingAverage { Length = MovingPeriod };
_prevClose = null;
_prevMa = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_ema, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _ema);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal maValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!_ema.IsFormed)
{
_prevClose = candle.ClosePrice;
_prevMa = maValue;
return;
}
var close = candle.ClosePrice;
if (_prevClose is null || _prevMa is null)
{
_prevClose = close;
_prevMa = maValue;
return;
}
// Buy signal: candle crosses MA from below to above
var buySignal = _prevClose <= _prevMa && close > maValue;
// Sell signal: candle crosses MA from above to below
var sellSignal = _prevClose >= _prevMa && close < maValue;
if (buySignal && Position <= 0)
{
BuyMarket(Position < 0 ? Math.Abs(Position) + 1 : 1);
}
else if (sellSignal && Position >= 0)
{
SellMarket(Position > 0 ? Math.Abs(Position) + 1 : 1);
}
_prevClose = close;
_prevMa = maValue;
}
/// <inheritdoc />
protected override void OnReseted()
{
_ema = null;
_prevClose = null;
_prevMa = null;
base.OnReseted();
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class maybeawo222_strategy(Strategy):
"""
EMA crossover: buy when price crosses MA from below, sell from above.
"""
def __init__(self):
super(maybeawo222_strategy, self).__init__()
self._moving_period = self.Param("MovingPeriod", 20).SetDisplay("MA Period", "EMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))).SetDisplay("Candle Type", "Candles", "General")
self._prev_close = None
self._prev_ma = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(maybeawo222_strategy, self).OnReseted()
self._prev_close = None
self._prev_ma = None
def OnStarted2(self, time):
super(maybeawo222_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self._moving_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def _process_candle(self, candle, ma_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
ma = float(ma_val)
if self._prev_close is None or self._prev_ma is None:
self._prev_close = close
self._prev_ma = ma
return
buy_signal = self._prev_close <= self._prev_ma and close > ma
sell_signal = self._prev_close >= self._prev_ma and close < ma
if buy_signal and self.Position <= 0:
self.BuyMarket()
elif sell_signal and self.Position >= 0:
self.SellMarket()
self._prev_close = close
self._prev_ma = ma
def CreateClone(self):
return maybeawo222_strategy()