在 GitHub 上查看

Daily Trend Reversal

概述

Daily Trend Reversal 是 MetaTrader 4 策略 dailyTrendReversal_D1 的移植版本。策略以当日的开盘价、最高价和最低价为参照,只在价格行为与商品通道指数(CCI)共同指向同一方向时参与交易。策略限定在可配置的 GMT 交易时段内执行,达到每日盈利目标后可以自动停止,并在过滤条件反向时立即平仓。

策略逻辑

日内偏向过滤

  • 阶梯过滤 —— 最多三个条件用于验证当天的趋势:
    1. 当前价格到当日极值的距离必须大于设定的风险阈值(以点为单位)。
    2. 当日开盘价到另一侧极值的距离也必须大于风险阈值,同时当前价格需保持在开盘价上下 10 点以内。
    3. (可选)当前 K 线需要在趋势方向上收盘,并且价格仍位于开盘价上下 10 点以内。
  • 区间主导 —— 比较开盘价到最高价与开盘价到最低价的距离,较长的一侧定义当前趋势。
  • CCI 趋势 —— 最近三个已完成的 CCI 数值需单调上升(做多)或单调下降(做空)。

入场规则

  • 做多
    • 仅在交易时段内且为工作日时启用。
    • 价格高于开盘价,阶梯过滤判定为上升趋势,区间主导与 CCI 同时指向上行。
    • 仅在当前净头寸为空或为空头时开多(若存在空头仓位,会在建多时反向买入平仓)。
  • 做空
    • 条件镜像:价格低于开盘价,阶梯过滤、区间主导和 CCI 均确认下行趋势。
    • 仅在净头寸为空或为多头时开空。

出场规则

  • 固定止盈 / 止损 —— 以点数定义相对入场价的距离,填 0 表示关闭。
  • 时段与持仓控制 —— 到达收盘时间或超过持仓时长后,盈利仓位立即平仓;亏损仓位进入保本模式,价格回到入场价即退出。
  • 反向平仓(可选) —— 启用后,当下行条件满足(价格跌破开盘价,日内和 CCI 均转空)时多单立即离场;空单规则相反。
  • 每日 Profit Stop —— 将当日已实现收益与浮动盈亏相加,达到阈值后全部平仓并暂停开仓,直至手动重新开启。

参数说明

  • Auto Trading —— 是否允许自动开仓。
  • Reversal Exit —— 是否在趋势反转时立即平仓。
  • Trend Steps —— 需要满足的过滤步骤数量(1–3)。
  • Volume —— 市价单的下单数量。
  • Take Profit (pips) —— 止盈距离,0 表示关闭。
  • Stop Loss (pips) —— 止损距离,0 表示关闭。
  • Profit Stop —— 每日盈利目标(价格单位),0 表示不限制。
  • GMT Diff —— 图表时间减去 GMT 的小时差,用于换算交易时段。
  • Start Hour / End Hour —— 允许开仓的 GMT 小时范围。
  • Closing Hour —— GMT 收盘小时,之后策略会平仓或转入保本模式。
  • Holding Hours —— 单笔交易允许的最长持仓时间。
  • Risk (pips) —— 阶梯过滤使用的风险阈值(点)。
  • CCI Period —— CCI 指标的周期长度。
  • Candle Type —— 计算所用的时间框架(默认 15 分钟 K 线)。

其他说明

  • 策略根据标的的最小报价步长自动识别点值,能够适配 5 位和 3 位报价的外汇品种。
  • 每个新交易日的第一根 K 线会重置当日盈亏基准,重新计算每日 Profit Stop。
  • 本目录仅提供 C# 实现,暂不包含 Python 版本。
using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Port of the MetaTrader strategy dailyTrendReversal_D1.
/// Combines daily open/high/low levels with a multi-step filter and CCI trend confirmation.
/// Applies strict session control, optional reversal exits, and a configurable daily profit stop.
/// </summary>
public class DailyTrendReversalStrategy : Strategy
{
	private readonly StrategyParam<bool> _enableAutoTrading;
	private readonly StrategyParam<bool> _enableReversal;
	private readonly StrategyParam<int> _trendSteps;
	private readonly StrategyParam<decimal> _takeProfitPips;
	private readonly StrategyParam<decimal> _stopLossPips;
	private readonly StrategyParam<decimal> _profitStop;
	private readonly StrategyParam<int> _gmtDiff;
	private readonly StrategyParam<int> _gmtStartHour;
	private readonly StrategyParam<int> _gmtEndHour;
	private readonly StrategyParam<int> _gmtClosingHour;
	private readonly StrategyParam<int> _holdingHours;
	private readonly StrategyParam<int> _riskPips;
	private readonly StrategyParam<int> _cciPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private CommodityChannelIndex _cci = null!;

