Открыть на GitHub

Стратегия TradeXpert Manual Trading Panel

Обзор

Исходный советник TradeXpert для MQL5 — это панель ручной торговли с набором кнопок для открытия позиций, размещения отложенных заявок, установки защитных уровней и мгновенного разворота позиции. В версии на StockSharp все эти функции реализованы через параметры стратегии. Стратегия не генерирует собственных сигналов: она ждет ваших команд, исполняет соответствующие заявки и контролирует защитные выходы по мере поступления новых свечей.

Воссозданные возможности

  • Рыночные действия. Одноразовые команды Buy и Sell с использованием заданного объема.
  • Отложенные заявки. Единоразовая постановка лимитных и стоп-заявок для покупки и продажи с абсолютной ценой либо с вычислением цены по смещению от последнего закрытия.
  • Управление защитой. Стоп-лосс и тейк-профит задаются в абсолютных значениях или как смещения от цены входа. Если экстремумы свечи пробивают указанный уровень, стратегия закрывает позицию рыночной заявкой.
  • Ручное закрытие и разворот. Параметры для мгновенного закрытия или разворота позиции воспроизводят кнопки Close и Reverse из MQL-панели.

Логика работы стратегии

  1. Стратегия подписывается на тип свечей, выбранный в параметре CandleType, и использует поток для расчета смещений и проверки защитных уровней.
  2. На каждой закрывшейся свече стратегия:
    • Обновляет свойство Volume актуальным значением TradeVolume.
    • Обрабатывает запросы на закрытие или разворот, даже если индикаторы еще не сформированы.
    • После проверки готовности рынка исполняет запрошенные рыночные сделки, отправляет отложенные заявки и проверяет условия срабатывания стоп-лосса и тейк-профита.
  3. При любом изменении величины позиции (открытие, наращивание, сокращение) обновляется сохраненная цена входа, чтобы смещения защитных уровней учитывали последнюю сделку.
  4. Защитная логика ориентируется на максимум и минимум свечи. При пробитии уровня стратегия отправляет противоположную рыночную заявку объемом, равным текущей позиции, чтобы полностью ее закрыть.

Параметры

  • CandleType — тип свечей для расчета смещений и контроля рисков.
  • TradeVolume — объем каждой рыночной и отложенной заявки (должен быть > 0).
  • EntryAction — селектор рыночных действий (None, BuyMarket, SellMarket). При выборе значения, отличного от None, заявка исполняется один раз, после чего параметр возвращается в None.
  • PendingAction — селектор отложенных заявок (None, BuyLimit, BuyStop, SellLimit, SellStop). После успешной постановки заявки значение очищается.
  • PendingPrice — абсолютная цена отложенной заявки. При 0 используется PendingOffset.
  • PendingOffset — смещение от последнего закрытия при отсутствии абсолютной цены. Знак автоматически подбирается в зависимости от выбранного типа заявки.
  • UseStopLoss / StopLossPrice / StopLossOffset — включение и настройка стоп-лосса. При нулевом абсолютном значении цена стопа рассчитывается по смещению от зафиксированного входа.
  • UseTakeProfit / TakeProfitPrice / TakeProfitOffset — аналогичные параметры для тейк-профита.
  • ClosePositionRequest — установка true инициирует немедленное закрытие всей позиции рыночной заявкой; после обработки флаг сбрасывается.
  • ReversePositionRequest — установка true разворачивает позицию: текущая позиция закрывается, затем открывается противоположная с объемом ReverseVolume, после чего флаг сбрасывается.
  • ReverseVolume — объем новой позиции после разворота. Чтобы получить симметричный разворот, задайте значение, равное текущему абсолютному объему позиции.

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

  1. Подберите CandleType в соответствии с тем, как вы хотите измерять смещения и контролировать риск. По умолчанию используется минутная свеча, что соответствует изначальной панели, реагировавшей на поток тиков.
  2. Установите TradeVolume и при необходимости задайте защитные уровни (StopLoss*, TakeProfit*). При значении 0 для абсолютных параметров будут задействованы смещения.
  3. Для отложенных заявок решите, нужна ли фиксированная цена (PendingPrice) или динамический расчет по смещению (PendingOffset). Итоговая цена вычисляется в момент постановки заявки.
  4. Отправляйте команды, изменяя EntryAction, PendingAction, ClosePositionRequest или ReversePositionRequest. Каждый параметр работает как кнопка: после выполнения он автоматически возвращается в исходное состояние и не повторяет действие на следующей свече.
  5. При открытой позиции стратегия отслеживает цену и срабатывание защитных уровней. После закрытия по стопу или тейку триггеры отключаются до следующего входа, чтобы избежать повторных заявок.

Отличия от оригинального MQL-варианта

  • Графическая панель заменена набором параметров стратегии, которые можно менять через интерфейс StockSharp или внешние скрипты.
  • Вместо размещения отдельных стоп- и тейк-заявок стратегия закрывает позицию рыночными ордерами при достижении уровней. Это полностью соответствует высокоуровневому API и не требует сопровождать дополнительные заявки.
  • Расчет смещений выполняется по закрывшимся свечам, а не по каждому тику, что повышает воспроизводимость поведения в тестах и на реальном рынке.

Примечания

  • В течение одной свечи можно отправить несколько команд (например, купить и сразу запросить установку тейк-профита). Стратегия обработает их последовательно на следующей закрывшейся свече.
  • Чтобы повторить действие, выберите требуемое значение повторно — внутренняя логика обнаружит изменение и выполнит новую команду.
  • При изменении размера позиции сохраненная цена входа обновляется до закрытия свечи, в которой зафиксировано изменение. При необходимости скорректируйте смещения защитных уровней, чтобы сохранить нужные расстояния.
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// TradeXpert Manual Trading Panel strategy. Uses CCI zero-line crossover (period 20).
/// </summary>
public class TradeXpertManualTradingPanelStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _cciPeriod;
	private decimal? _prevCci;

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

	public TradeXpertManualTradingPanelStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
		_cciPeriod = Param(nameof(CciPeriod), 20).SetGreaterThanZero().SetDisplay("CCI Period", "CCI lookback", "Indicators");
	}

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

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

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevCci = null;
		var cci = new CommodityChannelIndex { Length = CciPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(cci, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawOwnTrades(area); }
	}

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