Sample SMA strategy
public class SmaChartStrategy : ChartStrategy { #region Private fields private readonly SMA _shortSma = new SMA(); private readonly SMA _longSma = new SMA(); private int _lastBar; #endregion #region Public properties [Display( Name = "Short period", Order = 10)] [Parameter] public int ShortPeriod { get => _shortSma.Period; set { _shortSma.Period = Math.Max(1, value); RecalculateValues(); } } [Display( Name = "Long period", Order = 20)] [Parameter] public int LongPeriod { get => _longSma.Period; set { _longSma.Period = Math.Max(1, value); RecalculateValues(); } } [Display( Name = "Volume", Order = 30)] [Parameter] public decimal Volume { get; set; } [Display(ResourceType = typeof(Resources), Name = "ClosePositionOnStopping", Order = 40)] [Parameter] public bool ClosePositionOnStopping { get; set; } #endregion #region ctor public SmaChartStrategy() { var firstSeries = (ValueDataSeries)DataSeries[0]; firstSeries.Name = "Short"; firstSeries.Color = Colors.Red; firstSeries.VisualType = VisualMode.Line; DataSeries.Add(new ValueDataSeries("Long") { VisualType = VisualMode.Line, Color = Colors.Green, }); ShortPeriod = 21; LongPeriod = 75; Volume = 1; ClosePositionOnStopping = true; } #endregion #region Overrides of BaseIndicator protected override void OnCalculate(int bar, decimal value) { var shortSma = _shortSma.Calculate(bar, value); var longSma = _longSma.Calculate(bar, value); DataSeries[0][bar] = shortSma; DataSeries[1][bar] = longSma; var prevBar = _lastBar; _lastBar = bar; if (!CanProcess(bar) || prevBar == bar) return; if (_shortSma[prevBar - 1] < _longSma[prevBar - 1] && _shortSma[prevBar] >= _longSma[prevBar]) { //cross up OpenPosition(OrderDirections.Buy); } if (_shortSma[prevBar - 1] > _longSma[prevBar - 1] && _shortSma[prevBar] <= _longSma[prevBar]) { //cross down OpenPosition(OrderDirections.Sell); } } protected override void OnStopping() { if (CurrentPosition != 0 && ClosePositionOnStopping) { RaiseShowNotification($"Closing current position {CurrentPosition} on stopping.", level: LoggingLevel.Warning); CloseCurrentPosition(); } base.OnStopping(); } #endregion #region Private methods private void OpenPosition(OrderDirections direction) { var order = new Order { Portfolio = Portfolio, Security = Security, Direction = direction, Type = OrderTypes.Market, QuantityToFill = GetOrderVolume(), }; OpenOrder(order); } private void CloseCurrentPosition() { var order = new Order { Portfolio = Portfolio, Security = Security, Direction = CurrentPosition > 0 ? OrderDirections.Sell : OrderDirections.Buy, Type = OrderTypes.Market, QuantityToFill = Math.Abs(CurrentPosition), }; OpenOrder(order); } private decimal GetOrderVolume() { if (CurrentPosition == 0) return Volume; if (CurrentPosition > 0) return Volume + CurrentPosition; return Volume + Math.Abs(CurrentPosition); } #endregion }
Сервис поддержки клиентов работает на платформе UserEcho