在 GitHub 上查看

EA Moving Average 策略

概览

  • 由 MetaTrader 专家顾问 “EA Moving Average”(barabashkakvn 版)移植而来。
  • 使用四条可配置的移动平均线分别负责多空进场与离场判断。
  • 适用于单品种、净额结算账户。默认使用 15 分钟K线,可根据需要选择其他标准K线类型。
  • 策略始终只保留一张持仓;持仓期间仅检查离场条件,不会反向加仓。

交易逻辑

做多进场

  1. 当前K线开盘价在 Buy Open 均线之下、收盘价突破到均线上方(单根K线完成金叉)。
  2. UseBuy 为真。
  3. 若启用 ConsiderPriceLastOut,当前价格必须小于或等于上一次平仓价格,避免在更高价位追多。
  4. 条件满足时按风险模型计算的仓位执行市价买单。

做多离场

  1. 仅在存在多头仓位时生效。
  2. K线开在 Buy Close 均线上方,收盘跌回其下方(死叉信号)。
  3. 触发后立即以市价全量平仓。

做空进场

  1. 当前K线开盘在 Sell Open 均线上方,收盘跌破均线。
  2. UseSell 为真。
  3. 若启用 ConsiderPriceLastOut,当前价格必须大于或等于上一次平仓价格,避免在更低价位追空。
  4. 条件满足时按风险模型执行市价卖单。

做空离场

  1. 仅在存在空头仓位时生效。
  2. K线开盘位于 Sell Close 均线下方、收盘站回其上方。
  3. 触发后市价全量回补。

风险与仓位管理

  • MaximumRisk 表示每笔交易可承受的账户资金比例。策略将该比例乘以投资组合市值并除以当前价格,得到基础下单数量。
  • DecreaseFactor 模拟原版EA的“亏损递减”逻辑:连续两笔及以上亏损后,根据亏损次数与 DecreaseFactor 的比值按比例减小下单数量。
  • 计算出的数量会根据品种的最小成交量步长取整,且不低于一个步长;若风险计算失败,则回退到策略的 Volume 属性(默认 1 手)。

参数

参数 默认值 说明
MaximumRisk 0.02 单笔交易风险占账户净值的比例。
DecreaseFactor 3 连续亏损后减少仓位的系数,0 表示不启用。
BuyOpenPeriod 30 多头进场均线的周期。
BuyOpenShift 3 多头进场均线向前平移的K线数量。
BuyOpenMethod Exponential 多头进场均线的类型(SimpleExponentialSmoothedLinearWeighted)。
BuyOpenPrice Close 多头进场均线使用的价格。
BuyClosePeriod 14 多头离场均线周期。
BuyCloseShift 3 多头离场均线的平移值。
BuyCloseMethod Exponential 多头离场均线类型。
BuyClosePrice Close 多头离场均线使用的价格。
SellOpenPeriod 30 空头进场均线周期。
SellOpenShift 0 空头进场均线平移。
SellOpenMethod Exponential 空头进场均线类型。
SellOpenPrice Close 空头进场均线使用的价格。
SellClosePeriod 20 空头离场均线周期。
SellCloseShift 2 空头离场均线平移。
SellCloseMethod Exponential 空头离场均线类型。
SellClosePrice Close 空头离场均线使用的价格。
UseBuy true 是否允许做多。
UseSell true 是否允许做空。
ConsiderPriceLastOut true 新开仓前是否需要相对上次平仓获得更优价格。
CandleType 15 分钟K线 参与计算的K线类型。

额外说明

  • 最新一次平仓价格与连续亏损计数来自真实成交回报,复现了原 EA 的行为。
  • StockSharp 在K线收盘时触发逻辑,因此进场价格过滤使用的是收盘价,对应原代码中基于实时买卖价的判断。
  • 策略假设账户为净额模式,不支持同时持有多空仓位。
  • 建议先在历史数据或模拟环境中验证参数,再投入实盘。
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;
using Ecng.Logging;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Conversion of the "EA Moving Average" MetaTrader strategy.
/// Uses four configurable moving averages to define entry and exit rules for long and short trades.
/// Risk per trade is managed through a fixed percentage of account equity with optional lot reduction after consecutive losses.
/// </summary>
public class EaMovingAverageStrategy : Strategy
{
	/// <summary>
	/// Moving average calculation methods supported by the strategy.
	/// </summary>
	public enum MaMethods
	{
		Simple,
		Exponential,
		Smoothed,
		LinearWeighted
	}