	private readonly List<decimal> _cciHistory = new(3);

	private decimal _pipSize;
	private decimal _tenPips;

	private DateTime? _currentDay;
	private decimal _dailyOpen;
	private decimal _dailyHigh;
	private decimal _dailyLow;
	private decimal _dayPnLBase;

	private bool _tradingSuspended;

	private decimal _lastClose;
	private DateTimeOffset _lastCandleTime;

	private decimal _longEntryPrice;
	private DateTimeOffset? _longEntryTime;
	private decimal _longTakeProfitPrice;
	private decimal _longStopPrice;
	private bool _longBreakEvenActive;

	private decimal _shortEntryPrice;
	private DateTimeOffset? _shortEntryTime;
	private decimal _shortTakeProfitPrice;
	private decimal _shortStopPrice;
	private bool _shortBreakEvenActive;

	private DateTimeOffset _lastEntryTime;

	private enum TrendDirections
	{
		Flat,
		Up,
		Down,
	}

	/// <summary>
	/// Enables automated entries within the trading window.
	/// </summary>
	public bool EnableAutoTrading
	{
		get => _enableAutoTrading.Value;
		set => _enableAutoTrading.Value = value;
	}

	/// <summary>
	/// Enables closing positions when the opposite trend is confirmed.
	/// </summary>
	public bool EnableReversal
	{
		get => _enableReversal.Value;
		set => _enableReversal.Value = value;
	}

	/// <summary>
	/// Number of step filters applied to the daily trend evaluation.
	/// </summary>
	public int TrendSteps
	{
		get => _trendSteps.Value;
		set => _trendSteps.Value = value;
	}


	/// <summary>
	/// Take-profit distance expressed in pips.
	/// </summary>
	public decimal TakeProfitPips
	{
		get => _takeProfitPips.Value;
		set => _takeProfitPips.Value = value;
	}

	/// <summary>
	/// Stop-loss distance expressed in pips.
	/// </summary>
	public decimal StopLossPips
	{
		get => _stopLossPips.Value;
		set => _stopLossPips.Value = value;
	}

	/// <summary>
	/// Daily profit target that halts trading when reached (includes floating PnL).
	/// </summary>
	public decimal ProfitStop
	{
		get => _profitStop.Value;
		set => _profitStop.Value = value;
	}

	/// <summary>
	/// Difference between chart time and GMT in hours.
	/// </summary>
	public int GmtDiff
	{
		get => _gmtDiff.Value;
		set => _gmtDiff.Value = value;
	}

	/// <summary>
	/// GMT start hour of the active trading window.
	/// </summary>
	public int GmtStartHour
	{
		get => _gmtStartHour.Value;
		set => _gmtStartHour.Value = value;
	}

	/// <summary>
	/// GMT end hour for accepting new entries.
	/// </summary>
	public int GmtEndHour
	{
		get => _gmtEndHour.Value;
		set => _gmtEndHour.Value = value;
	}

	/// <summary>
	/// GMT hour when all trades should be protected or closed.
	/// </summary>
	public int GmtClosingHour
	{
		get => _gmtClosingHour.Value;
		set => _gmtClosingHour.Value = value;
	}

	/// <summary>
	/// Maximum holding time in hours before forcing exits.
	/// </summary>
	public int HoldingHours
	{
		get => _holdingHours.Value;
		set => _holdingHours.Value = value;
	}

	/// <summary>
	/// Risk threshold in pips used by the trend step filter.
	/// </summary>
	public int RiskPips
	{
		get => _riskPips.Value;
		set => _riskPips.Value = value;
	}

	/// <summary>
	/// Length of the Commodity Channel Index indicator.
	/// </summary>
	public int CciPeriod
	{
		get => _cciPeriod.Value;
		set => _cciPeriod.Value = value;
	}

