Открыть на GitHub

Стратегия MultiCurrency Template MT5

Общее описание

MultiCurrency Template MT5 — это порт стратегии MetaTrader с одноимённым советником. Она ищет комбинацию из двух дневных свечей и позволяет вести корзину позиций сразу по нескольким инструментам. Первичная сделка открывается только тогда, когда предыдущая дневная свеча формирует нужный бычий или медвежий сценарий, после чего управление переносится на более быстрый контрольный таймфрейм. При неблагоприятном движении цены модуль мартингейла дозагружает позиции через заданный шаг в MetaTrader-пунктах, а выход реализует комбинацию фиксированного тейк-профита, усреднённого выхода по безубытку и опционального трейлинг-стопа.

При переносе в StockSharp сохранена мультивалютная логика: пользователь может передать список инструментов через параметр PairsToTrade, и для каждого инструмента создаётся независимый контекст с собственной корзиной и расчётами. Если TradeMultipair отключён, стратегия торгует только базовым инструментом из свойства Security.

Формирование сигналов

  • Подписка на свечи типа SignalCandleType (по умолчанию дневные) и хранение двух последних завершённых свечей.
  • Покупка появляется, если текущий закрытие ниже предыдущего открытия, а предыдущая свеча закрылась выше открытия.
  • Продажа возникает, если текущее закрытие выше предыдущего открытия, а предыдущая свеча закрылась ниже открытия.
  • Одновременно активен только один направленный сценарий; новые сигналы игнорируются до полной ликвидации текущей корзины.

Открытие и сопровождение позиций

  • Входы выполняются рыночными заявками с объёмом Lots.
  • При включённом NewBarTrade стратегия ждёт формирования новой свечи таймфрейма TradeCandleType, после чего допускает сделку. Флаг сбрасывается после первой попытки торговать, полностью повторяя поведение MetaTrader «торговать только на новой свече».
  • Начальные уровни стоп-лосса и тейк-профита задаются в MetaTrader-пунктах с учётом вычисленного размера пункта.
  • Если EnableMartingale = true, то при отклонении цены от лучшего входа корзины на StepPoints MetaTrader-пунктов добавляется новая усредняющая позиция. Её объём умножается на NextLotMultiplier в степени количества уже открытых сделок данного направления.

Управление сделками

  • Режим EnableTakeProfitAverage задаёт работу тейк-профита:
    • При выключенном режиме цель остаётся на фиксированной дистанции TakeProfitPips от лучшей цены.
    • При включённом режиме и наличии минимум двух ордеров тейк переносится на цену безубыточности плюс TakeProfitOffsetPoints.
  • Стоп-уровни пересчитываются после каждого исполнения ордера, учитывая самый неблагоприятный вход корзины.
  • Трейлинг-стоп активен, если в корзине осталась только одна сделка: сначала перенос в безубыток + TrailingStopPoints после прохождения TrailingStopPoints + TrailingStepPoints, затем сопровождение с тем же отступом.
  • Срабатывание стопа или тейка приводит к закрытию всей корзины одной рыночной заявкой.

Параметры

Параметр Описание
Lots Базовый объём первой сделки в корзине.
StopLossPips Стартовый стоп-лосс в MetaTrader-пунктах.
TakeProfitPips Стартовый тейк-профит в MetaTrader-пунктах.
TrailingStopPoints Отступ трейлинг-стопа (пункты MetaTrader) при единственной сделке.
TrailingStepPoints Дополнительный шаг, после которого трейлинг переносится повторно.
SlippagePoints Сохраняется для совместимости, на исполнение в StockSharp не влияет.
NewBarTrade Разрешать сделки только после появления новой свечи TradeCandleType.
TradeCandleType Таймфрейм, отвечающий за новую свечу и сервисные расчёты.
TradeMultipair Включает режим одновременной торговли несколькими инструментами.
PairsToTrade Список тикеров через запятую, которые будут получены через GetSecurity.
Commentary Текст комментария к ордерам, перенесённый из оригинала.
EnableMartingale Активирует блок усредняющих входов.
NextLotMultiplier Множитель объёма для каждого последующего усреднения.
StepPoints Шаг в пунктах MetaTrader между усредняющими сделками.
EnableTakeProfitAverage Включает переназначение тейка на уровень безубыточности.
TakeProfitOffsetPoints Смещение от цены безубыточности при активном усреднённом тейке.
SignalCandleType Таймфрейм для анализа двух свечей (по умолчанию день).

Примечания

  • Все сделки исполняются рыночными ордерами; защитные приказы брокера моделируются внутри стратегии.
  • PairsToTrade должен содержать идентификаторы, доступные подключённому коннектору. Неизвестные инструменты пропускаются.
  • Модули мартингейла и трейлинг-стопа работают независимо для каждого инструмента.
  • Параметр SlippagePoints оставлен для совместимости и не участвует в расчётах в среде StockSharp.
using System;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Simplified from "Multi Currency Template MT5" MetaTrader expert.
/// Uses candlestick pattern (bearish followed by bullish or vice versa) for entries
/// with simple reversal logic.
/// </summary>
public class MultiCurrencyTemplateMt5Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _lookback;

	private ICandleMessage _prevCandle;

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

	public int Lookback
	{
		get => _lookback.Value;
		set => _lookback.Value = value;
	}

	public MultiCurrencyTemplateMt5Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for signal generation", "General");

		_lookback = Param(nameof(Lookback), 1)
			.SetGreaterThanZero()
			.SetDisplay("Lookback", "Number of prior candles for pattern", "Signals");
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_prevCandle = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (_prevCandle is null)
		{
			_prevCandle = candle;
			return;
		}

		var volume = Volume;
		if (volume <= 0)
			volume = 1;

		// Buy signal: previous candle was bullish (close > open), current closes below previous open
		// This is a reversal pattern - bearish candle after bullish suggests exhaustion, buy the dip
		var minBody = _prevCandle.OpenPrice * 0.001m;
		var buySignal = candle.ClosePrice < _prevCandle.OpenPrice - minBody && _prevCandle.ClosePrice > _prevCandle.OpenPrice + minBody;
		// Sell signal: previous candle was bearish (close < open), current closes above previous open
		var sellSignal = candle.ClosePrice > _prevCandle.OpenPrice + minBody && _prevCandle.ClosePrice < _prevCandle.OpenPrice - minBody;

		if (buySignal)
		{
			if (Position <= 0)
				BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
		}
		else if (sellSignal)
		{
			if (Position >= 0)
				SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
		}

		_prevCandle = candle;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		_prevCandle = null;

		base.OnReseted();
	}
}