The Close Profit End Of Week Strategy automates the MetaTrader script Closeprofitendofweek.mq5. The strategy supervises the assigned instrument and, on Fridays after a configurable cut-off time, exits every profitable position. The goal is to secure floating gains before the weekend gap risk appears.
Original MQL Behaviour
The source Expert Advisor continuously polled positions through the timer handler. Whenever the server time matched Friday and the configured end time, it looped through all open positions on the traded symbol. Every position with positive profit was closed via a market order. Crypto symbols were explicitly excluded because they trade without weekend breaks.
StockSharp Implementation
The C# port keeps the same protection logic while using StockSharp's high-level API:
Subscribes to a configurable candle series only to receive regular time updates.
Checks each finished candle and verifies that it represents a Friday whose closing time is after the user-defined cut-off.
Accesses the connected portfolio to evaluate the net position for the strategy symbol.
Issues a market order in the opposite direction for every profitable exposure that is still open.
Skips the routine entirely when the instrument is classified as a crypto asset.
Parameters
Name
Description
Default
StartTradeTime
Beginning of the monitoring window (kept for parity with the MQL inputs).
00:00
EndTradeTime
Time of day on Friday after which profitable positions must be closed.
20:00
CloseTradesAtEndTime
Enables or disables the automatic closing routine.
true
CandleType
Data series used to track time (defaults to 1-minute candles).
TimeFrameCandle(1m)
Execution Flow
When the strategy starts it verifies whether the selected security belongs to the crypto-asset class. Crypto instruments are ignored to mirror the MetaTrader guard clause.
A candle subscription is created to receive regular callbacks once each candle is finished.
Every finished candle triggers the schedule checks. Only Fridays that closed after the cut-off time lead to further processing.
The strategy scans the connected portfolio, filters the position that corresponds to the configured security, and reads its floating profit.
If the floating profit is greater than zero, a market order is submitted in the opposite direction to fully close the exposure.
Duplicate exit orders are avoided by inspecting active orders before sending new ones.
Usage Notes
Attach the strategy to a non-crypto instrument together with the same portfolio that owns the open positions you want to supervise.
The strategy does not open any new trades; it only manages existing positions.
The StartTradeTime parameter exists for configuration parity and future extensions but is not referenced by the current logic.
For multi-symbol portfolios, run one instance per instrument to replicate the single-symbol scope of the MetaTrader script.
Limitations
Profit detection relies on the broker portfolio reporting floating PnL. If the portfolio does not update in real time the closing command may be delayed.
Only positions for the configured strategy symbol are closed. Exposures held on other symbols remain untouched.
The check is executed on candle close events. Select an appropriately short timeframe if you need a tighter schedule.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Close Profit End Of Week strategy: Momentum + EMA trend following.
/// Buys when momentum positive and close above EMA, sells when momentum negative and close below EMA.
/// </summary>
public class CloseProfitEndOfWeekStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _momPeriod;
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<decimal> _momentumLevel;
private decimal _prevMom;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int MomPeriod { get => _momPeriod.Value; set => _momPeriod.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public decimal MomentumLevel { get => _momentumLevel.Value; set => _momentumLevel.Value = value; }
public CloseProfitEndOfWeekStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_momPeriod = Param(nameof(MomPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Momentum Period", "Momentum period", "Indicators");
_emaPeriod = Param(nameof(EmaPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA filter period", "Indicators");
_momentumLevel = Param(nameof(MomentumLevel), 101m)
.SetDisplay("Momentum Level", "Momentum threshold", "Signals");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevMom = 0;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevMom = 0;
_hasPrev = false;
var mom = new Momentum { Length = MomPeriod };
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(mom, ema, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal momValue, decimal emaValue)
{
if (candle.State != CandleStates.Finished) return;
if (_hasPrev)
{
if (_prevMom <= MomentumLevel && momValue > MomentumLevel && candle.ClosePrice > emaValue && Position <= 0)
BuyMarket();
else if (_prevMom >= 200m - MomentumLevel && momValue < 200m - MomentumLevel && candle.ClosePrice < emaValue && Position >= 0)
SellMarket();
}
_prevMom = momValue;
_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 Momentum, ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class close_profit_end_of_week_strategy(Strategy):
def __init__(self):
super(close_profit_end_of_week_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._mom_period = self.Param("MomPeriod", 20)
self._ema_period = self.Param("EmaPeriod", 50)
self._momentum_level = self.Param("MomentumLevel", 101.0)
self._prev_mom = 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 MomPeriod(self):
return self._mom_period.Value
@MomPeriod.setter
def MomPeriod(self, value):
self._mom_period.Value = value
@property
def EmaPeriod(self):
return self._ema_period.Value
@EmaPeriod.setter
def EmaPeriod(self, value):
self._ema_period.Value = value
@property
def MomentumLevel(self):
return self._momentum_level.Value
@MomentumLevel.setter
def MomentumLevel(self, value):
self._momentum_level.Value = value
def OnReseted(self):
super(close_profit_end_of_week_strategy, self).OnReseted()
self._prev_mom = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(close_profit_end_of_week_strategy, self).OnStarted2(time)
self._prev_mom = 0.0
self._has_prev = False
mom = Momentum()
mom.Length = self.MomPeriod
ema = ExponentialMovingAverage()
ema.Length = self.EmaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(mom, ema, self._process_candle).Start()
def _process_candle(self, candle, mom_value, ema_value):
if candle.State != CandleStates.Finished:
return
mom_val = float(mom_value)
ema_val = float(ema_value)
close = float(candle.ClosePrice)
level = float(self.MomentumLevel)
if self._has_prev:
if self._prev_mom <= level and mom_val > level and close > ema_val and self.Position <= 0:
self.BuyMarket()
elif self._prev_mom >= (200.0 - level) and mom_val < (200.0 - level) and close < ema_val and self.Position >= 0:
self.SellMarket()
self._prev_mom = mom_val
self._has_prev = True
def CreateClone(self):
return close_profit_end_of_week_strategy()