MA-Ausbruch von Hochs und Tiefs
Preisaktionsstrategie, die Long einsteigt, wenn der Preis über einem gleitenden Durchschnitt der Hochs schließt, und Short einsteigt, wenn der Preis unter einem gleitenden Durchschnitt der Tiefs schließt. Positionen werden mit optionalen Take-Profit- und Stop-Loss-Niveaus verwaltet.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy based on price crossing moving averages of highs and lows.
/// Buys when price closes above the high-based moving average and sells when closing below the low-based moving average.
/// </summary>
public class HighLowMaBreakoutStrategy : Strategy
{
private readonly StrategyParam<int> _maHighPeriod;
private readonly StrategyParam<int> _maLowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevMaHigh;
private decimal _prevMaLow;
private decimal _prevClose;
private bool _hasPrev;
public int MaHighPeriod { get => _maHighPeriod.Value; set => _maHighPeriod.Value = value; }
public int MaLowPeriod { get => _maLowPeriod.Value; set => _maLowPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public HighLowMaBreakoutStrategy()
{
_maHighPeriod = Param(nameof(MaHighPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("High MA Period", "Period of high price MA", "Parameters");
_maLowPeriod = Param(nameof(MaLowPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Low MA Period", "Period of low price MA", "Parameters");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevMaHigh = 0;
_prevMaLow = 0;
_prevClose = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var maHigh = new SimpleMovingAverage { Length = MaHighPeriod };
var maLow = new SimpleMovingAverage { Length = MaLowPeriod };
SubscribeCandles(CandleType).Bind(maHigh, maLow, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal maHigh, decimal maLow)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
if (!_hasPrev)
{
_prevClose = close;
_prevMaHigh = maHigh;
_prevMaLow = maLow;
_hasPrev = true;
return;
}
// Cross above high MA => buy
if (_prevClose <= _prevMaHigh && close > maHigh && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
// Cross below low MA => sell
else if (_prevClose >= _prevMaLow && close < maLow && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevClose = close;
_prevMaHigh = maHigh;
_prevMaLow = maLow;
}
}
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class high_low_ma_breakout_strategy(Strategy):
def __init__(self):
super(high_low_ma_breakout_strategy, self).__init__()
self._ma_high_period = self.Param("MaHighPeriod", 14) \
.SetDisplay("High MA Period", "Period of high price MA", "Parameters")
self._ma_low_period = self.Param("MaLowPeriod", 10) \
.SetDisplay("Low MA Period", "Period of low price MA", "Parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._prev_ma_high = 0.0
self._prev_ma_low = 0.0
self._prev_close = 0.0
self._has_prev = False
@property
def ma_high_period(self):
return self._ma_high_period.Value
@property
def ma_low_period(self):
return self._ma_low_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(high_low_ma_breakout_strategy, self).OnReseted()
self._prev_ma_high = 0.0
self._prev_ma_low = 0.0
self._prev_close = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(high_low_ma_breakout_strategy, self).OnStarted2(time)
ma_high = SimpleMovingAverage()
ma_high.Length = self.ma_high_period
ma_low = SimpleMovingAverage()
ma_low.Length = self.ma_low_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ma_high, ma_low, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, ma_high, ma_low):
if candle.State != CandleStates.Finished:
return
close = candle.ClosePrice
if not self._has_prev:
self._prev_close = close
self._prev_ma_high = ma_high
self._prev_ma_low = ma_low
self._has_prev = True
return
# Cross above high MA => buy
if self._prev_close <= self._prev_ma_high and close > ma_high and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Cross below low MA => sell
elif self._prev_close >= self._prev_ma_low and close < ma_low and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_close = close
self._prev_ma_high = ma_high
self._prev_ma_low = ma_low
def CreateClone(self):
return high_low_ma_breakout_strategy()