Открыть на GitHub

Стратегия Ten Points 3

Кратко

  • Конвертация эксперта MetaTrader 4 10p3v004 ("10points 3") на высокоуровневый API StockSharp.
  • Воссоздаёт сеточную систему на основе наклона MACD, включая мартингейл, трейлинг и защиту по прибыли.
  • Для каждого параметра добавлены подробные пояснения, что позволяет точно повторить поведение оригинальной системы либо безопасно его настроить.

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

  1. Определение сигнала. После закрытия каждой свечи выбранного таймфрейма вычисляется MACD с настраиваемыми периодами. Рост главной линии относительно предыдущего значения формирует сигнал на покупку, падение — на продажу. Флаг ReverseSignals меняет интерпретацию.
  2. Построение сетки. В любой момент может существовать только одна сетка в одном направлении.
    • Первый ордер выставляется сразу после появления сигнала.
    • Дополнительные ордера добавляются, если направление соответствует сигналу, цена отошла не менее чем на GridSpacingPoints * PriceStep от последней сделки и количество ордеров меньше MaxTrades.
    • Объём очередного ордера увеличивается по мартингейлу: 2^n при сетке до 12 шагов и 1.5^n при более длинной сетке. Объём округляется по шагу инструмента и ограничивается как биржевыми лимитами, так и параметром MaxVolumeCap.
  3. Управление капиталом. При включённом UseMoneyManagement базовый объём рассчитывается из текущей стоимости портфеля и параметра RiskPerTenThousand. Опция IsStandardAccount повторяет особые правила округления объёма для стандартных/мини счетов. При отключении используется фиксированный BaseVolume.
  4. Выход из позиции.
    • Начальный стоп закрывает сетку при неблагоприятном движении на InitialStopPoints.
    • Тейк-профит ликвидирует позицию при достижении TakeProfitPoints в нужную сторону.
    • Трейлинг-стоп активируется, когда цена отходит от средней цены на TrailingStopPoints + GridSpacingPoints, и далее удерживает запас TrailingStopPoints.
    • Защита счёта контролирует нереализованную прибыль (в пунктах × объём). При достижении SecureProfit и количестве ордеров не менее OrdersToProtect сетка закрывается полностью.

Параметры

Параметр Описание Значение по умолчанию
CandleType Таймфрейм, на котором рассчитывается MACD и принимаются решения. Свечи 30 минут
MacdFastPeriod / MacdSlowPeriod / MacdSignalPeriod Периоды MACD, совпадают с оригинальным советником. 14 / 26 / 9
BaseVolume Стартовый объём первой сделки при отключённом управлении капиталом. 0.01
GridSpacingPoints Минимальная дистанция между ордерами сетки (в шагах цены). 15
TakeProfitPoints Расстояние до тейк-профита, 0 — отключено. 40
InitialStopPoints Расстояние начального стопа, 0 — отключено. 0
TrailingStopPoints Размер трейлинг-буфера, активируется после движения на TrailingStopPoints + GridSpacingPoints. 20
MaxTrades Максимальное число ордеров в сетке. 9
OrdersToProtect Минимальное число ордеров для срабатывания защиты счёта. 3
SecureProfit Порог нереализованной прибыли (пункты × объём) для принудительного закрытия. 8
AccountProtectionEnabled Включает/выключает защиту счёта. true
ReverseSignals Инвертирует сигналы MACD. false
UseMoneyManagement Включает расчёт объёма по капиталу. false
RiskPerTenThousand Риск на каждые 10 000 единиц капитала при включённом управлении. 12
IsStandardAccount Логика округления объёма (стандартные/мини лоты). true
MaxVolumeCap Жёсткий предел итогового объёма после мартингейла. 100

Особенности конвертации

  • В MT4 стопы задавались на уровне каждого ордера. В StockSharp позиция ведётся агрегировано, поэтому стопы и трейлинг рассчитываются от средней цены входа.
  • В исходнике прибыль переводилась в валюту счёта через TickValue. В новой версии защита счёта работает с величиной «пункты × объём», что соответствует исходным расчётам в пунктах.
  • Функции AccountFreeMarginCheck и другие брокерские проверки недоступны в StockSharp. Вместо них используются биржевые ограничения инструмента и дополнительный параметр MaxVolumeCap.
  • Комментарии ордеров, magic number и графические элементы из MT4 не переносятся, так как в StockSharp им нет прямого аналога.

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

  1. Добавьте стратегию в проект, назначьте Security и Portfolio.
  2. Подберите CandleType под нужный таймфрейм (обычно такой же, как в MT4).
  3. Настройте объём: либо фиксированный BaseVolume, либо включите UseMoneyManagement с нужными параметрами риска.
  4. Выберите, какие защитные механизмы использовать, и задайте соответствующие пороги.
  5. Запустите стратегию и контролируйте сделки через встроенные графики (свечи, MACD, собственные сделки).

Идеи для развития

  • Заменить фиксированный шаг сетки динамическим (например, на основе ATR).
  • Разделить настройки трейлинг-стопа или множителя мартингейла для длинных и коротких позиций.
  • Добавить фильтры тренда (МА, анализ старшего таймфрейма), чтобы сократить работу против тенденции.

Важно: По требованию Python-версия стратегии не создавалась, папка PY отсутствует.

using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// TenPoints3: RSI reversal with EMA filter and ATR stops.
/// </summary>
public class TenPoints3Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevRsi;
	private decimal _entryPrice;

	public TenPoints3Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(8).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");
		_rsiLength = Param(nameof(RsiLength), 14)
			.SetDisplay("RSI Length", "RSI period.", "Indicators");
		_emaLength = Param(nameof(EmaLength), 25)
			.SetDisplay("EMA Length", "Trend filter.", "Indicators");
		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
	}

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
	public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
	public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevRsi = 0; _entryPrice = 0;
	}

		protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevRsi = 0; _entryPrice = 0;
		var rsi = new RelativeStrengthIndex { Length = RsiLength };
		var ema = new ExponentialMovingAverage { Length = EmaLength };
		var atr = new AverageTrueRange { Length = AtrLength };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(rsi, ema, atr, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, ema); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsiVal, decimal emaVal, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished) return;
		if (_prevRsi == 0 || atrVal <= 0) { _prevRsi = rsiVal; return; }
		var close = candle.ClosePrice;

		if (Position > 0)
		{
			if (close >= _entryPrice + atrVal * 2.5m || close <= _entryPrice - atrVal * 1.5m || rsiVal > 70) { SellMarket(); _entryPrice = 0; }
		}
		else if (Position < 0)
		{
			if (close <= _entryPrice - atrVal * 2.5m || close >= _entryPrice + atrVal * 1.5m || rsiVal < 30) { BuyMarket(); _entryPrice = 0; }
		}

		if (Position == 0)
		{
			if (rsiVal > 55 && _prevRsi <= 55 && close > emaVal) { _entryPrice = close; BuyMarket(); }
			else if (rsiVal < 45 && _prevRsi >= 45 && close < emaVal) { _entryPrice = close; SellMarket(); }
		}
		_prevRsi = rsiVal;
	}
}