Открыть на GitHub

Стратегия Little EA

Обзор

Little EA — это эксперт по пересечению скользящей средней, изначально созданный для MetaTrader. Стратегия анализирует свечу, выбранную параметром OHLC bar index, и реагирует, когда эта свеча пересекает смещённую скользящую среднюю снизу вверх или сверху вниз. Порт на StockSharp сохраняет идею многошагового входа и позволяет накапливать несколько траншей в каждом направлении при условии соблюдения настраиваемого лимита по объёму.

Логика торговли

  1. Подписаться на свечной поток выбранного таймфрейма и подавать в скользящую среднюю выбранного типа нужный источник цены (close, open, high, low, median, typical или weighted).
  2. Сохранять завершённые свечи, чтобы иметь доступ к свече с индексом OhlcBarIndex (значение по умолчанию 1 — последняя полностью закрытая свеча).
  3. Применить параметр MaShift, считывая значение скользящей средней несколько баров назад, тем самым повторяя визуальный сдвиг из MetaTrader.
  4. Если опорная свеча закрывается выше смещённой средней, фиксируется бычий сигнал; если ниже — медвежий сигнал.
  5. При бычьем сигнале:
    • если текущий короткий объём уже достиг лимита, закрыть всю короткую позицию;
    • иначе, пока длинная позиция меньше лимита, добавить один транш объёмом TradeVolume.
  6. При медвежьем сигнале:
    • если длинная позиция уже на предельном объёме, полностью закрыть лонг;
    • иначе увеличить шорт на один транш TradeVolume, если лимит ещё не исчерпан.

Такой подход к ограничению объёма имитирует параметр Int_Max_Pos оригинального советника, но с учётом неттингового учёта позиций в StockSharp.

Параметры

Название Тип Значение по умолчанию Описание
CandleType DataType таймфрейм 1 минута Основной временной интервал для расчёта сигналов и индикатора.
OhlcBarIndex int 1 Индекс исторической свечи, по которой оценивается пересечение (0 = текущая формирующаяся свеча, 1 = последняя закрытая).
MaxPositionsPerSide int 15 Максимальное количество траншей TradeVolume, которое допускается накапливать в одном направлении.
MaPeriod int 64 Длина скользящей средней.
MaShift int 0 Количество баров, на которое значение скользящей средней смещается назад при проверке сигнала.
MaType MovingAverageType Smoothed Тип скользящей (Simple, Exponential, Smoothed, Weighted).
AppliedPrice AppliedPriceType Close Источник цены для расчёта индикатора.
TradeVolume decimal 1 Объём каждой новой сделки или добавления к позиции.

Отличия от оригинального советника MetaTrader

  • Управление капиталом упрощено: реализована только работа с фиксированным объёмом, процентный риск из оригинала не поддерживается.
  • В StockSharp используется неттинг, поэтому противоположные позиции закрываются перед набором новой экспозиции. Ограничение MaxPositionsPerSide применяется к чистому объёму в лотах.
  • Обработка индикатора и исторических данных выполнена через высокоуровневую подписку на свечи, что заменяет ручное копирование буферов в MQL.

Рекомендации по использованию

  • До старта стратегии установите TradeVolume в соответствии с шагом лота инструмента; в конструкторе это значение также присваивается Strategy.Volume, поэтому стандартные методы заявок используют нужный объём по умолчанию.
  • Комбинируйте MaShift и OhlcBarIndex, чтобы при необходимости добиться визуального совпадения с графиком MetaTrader.
  • Рекомендуется запускать стратегию вместе с графиком, чтобы видеть свечи, наложенную скользящую и совершённые сделки для проверки сигналов.

Индикаторы

  • Одна настраиваемая скользящая средняя (Simple, Exponential, Smoothed или Weighted).
using System;
using System.Collections.Generic;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

public class LittleEaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _momentumPeriod;
	private decimal? _prevMom;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int MomentumPeriod { get => _momentumPeriod.Value; set => _momentumPeriod.Value = value; }

	public LittleEaStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
		_momentumPeriod = Param(nameof(MomentumPeriod), 10).SetGreaterThanZero().SetDisplay("Momentum Period", "Momentum lookback", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevMom = null;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevMom = null;
		var mom = new Momentum { Length = MomentumPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(mom, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal momVal)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!IsFormedAndOnlineAndAllowTrading()) { _prevMom = momVal; return; }
		if (_prevMom == null) { _prevMom = momVal; return; }
		if (_prevMom.Value < 100m && momVal >= 100m && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (_prevMom.Value > 100m && momVal <= 100m && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
		_prevMom = momVal;
	}
}