Открыть на GitHub

Стратегия LotScalp

Стратегия открывает одну сделку в день в заданный час, опираясь на разницу между открытием прошлых свечей.

Как это работает

  1. Ожидание времени входа: стратегия отслеживает время открытия свечи. Когда текущий час становится больше TradeTime, торговля разрешается при следующем появлении этого часа.
  2. Генерация сигналов:
    • Когда час равен TradeTime, сравниваются цены открытия t1 и t2 свечей назад.
    • Если Open[t1] - Open[t2] превышает DeltaShort пунктов, открывается короткая позиция.
    • Если Open[t2] - Open[t1] превышает DeltaLong пунктов, открывается длинная позиция.
  3. Управление позицией:
    • Длинная позиция закрывается при росте цены на 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;
	}
}