Стратегия открывает одну сделку в день в заданный час, опираясь на разницу между открытием прошлых свечей.
Как это работает
Ожидание времени входа: стратегия отслеживает время открытия свечи. Когда текущий час становится больше TradeTime, торговля разрешается при следующем появлении этого часа.
Генерация сигналов:
Когда час равен TradeTime, сравниваются цены открытия t1 и t2 свечей назад.
Если Open[t1] - Open[t2] превышает DeltaShort пунктов, открывается короткая позиция.
Если Open[t2] - Open[t1] превышает DeltaLong пунктов, открывается длинная позиция.
Управление позицией:
Длинная позиция закрывается при росте цены на TakeProfitLong пунктов либо падении на StopLossLong пунктов.
Короткая позиция закрывается при падении цены на TakeProfitShort пунктов либо росте на StopLossShort пунктов.
Если позиция открыта дольше MaxOpenTime часов, она принудительно закрывается.
Объём торговли фиксированный, за день выполняется не более одной сделки.
Параметры
Имя
Описание
CandleType
Тип используемых свечей.
Volume
Объём заявки.
TakeProfitLong
Стоп тейк-профит для длинных позиций в пунктах.
StopLossLong
Стоп-лосс для длинных позиций в пунктах.
TakeProfitShort
Тейк-профит для коротких позиций в пунктах.
StopLossShort
Стоп-лосс для коротких позиций в пунктах.
TradeTime
Час, когда оцениваются сигналы.
T1
Количество свечей назад для первого открытия.
T2
Количество свечей назад для второго открытия.
DeltaLong
Минимальная разница для входа в длинную позицию.
DeltaShort
Минимальная разница для входа в короткую позицию.
MaxOpenTime
Максимальное время удержания позиции (в часах).
Примечания
Обрабатываются только завершённые свечи.
Пороговые значения в пунктах переводятся в цену через минимальный шаг цены инструмента.
Дополнительные индикаторы не используются.
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()