	/// <summary>
	/// Price inputs supported by the moving average calculations.
	/// </summary>
	public enum MaPriceTypes
	{
		Close,
		Open,
		High,
		Low,
		Median,
		Typical,
		Weighted
	}
	private readonly StrategyParam<decimal> _maximumRisk;
	private readonly StrategyParam<decimal> _decreaseFactor;

	private readonly StrategyParam<int> _buyOpenPeriod;
	private readonly StrategyParam<int> _buyOpenShift;
	private readonly StrategyParam<MaMethods> _buyOpenMethod;
	private readonly StrategyParam<MaPriceTypes> _buyOpenPrice;

	private readonly StrategyParam<int> _buyClosePeriod;
	private readonly StrategyParam<int> _buyCloseShift;
	private readonly StrategyParam<MaMethods> _buyCloseMethod;
	private readonly StrategyParam<MaPriceTypes> _buyClosePrice;

	private readonly StrategyParam<int> _sellOpenPeriod;
	private readonly StrategyParam<int> _sellOpenShift;
	private readonly StrategyParam<MaMethods> _sellOpenMethod;
	private readonly StrategyParam<MaPriceTypes> _sellOpenPrice;

	private readonly StrategyParam<int> _sellClosePeriod;
	private readonly StrategyParam<int> _sellCloseShift;
	private readonly StrategyParam<MaMethods> _sellCloseMethod;
	private readonly StrategyParam<MaPriceTypes> _sellClosePrice;

	private readonly StrategyParam<bool> _useBuy;
	private readonly StrategyParam<bool> _useSell;
	private readonly StrategyParam<bool> _considerPriceLastOut;
	private readonly StrategyParam<DataType> _candleType;

	private DecimalLengthIndicator _buyOpenMa;
	private DecimalLengthIndicator _buyCloseMa;
	private DecimalLengthIndicator _sellOpenMa;
	private DecimalLengthIndicator _sellCloseMa;

	private readonly Queue<decimal> _buyOpenBuffer = new();
	private readonly Queue<decimal> _buyCloseBuffer = new();
	private readonly Queue<decimal> _sellOpenBuffer = new();
	private readonly Queue<decimal> _sellCloseBuffer = new();

	private decimal _lastExitPrice;
	private decimal _lastEntryPrice;
	private Sides? _lastEntrySide;
	private decimal _signedPosition;
	private int _consecutiveLosses;

