TCPivot Session Stop — это прямой порт советника MetaTrader 4 gpfTCPivotStop. Стратегия торгует вокруг классического дневного пивота, рассчитанного по данным предыдущего торгового дня. Логика включает:
Расчёт пивот-точки, трёх уровней сопротивления и поддержки на основании максимума, минимума и цены закрытия предыдущего дня.
Ожидание пробоя пивота: закрытие текущей свечи выше пивота (сигнал на покупку) или ниже пивота (сигнал на продажу).
Открытие рыночной позиции по направлению пробоя с установкой стоп-лосса и тейк-профита на выбранном уровне пивот-сетки.
При необходимости — принудительное закрытие позиции в начале заданного часа сессии, повторяющее поведение оригинального советника.
Реализация построена на высокоуровневом API StockSharp. Размер позиции определяется свойством Volume базового класса Strategy.
Параметры
Имя
Описание
Значение по умолчанию
TargetLevel
Уровень пивота, используемый для стоп-лосса и тейк-профита (1, 2 или 3).
1
CloseAtSessionStart
При включении закрывает позиции при наступлении указанного часа.
false
SessionCloseHour
Час (0-23), контролирующий закрытие при активном CloseAtSessionStart.
0
CandleType
Таймфрейм свечей, формирующих торговые сигналы.
H1
Логика торговли
Подписка на свечи выбранного таймфрейма для сигналов и на дневные свечи для расчёта пивот-уровней.
После закрытия каждой дневной свечи рассчитываются классические уровни пивота:
При завершении сигнальной свечи выполняются проверки:
Если CloseAtSessionStart включён и свеча открылась в SessionCloseHour, позиция немедленно закрывается.
При отсутствии позиции и пробое пивота вверх открывается покупка с целями, заданными TargetLevel.
При отсутствии позиции и пробое пивота вниз открывается продажа с зеркальными целями.
При наличии позиции выход выполняется при достижении цены стоп-лосса или тейк-профита.
Примечания
Вызов StartProtection() подключает встроенную систему риск-менеджмента платформы. Фактические выходы по стопу и профиту реализованы внутри стратегии.
В MetaTrader-версии присутствовали e-mail уведомления и динамический расчёт лота по риску. Эти возможности не перенесены; при необходимости используйте штатные модули StockSharp.
Пара CloseAtSessionStart + SessionCloseHour воспроизводит режим isTradeDay оригинального кода (значение 0 соответствует полуночи).
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class TcpPivotSessionStopStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast; private decimal _prevSlow; private bool _hasPrev;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public TcpPivotSessionStopStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 7).SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 21).SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = default;
_prevSlow = default;
_hasPrev = default;
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) return;
if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }
if (_cooldown > 0)
{
_cooldown--;
_prevFast = fast; _prevSlow = slow;
return;
}
if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
{
var volume = Volume + Math.Abs(Position);
BuyMarket(volume);
_cooldown = 2;
}
else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
{
var volume = Volume + Math.Abs(Position);
SellMarket(volume);
_cooldown = 2;
}
_prevFast = fast; _prevSlow = slow;
}
}