Sample SMA strategy

Modified on Fri, 04 Aug 2023 at 02:21 PM

Sources from this sample


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
         }

 

Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select atleast one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article