This strategy opens a single trade each day at a specified hour based on the difference between past candle opens.
How It Works
Waiting for Trade Time: The strategy monitors candle open times. Once the hour is greater than TradeTime, trading is allowed for the next occurrence of that hour.
Signal Generation:
When the current hour equals TradeTime, the strategy compares the open price from t1 bars ago with the open price from t2 bars ago.
If the difference Open[t1] - Open[t2] exceeds DeltaShort points, a short position is opened.
If the difference Open[t2] - Open[t1] exceeds DeltaLong points, a long position is opened.
Position Management:
For long positions, the strategy exits when price reaches TakeProfitLong above the entry or StopLossLong below it.
For short positions, it exits when price moves TakeProfitShort below or StopLossShort above the entry.
Positions are also closed if they remain open longer than MaxOpenTime hours.
The strategy trades with a fixed volume and does not enter new trades until the next day.
Parameters
Name
Description
CandleType
Candle source for the strategy.
Volume
Order volume.
TakeProfitLong
Take profit in points for long trades.
StopLossLong
Stop loss in points for long trades.
TakeProfitShort
Take profit in points for short trades.
StopLossShort
Stop loss in points for short trades.
TradeTime
Hour of the day when signals are evaluated.
T1
Number of bars back for the first open price.
T2
Number of bars back for the second open price.
DeltaLong
Minimum difference (in points) between Open[t2] and Open[t1] to open a long trade.
DeltaShort
Minimum difference (in points) between Open[t1] and Open[t2] to open a short trade.
MaxOpenTime
Maximum holding time in hours.
Notes
Only finished candles are processed.
The strategy uses the instrument price step to convert point-based thresholds into absolute prices.
No additional indicators are used.
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>
/// Scalping strategy comparing past open prices with EMA trend filter.
/// </summary>
public class LotScalpStrategy : Strategy
{
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevOpen;
private decimal _prevPrevOpen;
private int _barCount;
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public LotScalpStrategy()
{
_emaPeriod = Param(nameof(EmaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA period for trend", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle source", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevOpen = 0;
_prevPrevOpen = 0;
_barCount = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
SubscribeCandles(CandleType).Bind(ema, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal emaValue)
{
if (candle.State != CandleStates.Finished) return;
_barCount++;
var close = candle.ClosePrice;
var open = candle.OpenPrice;
if (_barCount >= 3)
{
var diff = _prevPrevOpen - _prevOpen;
// Open prices diverging downward + close above EMA => buy
if (diff > 0 && close > emaValue && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
// Open prices diverging upward + close below EMA => sell
else if (diff < 0 && close < emaValue && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
}
_prevPrevOpen = _prevOpen;
_prevOpen = open;
}
}
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 lot_scalp_strategy(Strategy):
def __init__(self):
super(lot_scalp_strategy, self).__init__()
self._ema_period = self.Param("EmaPeriod", 20) \
.SetDisplay("EMA Period", "EMA period for trend", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle source", "General")
self._prev_open = 0.0
self._prev_prev_open = 0.0
self._bar_count = 0
@property
def ema_period(self):
return self._ema_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(lot_scalp_strategy, self).OnReseted()
self._prev_open = 0.0
self._prev_prev_open = 0.0
self._bar_count = 0
def OnStarted2(self, time):
super(lot_scalp_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self.ema_period
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_value):
if candle.State != CandleStates.Finished:
return
self._bar_count += 1
close = candle.ClosePrice
open = candle.OpenPrice
if self._bar_count >= 3:
diff = self._prev_prev_open - self._prev_open
# Open prices diverging downward + close above EMA => buy
if diff > 0 and close > ema_value and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Open prices diverging upward + close below EMA => sell
elif diff < 0 and close < ema_value and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_prev_open = self._prev_open
self._prev_open = open
def CreateClone(self):
return lot_scalp_strategy()