Пересечение MA с тейк-профитом и стоп-лоссом
Стратегия открывает длинную позицию, когда быстрая SMA пересекает медленную снизу. Тейк-профит и стоп-лосс задаются в процентах и передвигаются при росте цены выше входа.
Параметры
- Fast MA Length
- Slow MA Length
- Take Profit %
- Stop Loss %
- Dynamic Take Profit %
- Dynamic Stop Loss %
- Candle Type
using System;
using System.Linq;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class MaCrossoverTpSlStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<decimal> _takeProfitPercent;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<DataType> _candleType;
private decimal _entryPrice;
private bool _wasFastLess;
private bool _initialized;
public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
public decimal TakeProfitPercent { get => _takeProfitPercent.Value; set => _takeProfitPercent.Value = value; }
public decimal StopLossPercent { get => _stopLossPercent.Value; set => _stopLossPercent.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MaCrossoverTpSlStrategy()
{
_fastLength = Param(nameof(FastLength), 5).SetGreaterThanZero();
_slowLength = Param(nameof(SlowLength), 12).SetGreaterThanZero();
_takeProfitPercent = Param(nameof(TakeProfitPercent), 10m).SetGreaterThanZero();
_stopLossPercent = Param(nameof(StopLossPercent), 5m).SetGreaterThanZero();
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_entryPrice = 0;
_wasFastLess = false;
_initialized = false;
var fastMa = new EMA { Length = FastLength };
var slowMa = new EMA { Length = SlowLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastMa, slowMa, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (!_initialized)
{
_wasFastLess = fast < slow;
_initialized = true;
return;
}
var isFastLess = fast < slow;
if (_wasFastLess && !isFastLess && Position <= 0)
{
_entryPrice = candle.ClosePrice;
BuyMarket();
}
if (Position > 0 && _entryPrice > 0)
{
var tp = _entryPrice * (1 + TakeProfitPercent / 100m);
var sl = _entryPrice * (1 - StopLossPercent / 100m);
if (candle.ClosePrice >= tp || candle.ClosePrice <= sl || (!_wasFastLess && isFastLess))
{
SellMarket();
_entryPrice = 0m;
}
}
_wasFastLess = isFastLess;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0m;
_wasFastLess = false;
_initialized = false;
}
}
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
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class ma_crossover_tp_sl_strategy(Strategy):
def __init__(self):
super(ma_crossover_tp_sl_strategy, self).__init__()
self._fast_length = self.Param("FastLength", 5) \
.SetGreaterThanZero()
self._slow_length = self.Param("SlowLength", 12) \
.SetGreaterThanZero()
self._take_profit_percent = self.Param("TakeProfitPercent", 10.0) \
.SetGreaterThanZero()
self._stop_loss_percent = self.Param("StopLossPercent", 5.0) \
.SetGreaterThanZero()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._entry_price = 0.0
self._was_fast_less = False
self._initialized = False
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(ma_crossover_tp_sl_strategy, self).OnReseted()
self._entry_price = 0.0
self._was_fast_less = False
self._initialized = False
def OnStarted2(self, time):
super(ma_crossover_tp_sl_strategy, self).OnStarted2(time)
self._entry_price = 0.0
self._was_fast_less = False
self._initialized = False
self._fast_ma = ExponentialMovingAverage()
self._fast_ma.Length = self._fast_length.Value
self._slow_ma = ExponentialMovingAverage()
self._slow_ma.Length = self._slow_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._fast_ma, self._slow_ma, self.OnProcess).Start()
def OnProcess(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
fv = float(fast)
sv = float(slow)
if not self._initialized:
self._was_fast_less = fv < sv
self._initialized = True
return
is_fast_less = fv < sv
close = float(candle.ClosePrice)
if self._was_fast_less and not is_fast_less and self.Position <= 0:
self._entry_price = close
self.BuyMarket()
if self.Position > 0 and self._entry_price > 0.0:
tp = self._entry_price * (1.0 + float(self._take_profit_percent.Value) / 100.0)
sl = self._entry_price * (1.0 - float(self._stop_loss_percent.Value) / 100.0)
if close >= tp or close <= sl or (not self._was_fast_less and is_fast_less):
self.SellMarket()
self._entry_price = 0.0
self._was_fast_less = is_fast_less
def CreateClone(self):
return ma_crossover_tp_sl_strategy()