Открыть на GitHub

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

Обзор

Стратегия переносит советник MetaTrader 4 «10points 3 v005» в инфраструктуру StockSharp. Направление определяется наклоном основной линии MACD: восходящее значение запускает длинную серию усреднений, нисходящее — короткую. В версии v005 добавлены временные фильтры, ограничения по капиталу и возможность отключить одну из сторон торговли.

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

  • Определить направление по сравнению текущего и предыдущего значения MACD. Параметр ReverseSignals позволяет инвертировать интерпретацию.
  • Открыть первую рыночную позицию сразу после появления сигнала. Далее добавлять ордера через каждые EntryDistancePips пунктов движения против открытой позиции.
  • Объём каждого последующего ордера рассчитывается по схеме мартингейла с множителем MartingaleFactor (или HighTradeFactor, если допускается больше 12 сделок). Объёмы округляются к шагу инструмента и ограничиваются 100 лотами.
  • При каждом входе обновляются общие уровни стоп-лосса и тейк-профита. Стартовые значения задаются параметрами InitialStopPips и TakeProfitPips, а трейлинг-стоп активируется после прохождения EntryDistancePips + TrailingStopPips пунктов.
  • Блок защиты капитала может выровнять целевой уровень по лучшей цене входа (ReboundLock) и закрыть последний ордер при достижении прибыли SecureProfit.
  • Дополнительные предохранители закрывают корзину при убытке StopLossAmount, превышении целевой прибыли ProfitTarget + ProfitBuffer или падении капитала ниже StartProtectionLevel.
  • Торговля ведётся только в интервале OpenHourCloseHour; по умолчанию работа по пятницам отключается (CloseOnFriday).

Управление капиталом

При выключенном UseMoneyManagement используется фиксированный объём LotSize. Если параметр активен, базовый объём вычисляется из текущей стоимости портфеля и RiskPercent. Переключатель IsStandardAccount задаёт расчёт для стандартного или мини-счёта.

Параметры

Параметр Описание
TakeProfitPips Расстояние тейк-профита для каждой позиции.
LotSize Базовый размер ордера при фиксированном объёме.
InitialStopPips Начальное расстояние стоп-лосса.
TrailingStopPips Расстояние трейлинг-стопа после активации.
MaxTrades Максимальное количество ордеров в корзине.
EntryDistancePips Минимальное движение против позиции для нового входа.
SecureProfit Порог плавающей прибыли (в валюте) для защитного выхода.
UseAccountProtection Включает блок защиты капитала.
OrdersToProtect Число последних ордеров, защищаемых правилом прибыли.
ReverseSignals Инверсия сигнала MACD.
UseMoneyManagement Включает расчёт объёма по капиталу.
RiskPercent Процент риска в формуле money management.
IsStandardAccount Использовать стандартный или мини-лот.
EurUsdPipValue и т.д. Стоимость пункта для расчёта прибыли.
CandleType Таймфрейм свечей для сигнала.
MacdFastLength, MacdSlowLength, MacdSignalLength Настройки MACD.
EnableLong, EnableShort Разрешение длинных/коротких корзин.
OpenHour, CloseHour, MinuteToStop Временное окно торговли.
StopLossProtection, StopLossAmount Глобальный стоп по капиталу.
ProfitTargetEnabled, ProfitTarget, ProfitBuffer Фиксация прибыли по капиталу.
StartProtectionEnabled, StartProtectionLevel Минимальный уровень капитала.
ReboundLock Выравнивание целей по лучшему входу.
MartingaleFactor, HighTradeFactor Множители мартингейла.
CloseOnFriday Отключение торговли по пятницам.

Примечания

  • Реализация использует высокоуровневый API StockSharp, что упрощает подписку на свечи и индикаторы.
  • Все защитные механизмы закрывают корзину рыночными заявками, имитируя логику оригинального советника.
  • Перед использованием на реальном счёте убедитесь, что параметры соответствуют спецификациям вашего брокера (шаг цены, стоимость пункта, допустимые объёмы).
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// 10 Points 3 V005: Dual EMA crossover with RSI confirmation and ATR stops.
/// </summary>
public class TenPoints3V005Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastEmaLength;
	private readonly StrategyParam<int> _slowEmaLength;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;

	public TenPoints3V005Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");
		_fastEmaLength = Param(nameof(FastEmaLength), 10)
			.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators");
		_slowEmaLength = Param(nameof(SlowEmaLength), 30)
			.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators");
		_rsiLength = Param(nameof(RsiLength), 14)
			.SetDisplay("RSI Length", "RSI period.", "Indicators");
		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
	}

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int FastEmaLength { get => _fastEmaLength.Value; set => _fastEmaLength.Value = value; }
	public int SlowEmaLength { get => _slowEmaLength.Value; set => _slowEmaLength.Value = value; }
	public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
	public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }

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

		_prevFast = 0; _prevSlow = 0; _entryPrice = 0;
	}

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

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

		if (Position > 0)
		{
			if ((fastVal < slowVal && _prevFast >= _prevSlow) || close <= _entryPrice - atrVal * 1.5m) { SellMarket(); _entryPrice = 0; }
		}
		else if (Position < 0)
		{
			if ((fastVal > slowVal && _prevFast <= _prevSlow) || close >= _entryPrice + atrVal * 1.5m) { BuyMarket(); _entryPrice = 0; }
		}

		if (Position == 0)
		{
			if (fastVal > slowVal && _prevFast <= _prevSlow && rsiVal > 50) { _entryPrice = close; BuyMarket(); }
			else if (fastVal < slowVal && _prevFast >= _prevSlow && rsiVal < 50) { _entryPrice = close; SellMarket(); }
		}
		_prevFast = fastVal; _prevSlow = slowVal;
	}
}