Стратегия Cross MA
Стратегия торгует пересечение двух простых скользящих средних и использует стоп-лосс на основе ATR. Лонг открывается, когда быстрая SMA пересекает медленную SMA снизу вверх. Шорт открывается при пересечении сверху вниз. После входа позиция защищается стопом на расстоянии одного значения ATR от цены входа, который проверяется на каждой новой свече.
Параметры
- Тип свечей
- Период быстрой SMA
- Период медленной SMA
- Период ATR
- Объём
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>
/// Strategy based on two SMA crossovers with ATR stop loss.
/// Buys when the fast SMA rises above the slow SMA and sells on opposite cross.
/// A stop loss is placed one ATR away from the entry price.
/// </summary>
public class CrossMAStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _atrPeriod;
private readonly StrategyParam<DataType> _candleType;
private int _lastSignal;
/// <summary>
/// Fast SMA period.
/// </summary>
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
/// <summary>
/// Slow SMA period.
/// </summary>
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
/// <summary>
/// ATR period for stop calculation.
/// </summary>
public int AtrPeriod
{
get => _atrPeriod.Value;
set => _atrPeriod.Value = value;
}
/// <summary>
/// Candle type for calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of the strategy.
/// </summary>
public CrossMAStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 5)
.SetGreaterThanZero()
.SetDisplay("Fast SMA Period", "Period of the fast SMA", "Parameters");
_slowPeriod = Param(nameof(SlowPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Slow SMA Period", "Period of the slow SMA", "Parameters");
_atrPeriod = Param(nameof(AtrPeriod), 6)
.SetGreaterThanZero()
.SetDisplay("ATR Period", "Period of ATR for stop calculation", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles for calculations", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_lastSignal = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastSma = new SimpleMovingAverage
{
Length = FastPeriod
};
var slowSma = new SimpleMovingAverage
{
Length = SlowPeriod
};
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastSma, slowSma, ProcessCandle)
.Start();
StartProtection(
new Unit(2000m, UnitTypes.Absolute),
new Unit(1000m, UnitTypes.Absolute));
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastSma);
DrawIndicator(area, slowSma);
DrawOwnTrades(area);
}
}
/// <summary>
/// Process candle and indicator values.
/// </summary>
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (fast > slow && candle.ClosePrice > slow && _lastSignal != 1 && Position <= 0)
{
BuyMarket();
_lastSignal = 1;
}
else if (fast < slow && candle.ClosePrice < slow && _lastSignal != -1 && Position >= 0)
{
SellMarket();
_lastSignal = -1;
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class cross_ma_strategy(Strategy):
def __init__(self):
super(cross_ma_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 5)
self._slow_period = self.Param("SlowPeriod", 20)
self._atr_period = self.Param("AtrPeriod", 6)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4)))
self._last_signal = 0
@property
def FastPeriod(self):
return self._fast_period.Value
@FastPeriod.setter
def FastPeriod(self, value):
self._fast_period.Value = value
@property
def SlowPeriod(self):
return self._slow_period.Value
@SlowPeriod.setter
def SlowPeriod(self, value):
self._slow_period.Value = value
@property
def AtrPeriod(self):
return self._atr_period.Value
@AtrPeriod.setter
def AtrPeriod(self, value):
self._atr_period.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(cross_ma_strategy, self).OnStarted2(time)
self._last_signal = 0
fast_sma = SimpleMovingAverage()
fast_sma.Length = self.FastPeriod
slow_sma = SimpleMovingAverage()
slow_sma.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast_sma, slow_sma, self.ProcessCandle).Start()
self.StartProtection(
Unit(2000.0, UnitTypes.Absolute),
Unit(1000.0, UnitTypes.Absolute))
def ProcessCandle(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast)
slow_val = float(slow)
close = float(candle.ClosePrice)
if fast_val > slow_val and close > slow_val and self._last_signal != 1 and self.Position <= 0:
self.BuyMarket()
self._last_signal = 1
elif fast_val < slow_val and close < slow_val and self._last_signal != -1 and self.Position >= 0:
self.SellMarket()
self._last_signal = -1
def OnReseted(self):
super(cross_ma_strategy, self).OnReseted()
self._last_signal = 0
def CreateClone(self):
return cross_ma_strategy()