	/// <summary>
	/// Candle type that drives the strategy calculations.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of the <see cref="DailyTrendReversalStrategy"/> class.
	/// </summary>
	public DailyTrendReversalStrategy()
	{
		_enableAutoTrading = Param(nameof(EnableAutoTrading), true)
		.SetDisplay("Auto Trading", "Enable automated entries inside the session", "Trading");

		_enableReversal = Param(nameof(EnableReversal), true)
		.SetDisplay("Reversal Exit", "Close positions on confirmed opposite trend", "Trading");

		_trendSteps = Param(nameof(TrendSteps), 3)
		.SetRange(0, 3)
		.SetDisplay("Trend Steps", "Number of filters used for daily direction", "Trend Filter");


		_takeProfitPips = Param(nameof(TakeProfitPips), 30m)
		.SetRange(0m, 1000m)
		.SetDisplay("Take Profit (pips)", "Distance to fixed take profit (0 disables)", "Risk");

		_stopLossPips = Param(nameof(StopLossPips), 0m)
		.SetRange(0m, 1000m)
		.SetDisplay("Stop Loss (pips)", "Distance to protective stop loss (0 disables)", "Risk");

		_profitStop = Param(nameof(ProfitStop), 100m)
		.SetRange(0m, 100000m)
		.SetDisplay("Profit Stop", "Daily profit target that pauses trading", "Risk");

		_gmtDiff = Param(nameof(GmtDiff), 0)
		.SetDisplay("GMT Diff", "Chart time minus GMT in hours", "Session");

		_gmtStartHour = Param(nameof(GmtStartHour), 5)
		.SetRange(0, 23)
		.SetDisplay("Start Hour", "Session start hour in GMT", "Session");

		_gmtEndHour = Param(nameof(GmtEndHour), 14)
		.SetRange(0, 23)
		.SetDisplay("End Hour", "Session end hour for new trades (GMT)", "Session");

		_gmtClosingHour = Param(nameof(GmtClosingHour), 18)
		.SetRange(0, 23)
		.SetDisplay("Closing Hour", "Session close hour for active trades (GMT)", "Session");

		_holdingHours = Param(nameof(HoldingHours), 10)
		.SetRange(0, 48)
		.SetDisplay("Holding Hours", "Maximum holding time for positions", "Risk");

		_riskPips = Param(nameof(RiskPips), 30)
		.SetRange(0, 1000)
		.SetDisplay("Risk (pips)", "Risk filter threshold used by trend steps", "Trend Filter");

		_cciPeriod = Param(nameof(CciPeriod), 15)
		.SetGreaterThanZero()
		.SetDisplay("CCI Period", "Length of the Commodity Channel Index", "Trend Filter");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
		.SetDisplay("Candle Type", "Primary timeframe for calculations", "General");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, CandleType);
	}

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

		_cciHistory.Clear();
		_pipSize = 0m;
		_tenPips = 0m;
		_currentDay = null;
		_dailyOpen = 0m;
		_dailyHigh = 0m;
		_dailyLow = 0m;
		_dayPnLBase = 0m;
		_tradingSuspended = false;
		_lastClose = 0m;
		_lastCandleTime = default;

		_longEntryPrice = 0m;
		_longEntryTime = null;
		_longTakeProfitPrice = 0m;
		_longStopPrice = 0m;
		_longBreakEvenActive = false;

		_shortEntryPrice = 0m;
		_shortEntryTime = null;
		_shortTakeProfitPrice = 0m;
		_shortStopPrice = 0m;
		_shortBreakEvenActive = false;

		_lastEntryTime = default;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_pipSize = GetPipSize();
		_tenPips = 10m * _pipSize;
		_dayPnLBase = PnL;
		_tradingSuspended = false;

		_cci = new CommodityChannelIndex
		{
			Length = CciPeriod,
		};

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

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

		StartProtection(null, null);
	}

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

		_lastCandleTime = candle.CloseTime;
		_lastClose = candle.ClosePrice;

		UpdateDailyLevels(candle);
		UpdateCciHistory(cciValue);

		var riskDistance = Math.Max(0, RiskPips) * _pipSize;
		var trend = GetDirectionalTrend(candle, riskDistance);
		var rangeTrend = GetRangeTrend();
		var cciTrend = GetCciTrend();

		ManageExistingPositions(candle, rangeTrend, cciTrend, riskDistance);
		HandleProfitStop();

		if (!CanOpenPositions(candle))
		return;

		if (!_cci.IsFormed)
		return;

		EvaluateEntries(candle, trend, rangeTrend, cciTrend);
	}

	private void EvaluateEntries(ICandleMessage candle, TrendDirections trend, TrendDirections rangeTrend, TrendDirections cciTrend)
	{
		if (_lastEntryTime != default && candle.CloseTime - _lastEntryTime < TimeSpan.FromHours(3))
			return;

		var price = candle.ClosePrice;

		if (trend == TrendDirections.Up && rangeTrend == TrendDirections.Up && cciTrend == TrendDirections.Up && price > _dailyOpen && Position <= 0m)
		{
			var volume = Volume + Math.Max(0m, -Position);
			if (volume > 0m)
			{
				BuyMarket(volume);
				_lastEntryTime = candle.CloseTime;
				LogInfo($"Enter long at {price} due to daily trend confirmation.");
			}
		}

		if (trend == TrendDirections.Down && rangeTrend == TrendDirections.Down && cciTrend == TrendDirections.Down && price < _dailyOpen && Position >= 0m)
		{
			var volume = Volume + Math.Max(0m, Position);
			if (volume > 0m)
			{
				SellMarket(volume);
				_lastEntryTime = candle.CloseTime;
				LogInfo($"Enter short at {price} due to daily trend confirmation.");
			}
		}
	}

	private void ManageExistingPositions(ICandleMessage candle, TrendDirections rangeTrend, TrendDirections cciTrend, decimal riskDistance)
	{
		if (Position > 0m)
		{
			ManageLongPosition(candle, rangeTrend, cciTrend, riskDistance);
		}
		else if (Position < 0m)
		{
			ManageShortPosition(candle, rangeTrend, cciTrend, riskDistance);
		}
	}

	private void ManageLongPosition(ICandleMessage candle, TrendDirections rangeTrend, TrendDirections cciTrend, decimal riskDistance)
	{
		var price = candle.ClosePrice;

		if (_longTakeProfitPrice > 0m && price >= _longTakeProfitPrice)
		{
			SellMarket(Position);
			LogInfo("Long take profit reached.");
			return;
		}

		if (_longStopPrice > 0m && price <= _longStopPrice)
		{
			SellMarket(Position);
			LogInfo("Long stop loss triggered.");
			return;
		}

		var holdingExceeded = HoldingHours > 0 && _longEntryTime is DateTimeOffset longEntry && candle.CloseTime - longEntry >= TimeSpan.FromHours(HoldingHours);
		var closingHourReached = GmtClosingHour > 0 && IsAfterOrEqualHour(candle.CloseTime, GmtClosingHour + GmtDiff);

		if ((holdingExceeded || closingHourReached) && _longEntryPrice != 0m)
		{
			if (price > _longEntryPrice)
			{
				SellMarket(Position);
				LogInfo("Long closed with profit due to session or holding limit.");
				return;
			}

			if (!_longBreakEvenActive)
			{
				_longBreakEvenActive = true;
				LogInfo("Long switched to break-even mode due to session or holding limit.");
			}
		}

		if (_longBreakEvenActive && _longEntryPrice != 0m && price >= _longEntryPrice)
		{
			SellMarket(Position);
			_longBreakEvenActive = false;
			LogInfo("Long closed at break-even after session limit.");
			return;
		}

		if (EnableReversal && _dailyOpen != 0m)
		{
			var step1 = TrendSteps >= 0 && price - _dailyLow > riskDistance;
			var step2 = TrendSteps >= 2 && _dailyHigh - _dailyOpen >= riskDistance && _dailyOpen - price <= _tenPips;

			if (price < _dailyOpen && (step1 || step2) && rangeTrend == TrendDirections.Down && cciTrend == TrendDirections.Down)
			{
				SellMarket(Position);
				LogInfo("Long reversed due to opposite trend confirmation.");
			}
		}
	}

	private void ManageShortPosition(ICandleMessage candle, TrendDirections rangeTrend, TrendDirections cciTrend, decimal riskDistance)
	{
		var price = candle.ClosePrice;

		if (_shortTakeProfitPrice > 0m && price <= _shortTakeProfitPrice)
		{
			BuyMarket(Math.Abs(Position));
			LogInfo("Short take profit reached.");
			return;
		}

		if (_shortStopPrice > 0m && price >= _shortStopPrice)
		{
			BuyMarket(Math.Abs(Position));
			LogInfo("Short stop loss triggered.");
			return;
		}

		var holdingExceeded = HoldingHours > 0 && _shortEntryTime is DateTimeOffset shortEntry && candle.CloseTime - shortEntry >= TimeSpan.FromHours(HoldingHours);
		var closingHourReached = GmtClosingHour > 0 && IsAfterOrEqualHour(candle.CloseTime, GmtClosingHour + GmtDiff);

		if ((holdingExceeded || closingHourReached) && _shortEntryPrice != 0m)
		{
			if (price < _shortEntryPrice)
			{
				BuyMarket(Math.Abs(Position));
				LogInfo("Short closed with profit due to session or holding limit.");
				return;
			}

			if (!_shortBreakEvenActive)
			{
				_shortBreakEvenActive = true;
				LogInfo("Short switched to break-even mode due to session or holding limit.");
			}
		}

		if (_shortBreakEvenActive && _shortEntryPrice != 0m && price <= _shortEntryPrice)
		{
			BuyMarket(Math.Abs(Position));
			_shortBreakEvenActive = false;
			LogInfo("Short closed at break-even after session limit.");
			return;
		}

		if (EnableReversal && _dailyOpen != 0m)
		{
			var step1 = TrendSteps >= 0 && _dailyHigh - price > riskDistance;
			var step2 = TrendSteps >= 2 && _dailyOpen - _dailyLow >= riskDistance && price - _dailyOpen <= _tenPips;

			if (price > _dailyOpen && (step1 || step2) && rangeTrend == TrendDirections.Up && cciTrend == TrendDirections.Up)
			{
				BuyMarket(Math.Abs(Position));
				LogInfo("Short reversed due to opposite trend confirmation.");
			}
		}
	}

	private void HandleProfitStop()
	{
		if (ProfitStop <= 0m || _tradingSuspended)
		return;

		var realized = PnL - _dayPnLBase;
		var floating = 0m;

		var total = realized + floating;

		if (total >= ProfitStop)
		{
			_tradingSuspended = true;
			if (Position > 0)
				SellMarket();
			else if (Position < 0)
				BuyMarket();
			LogInfo($"Trading suspended after reaching daily profit stop of {ProfitStop}.");
		}
	}

	private bool CanOpenPositions(ICandleMessage candle)
	{
		if (!EnableAutoTrading || _tradingSuspended)
		return false;

		if (_currentDay is null)
		return false;

		if (!IsWeekday(candle.OpenTime))
		return false;

		if (!IsWithinTradingWindow(candle.OpenTime))
		return false;

		return true;
	}

	private void UpdateDailyLevels(ICandleMessage candle)
	{
		var day = candle.OpenTime.Date;

		if (_currentDay != day)
		{
			_currentDay = day;
			_dailyOpen = candle.OpenPrice;
			_dailyHigh = candle.HighPrice;
			_dailyLow = candle.LowPrice;
			_dayPnLBase = PnL;
			_longBreakEvenActive = false;
			_shortBreakEvenActive = false;
		}
		else
		{
			_dailyHigh = Math.Max(_dailyHigh, candle.HighPrice);
			_dailyLow = Math.Min(_dailyLow, candle.LowPrice);
		}
	}

	private void UpdateCciHistory(decimal cciValue)
	{
		if (_cci.IsFormed)
		{
			_cciHistory.Insert(0, cciValue);
			if (_cciHistory.Count > 3)
			_cciHistory.RemoveAt(_cciHistory.Count - 1);
		}
	}

	private TrendDirections GetCciTrend()
	{
		if (_cciHistory.Count < 3)
		return TrendDirections.Flat;

		var current = _cciHistory[0];
		var previous = _cciHistory[1];
		var older = _cciHistory[2];

		if (current >= previous && previous >= older)
		return TrendDirections.Up;

		if (current <= previous && previous <= older)
		return TrendDirections.Down;

		return TrendDirections.Flat;
	}

	private TrendDirections GetDirectionalTrend(ICandleMessage candle, decimal riskDistance)
	{
		if (_currentDay is null)
		return TrendDirections.Flat;

		var price = candle.ClosePrice;

		if (price > _dailyOpen)
		{
			var step1 = TrendSteps >= 0 && _dailyHigh - price > riskDistance;
			var step2 = TrendSteps >= 2 && _dailyOpen - _dailyLow >= riskDistance && price - _dailyOpen <= _tenPips;
			var step3 = TrendSteps >= 3 && price - _dailyOpen <= _tenPips && candle.ClosePrice > candle.OpenPrice;

			if (step1 || step2 || step3)
			return TrendDirections.Up;
		}
		else if (price < _dailyOpen)
		{
			var step1 = TrendSteps >= 0 && price - _dailyLow > riskDistance;
			var step2 = TrendSteps >= 2 && _dailyHigh - _dailyOpen >= riskDistance && _dailyOpen - price <= _tenPips;
			var step3 = TrendSteps >= 3 && _dailyOpen - price <= _tenPips && candle.ClosePrice < candle.OpenPrice;

			if (step1 || step2 || step3)
			return TrendDirections.Down;
		}

		return TrendDirections.Flat;
	}

	private TrendDirections GetRangeTrend()
	{
		var upDistance = _dailyHigh - _dailyOpen;
		var downDistance = _dailyOpen - _dailyLow;

		if (upDistance > downDistance)
		return TrendDirections.Up;

		if (upDistance < downDistance)
		return TrendDirections.Down;

		return TrendDirections.Flat;
	}

	private bool IsWeekday(DateTimeOffset time)
	{
		var day = time.DayOfWeek;
		return day is not DayOfWeek.Saturday and not DayOfWeek.Sunday;
	}

	private bool IsWithinTradingWindow(DateTimeOffset time)
	{
		var hour = time.Hour;
		var start = NormalizeHour(GmtStartHour + GmtDiff);
		var end = NormalizeHour(GmtEndHour + GmtDiff);

		if (start == end)
		return false;

		return start < end ? hour >= start && hour < end : hour >= start || hour < end;
	}

	private bool IsAfterOrEqualHour(DateTimeOffset time, int targetHour)
	{
		var hour = time.Hour;
		var normalizedTarget = NormalizeHour(targetHour);
		return hour >= normalizedTarget;
	}

	private static int NormalizeHour(int hour)
	{
		var normalized = hour % 24;
		return normalized < 0 ? normalized + 24 : normalized;
	}

	private decimal GetPipSize()
	{
		var step = Security.PriceStep ?? 0.0001m;
		var decimals = Security.Decimals ?? 0;

		if (decimals >= 3)
		return step * 10m;

		return step > 0m ? step : 0.0001m;
	}

	/// <inheritdoc />
	protected override void OnPositionReceived(Position position)
	{
		base.OnPositionReceived(position);

		if (Position > 0m)
		{
			_longEntryPrice = _lastClose;
			_longEntryTime = _lastCandleTime;
			_longTakeProfitPrice = TakeProfitPips > 0m ? _longEntryPrice + TakeProfitPips * _pipSize : 0m;
			_longStopPrice = StopLossPips > 0m ? _longEntryPrice - StopLossPips * _pipSize : 0m;
			_longBreakEvenActive = false;
		}
		else
		{
			_longEntryTime = null;
			_longTakeProfitPrice = 0m;
			_longStopPrice = 0m;
			if (Position <= 0m)
			_longEntryPrice = 0m;
		}

		if (Position < 0m)
		{
			_shortEntryPrice = _lastClose;
			_shortEntryTime = _lastCandleTime;
			_shortTakeProfitPrice = TakeProfitPips > 0m ? _shortEntryPrice - TakeProfitPips * _pipSize : 0m;
			_shortStopPrice = StopLossPips > 0m ? _shortEntryPrice + StopLossPips * _pipSize : 0m;
			_shortBreakEvenActive = false;
		}
		else
		{
			_shortEntryTime = null;
			_shortTakeProfitPrice = 0m;
			_shortStopPrice = 0m;
			if (Position >= 0m)
			_shortEntryPrice = 0m;
		}
	}
}