	/// <summary>
	/// Initializes a new instance of the <see cref="EaMovingAverageStrategy"/> class.
	/// </summary>
	public EaMovingAverageStrategy()
	{
		_maximumRisk = Param(nameof(MaximumRisk), 0.02m)
			.SetNotNegative()
			.SetDisplay("Maximum Risk", "Risk per trade as part of equity", "Risk");

		_decreaseFactor = Param(nameof(DecreaseFactor), 3m)
			.SetNotNegative()
			.SetDisplay("Decrease Factor", "Lot reduction factor after losses", "Risk");

		_buyOpenPeriod = Param(nameof(BuyOpenPeriod), 30)
			.SetGreaterThanZero()
			.SetDisplay("Buy Open MA Period", "Moving average period for buy entries", "Buy Entry")
			
			.SetOptimize(5, 80, 5);

		_buyOpenShift = Param(nameof(BuyOpenShift), 3)
			.SetNotNegative()
			.SetDisplay("Buy Open MA Shift", "Shift in bars for the buy entry MA", "Buy Entry");

		_buyOpenMethod = Param(nameof(BuyOpenMethod), MaMethods.Exponential)
			.SetDisplay("Buy Open MA Method", "Moving average method for buy entries", "Buy Entry");

		_buyOpenPrice = Param(nameof(BuyOpenPrice), MaPriceTypes.Close)
			.SetDisplay("Buy Open Price", "Price type supplied to the buy entry MA", "Buy Entry");

		_buyClosePeriod = Param(nameof(BuyClosePeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("Buy Close MA Period", "Moving average period for buy exits", "Buy Exit")
			
			.SetOptimize(5, 60, 5);

		_buyCloseShift = Param(nameof(BuyCloseShift), 3)
			.SetNotNegative()
			.SetDisplay("Buy Close MA Shift", "Shift in bars for the buy exit MA", "Buy Exit");

		_buyCloseMethod = Param(nameof(BuyCloseMethod), MaMethods.Exponential)
			.SetDisplay("Buy Close MA Method", "Moving average method for buy exits", "Buy Exit");

		_buyClosePrice = Param(nameof(BuyClosePrice), MaPriceTypes.Close)
			.SetDisplay("Buy Close Price", "Price type supplied to the buy exit MA", "Buy Exit");

		_sellOpenPeriod = Param(nameof(SellOpenPeriod), 30)
			.SetGreaterThanZero()
			.SetDisplay("Sell Open MA Period", "Moving average period for sell entries", "Sell Entry")
			
			.SetOptimize(5, 80, 5);

		_sellOpenShift = Param(nameof(SellOpenShift), 0)
			.SetNotNegative()
			.SetDisplay("Sell Open MA Shift", "Shift in bars for the sell entry MA", "Sell Entry");

		_sellOpenMethod = Param(nameof(SellOpenMethod), MaMethods.Exponential)
			.SetDisplay("Sell Open MA Method", "Moving average method for sell entries", "Sell Entry");

		_sellOpenPrice = Param(nameof(SellOpenPrice), MaPriceTypes.Close)
			.SetDisplay("Sell Open Price", "Price type supplied to the sell entry MA", "Sell Entry");

		_sellClosePeriod = Param(nameof(SellClosePeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("Sell Close MA Period", "Moving average period for sell exits", "Sell Exit")
			
			.SetOptimize(5, 80, 5);

		_sellCloseShift = Param(nameof(SellCloseShift), 2)
			.SetNotNegative()
			.SetDisplay("Sell Close MA Shift", "Shift in bars for the sell exit MA", "Sell Exit");

		_sellCloseMethod = Param(nameof(SellCloseMethod), MaMethods.Exponential)
			.SetDisplay("Sell Close MA Method", "Moving average method for sell exits", "Sell Exit");

		_sellClosePrice = Param(nameof(SellClosePrice), MaPriceTypes.Close)
			.SetDisplay("Sell Close Price", "Price type supplied to the sell exit MA", "Sell Exit");

		_useBuy = Param(nameof(UseBuy), true)
			.SetDisplay("Use Buy", "Enable long trades", "General");

		_useSell = Param(nameof(UseSell), true)
			.SetDisplay("Use Sell", "Enable short trades", "General");

		_considerPriceLastOut = Param(nameof(ConsiderPriceLastOut), true)
			.SetDisplay("Consider Last Exit Price", "Require price improvement before re-entry", "General");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles processed by the strategy", "General");
	}

	/// <summary>
	/// Risk per trade as a fraction of the portfolio equity.
	/// </summary>
	public decimal MaximumRisk
	{
		get => _maximumRisk.Value;
		set => _maximumRisk.Value = value;
	}

	/// <summary>
	/// Lot reduction factor after consecutive losing trades.
	/// </summary>
	public decimal DecreaseFactor
	{
		get => _decreaseFactor.Value;
		set => _decreaseFactor.Value = value;
	}

	/// <summary>
	/// Moving average period for buy entries.
	/// </summary>
	public int BuyOpenPeriod
	{
		get => _buyOpenPeriod.Value;
		set => _buyOpenPeriod.Value = value;
	}

	/// <summary>
	/// Shift in bars for the buy entry moving average.
	/// </summary>
	public int BuyOpenShift
	{
		get => _buyOpenShift.Value;
		set => _buyOpenShift.Value = value;
	}

	/// <summary>
	/// Moving average method for buy entries.
	/// </summary>
	public MaMethods BuyOpenMethod
	{
		get => _buyOpenMethod.Value;
		set => _buyOpenMethod.Value = value;
	}

	/// <summary>
	/// Price type used for the buy entry moving average.
	/// </summary>
	public MaPriceTypes BuyOpenPrice
	{
		get => _buyOpenPrice.Value;
		set => _buyOpenPrice.Value = value;
	}

	/// <summary>
	/// Moving average period for buy exits.
	/// </summary>
	public int BuyClosePeriod
	{
		get => _buyClosePeriod.Value;
		set => _buyClosePeriod.Value = value;
	}

	/// <summary>
	/// Shift in bars for the buy exit moving average.
	/// </summary>
	public int BuyCloseShift
	{
		get => _buyCloseShift.Value;
		set => _buyCloseShift.Value = value;
	}

	/// <summary>
	/// Moving average method for buy exits.
	/// </summary>
	public MaMethods BuyCloseMethod
	{
		get => _buyCloseMethod.Value;
		set => _buyCloseMethod.Value = value;
	}

	/// <summary>
	/// Price type used for the buy exit moving average.
	/// </summary>
	public MaPriceTypes BuyClosePrice
	{
		get => _buyClosePrice.Value;
		set => _buyClosePrice.Value = value;
	}

	/// <summary>
	/// Moving average period for sell entries.
	/// </summary>
	public int SellOpenPeriod
	{
		get => _sellOpenPeriod.Value;
		set => _sellOpenPeriod.Value = value;
	}

	/// <summary>
	/// Shift in bars for the sell entry moving average.
	/// </summary>
	public int SellOpenShift
	{
		get => _sellOpenShift.Value;
		set => _sellOpenShift.Value = value;
	}

	/// <summary>
	/// Moving average method for sell entries.
	/// </summary>
	public MaMethods SellOpenMethod
	{
		get => _sellOpenMethod.Value;
		set => _sellOpenMethod.Value = value;
	}

	/// <summary>
	/// Price type used for the sell entry moving average.
	/// </summary>
	public MaPriceTypes SellOpenPrice
	{
		get => _sellOpenPrice.Value;
		set => _sellOpenPrice.Value = value;
	}

	/// <summary>
	/// Moving average period for sell exits.
	/// </summary>
	public int SellClosePeriod
	{
		get => _sellClosePeriod.Value;
		set => _sellClosePeriod.Value = value;
	}

	/// <summary>
	/// Shift in bars for the sell exit moving average.
	/// </summary>
	public int SellCloseShift
	{
		get => _sellCloseShift.Value;
		set => _sellCloseShift.Value = value;
	}

	/// <summary>
	/// Moving average method for sell exits.
	/// </summary>
	public MaMethods SellCloseMethod
	{
		get => _sellCloseMethod.Value;
		set => _sellCloseMethod.Value = value;
	}

	/// <summary>
	/// Price type used for the sell exit moving average.
	/// </summary>
	public MaPriceTypes SellClosePrice
	{
		get => _sellClosePrice.Value;
		set => _sellClosePrice.Value = value;
	}

	/// <summary>
	/// Enable long trades.
	/// </summary>
	public bool UseBuy
	{
		get => _useBuy.Value;
		set => _useBuy.Value = value;
	}

	/// <summary>
	/// Enable short trades.
	/// </summary>
	public bool UseSell
	{
		get => _useSell.Value;
		set => _useSell.Value = value;
	}

	/// <summary>
	/// Require price improvement relative to the last exit before re-entering.
	/// </summary>
	public bool ConsiderPriceLastOut
	{
		get => _considerPriceLastOut.Value;
		set => _considerPriceLastOut.Value = value;
	}

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

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

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

		_buyOpenBuffer.Clear();
		_buyCloseBuffer.Clear();
		_sellOpenBuffer.Clear();
		_sellCloseBuffer.Clear();

		_lastExitPrice = 0m;
		_lastEntryPrice = 0m;
		_lastEntrySide = null;
		_signedPosition = 0m;
		_consecutiveLosses = 0;
	}

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

		_buyOpenMa = CreateMovingAverage(BuyOpenMethod, BuyOpenPeriod);
		_buyCloseMa = CreateMovingAverage(BuyCloseMethod, BuyClosePeriod);
		_sellOpenMa = CreateMovingAverage(SellOpenMethod, SellOpenPeriod);
		_sellCloseMa = CreateMovingAverage(SellCloseMethod, SellClosePeriod);

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

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

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

		var buyOpen = ProcessMovingAverage(_buyOpenMa, _buyOpenBuffer, BuyOpenShift, GetPrice(candle, BuyOpenPrice), candle);
		var buyClose = ProcessMovingAverage(_buyCloseMa, _buyCloseBuffer, BuyCloseShift, GetPrice(candle, BuyClosePrice), candle);
		var sellOpen = ProcessMovingAverage(_sellOpenMa, _sellOpenBuffer, SellOpenShift, GetPrice(candle, SellOpenPrice), candle);
		var sellClose = ProcessMovingAverage(_sellCloseMa, _sellCloseBuffer, SellCloseShift, GetPrice(candle, SellClosePrice), candle);

		if (buyOpen is not decimal buyOpenValue ||
			buyClose is not decimal buyCloseValue ||
			sellOpen is not decimal sellOpenValue ||
			sellClose is not decimal sellCloseValue)
		{
			return;
		}


		if (Position != 0)
		{
			ProcessCloseSignal(candle, buyCloseValue, sellCloseValue);
		}
		else
		{
			ProcessOpenSignal(candle, buyOpenValue, sellOpenValue);
		}
	}

	private void ProcessOpenSignal(ICandleMessage candle, decimal buyMa, decimal sellMa)
	{
		var openPrice = candle.OpenPrice;
		var closePrice = candle.ClosePrice;

		if (UseBuy && openPrice < buyMa && closePrice > buyMa && CanReEnter(Sides.Buy, closePrice))
		{
			var volume = CalculateTradeVolume(closePrice);
			if (volume > 0)
			{
				BuyMarket(volume);
				this.AddInfoLog($"Buy signal. Close={closePrice}, MA={buyMa}, Volume={volume}");
			}
		}
		else if (UseSell && openPrice > sellMa && closePrice < sellMa && CanReEnter(Sides.Sell, closePrice))
		{
			var volume = CalculateTradeVolume(closePrice);
			if (volume > 0)
			{
				SellMarket(volume);
				this.AddInfoLog($"Sell signal. Close={closePrice}, MA={sellMa}, Volume={volume}");
			}
		}
	}

	private void ProcessCloseSignal(ICandleMessage candle, decimal buyMa, decimal sellMa)
	{
		var openPrice = candle.OpenPrice;
		var closePrice = candle.ClosePrice;

		if (Position > 0 && openPrice > buyMa && closePrice < buyMa)
		{
			if (Position > 0) SellMarket(Position); else if (Position < 0) BuyMarket(-Position);
			this.AddInfoLog($"Close long. Close={closePrice}, MA={buyMa}");
		}
		else if (Position < 0 && openPrice < sellMa && closePrice > sellMa)
		{
			if (Position > 0) SellMarket(Position); else if (Position < 0) BuyMarket(-Position);
			this.AddInfoLog($"Close short. Close={closePrice}, MA={sellMa}");
		}
	}

	private bool CanReEnter(Sides side, decimal price)
	{
		if (!ConsiderPriceLastOut)
			return true;

		if (_lastExitPrice == 0m)
			return true;

		return side == Sides.Buy
			? _lastExitPrice >= price
			: _lastExitPrice <= price;
	}

	private decimal? ProcessMovingAverage(DecimalLengthIndicator indicator, Queue<decimal> buffer, int shift, decimal price, ICandleMessage candle)
	{
		if (indicator == null)
			return null;

		var value = indicator.Process(new DecimalIndicatorValue(indicator, price, candle.OpenTime) { IsFinal = true });

		if (!indicator.IsFormed)
			return null;

		var maValue = value.ToDecimal();

		buffer.Enqueue(maValue);
		var maxSize = shift + 1;
		while (buffer.Count > maxSize)
			buffer.Dequeue();

		if (buffer.Count < maxSize)
			return null;

		return shift == 0 ? maValue : buffer.Peek();
	}

	private decimal CalculateTradeVolume(decimal price)
	{
		var baseVolume = Volume > 0 ? Volume : 1m;

		if (price <= 0)
			return NormalizeVolume(baseVolume);

		var equity = Portfolio?.BeginValue ?? 0m;
		if (equity <= 0)
			return NormalizeVolume(baseVolume);

		var volume = equity * MaximumRisk / price;

		if (DecreaseFactor > 0 && _consecutiveLosses > 1)
		{
			var reduction = volume * _consecutiveLosses / DecreaseFactor;
			volume -= reduction;
		}

		if (volume <= 0)
			volume = baseVolume;

		return NormalizeVolume(volume);
	}

	private decimal NormalizeVolume(decimal volume)
	{
		var security = Security;
		if (security != null)
		{
			var step = security.VolumeStep ?? 1m;
			if (step <= 0)
				step = 1m;

			if (volume < step)
				volume = step;

			var steps = Math.Floor(volume / step);
			if (steps < 1m)
				steps = 1m;

			volume = steps * step;
		}

		if (volume <= 0)
			volume = 1m;

		return volume;
	}

	private static decimal GetPrice(ICandleMessage candle, MaPriceTypes priceType)
	{
		return priceType switch
		{
			MaPriceTypes.Close => candle.ClosePrice,
			MaPriceTypes.Open => candle.OpenPrice,
			MaPriceTypes.High => candle.HighPrice,
			MaPriceTypes.Low => candle.LowPrice,
			MaPriceTypes.Median => (candle.HighPrice + candle.LowPrice) / 2m,
			MaPriceTypes.Typical => (candle.HighPrice + candle.LowPrice + candle.ClosePrice) / 3m,
			MaPriceTypes.Weighted => (candle.HighPrice + candle.LowPrice + (2m * candle.ClosePrice)) / 4m,
			_ => candle.ClosePrice
		};
	}

	private static DecimalLengthIndicator CreateMovingAverage(MaMethods method, int length)
	{
		return method switch
		{
			MaMethods.Simple => new SimpleMovingAverage { Length = length },
			MaMethods.Exponential => new ExponentialMovingAverage { Length = length },
			MaMethods.Smoothed => new SmoothedMovingAverage { Length = length },
			MaMethods.LinearWeighted => new WeightedMovingAverage { Length = length },
			_ => new SimpleMovingAverage { Length = length }
		};
	}

	/// <inheritdoc />
	protected override void OnOwnTradeReceived(MyTrade trade)
	{
		base.OnOwnTradeReceived(trade);

		var volume = trade.Trade.Volume;
		if (volume <= 0)
			return;

		var delta = trade.Order.Side == Sides.Buy ? volume : -volume;
		var previousPosition = _signedPosition;
		_signedPosition += delta;

		if (previousPosition == 0m && _signedPosition != 0m)
		{
			_lastEntrySide = delta > 0m ? Sides.Buy : Sides.Sell;
			_lastEntryPrice = trade.Trade.Price;
		}
		else if (previousPosition != 0m && _signedPosition == 0m)
		{
			_lastExitPrice = trade.Trade.Price;

			if (_lastEntrySide != null && _lastEntryPrice != 0m)
			{
				var profit = _lastEntrySide == Sides.Buy
					? _lastExitPrice - _lastEntryPrice
					: _lastEntryPrice - _lastExitPrice;

				if (profit > 0m)
				{
					_consecutiveLosses = 0;
				}
				else if (profit < 0m)
				{
					_consecutiveLosses++;
				}
			}

			_lastEntrySide = null;
			_lastEntryPrice = 0m;
		}
	}
}