This utility strategy immediately closes existing positions and cancels pending orders according to user-defined filters. It can operate on the attached security only or on all portfolio securities. Optional time window and price range restrictions allow precise control over which orders are affected.
Details
Purpose: risk management and manual liquidation.
Operation:
On start the strategy checks the optional time window.
If allowed it closes positions and cancels orders matching the filters.
After processing the strategy stops automatically.
Filters:
CloseAllSecurities – include all portfolio instruments instead of only the attached security.
CloseOpenLongOrders / CloseOpenShortOrders – close existing long or short positions.
ClosePendingLongOrders / ClosePendingShortOrders – cancel pending buy or sell orders.
SpecificOrderId – only touch orders with the given transaction id when non-zero.
CloseOrdersWithinRange, CloseRangeHigh, CloseRangeLow – limit by entry price range.
EnableTimeControl, StartCloseTime, StopCloseTime – apply only during a specific time window.
Default Values:
All closing options enabled.
SpecificOrderId = 0.
CloseOrdersWithinRange = false.
CloseRangeHigh = 0.
CloseRangeLow = 0.
EnableTimeControl = false.
StartCloseTime = 02:00.
StopCloseTime = 02:30.
Notes:
The strategy does not open new positions.
Price range filters are ignored when bounds are zero or negative.
When CloseAllSecurities is enabled, positions across the entire portfolio are processed.
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 that closes positions based on time-of-day and EMA conditions.
/// Opens positions during trend and closes them at specific time.
/// </summary>
public class CloseOrdersStrategy : Strategy
{
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevEma;
private bool _hasPrev;
public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public CloseOrdersStrategy()
{
_emaLength = Param(nameof(EmaLength), 40)
.SetGreaterThanZero()
.SetDisplay("EMA Length", "EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevEma = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema = new ExponentialMovingAverage { Length = EmaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal emaVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev)
{
_prevEma = emaVal;
_hasPrev = true;
return;
}
var close = candle.ClosePrice;
// EMA rising -> buy
if (emaVal > _prevEma && close > emaVal && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// EMA falling -> sell
else if (emaVal < _prevEma && close < emaVal && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevEma = emaVal;
}
}
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 close_orders_strategy(Strategy):
def __init__(self):
super(close_orders_strategy, self).__init__()
self._ema_length = self.Param("EmaLength", 40) \
.SetDisplay("EMA Length", "EMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._prev_ema = 0.0
self._has_prev = False
@property
def ema_length(self):
return self._ema_length.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(close_orders_strategy, self).OnReseted()
self._prev_ema = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(close_orders_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self.ema_length
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, ema_val):
if candle.State != CandleStates.Finished:
return
if not self._has_prev:
self._prev_ema = ema_val
self._has_prev = True
return
close = candle.ClosePrice
# EMA rising -> buy
if ema_val > self._prev_ema and close > ema_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# EMA falling -> sell
elif ema_val < self._prev_ema and close < ema_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_ema = ema_val
def CreateClone(self):
return close_orders_strategy()