Die JS MA Day-Strategie handelt auf Basis eines einfachen gleitenden Durchschnitts, der auf Tageskerzen mit dem Medianpreis berechnet wird. Die Strategie vergleicht die Position des gleitenden Durchschnitts relativ zum Eröffnungspreis jedes Tages und eröffnet Positionen, wenn der Trend des gleitenden Durchschnitts einen Crossover des Eröffnungspreises bestätigt.
Indikatoren
Einfacher gleitender Durchschnitt (Medianpreis)
Parameter
Name
Beschreibung
Standard
MaPeriod
Periode des einfachen gleitenden Durchschnitts.
3
Reverse
Kehrt Handelssignale um. Wenn aktiviert, werden Kaufsignale zu Verkaufssignalen und umgekehrt.
false
CandleType
Für Berechnungen verwendeter Kerzentyp. Standard sind Tages-Zeitrahmen-Kerzen.
TimeFrame(1 day)
Einstiegsregeln
Bewertet den täglichen einfachen gleitenden Durchschnitt (SMA) und die täglichen Eröffnungspreise.
Kaufen wenn:
Der aktuelle SMA liegt unter dem vorherigen SMA.
Der aktuelle SMA liegt über dem heutigen Eröffnungspreis.
Der vorherige SMA liegt unter dem SMA vor zwei Tagen.
Der vorherige SMA liegt über dem Eröffnungspreis des Vortages.
Verkaufen wenn:
Der aktuelle SMA liegt über dem vorherigen SMA.
Der aktuelle SMA liegt unter dem heutigen Eröffnungspreis.
Der vorherige SMA liegt über dem SMA vor zwei Tagen.
Der vorherige SMA liegt unter dem Eröffnungspreis des Vortages.
Wenn Reverse aktiviert ist, werden Kauf- und Verkaufsbedingungen getauscht.
Ausstiegsregeln
Positionen werden durch den Aufruf von StartProtection geschlossen, was die Konfiguration von Schutzorders wie Stop Loss oder Take Profit über die Plattformeinstellungen ermöglicht.
Hinweise
Die Strategie verarbeitet nur abgeschlossene Kerzen.
Das Ordervolumen wird durch die Volume-Eigenschaft der Basisklasse definiert.
Es gibt noch keine Python-Version dieser Strategie.
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>
/// Daily SMA strategy comparing moving average to open price.
/// Opens position when the moving average crosses daily open in trend direction.
/// </summary>
public class JsMaDayStrategy : Strategy
{
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<bool> _reverse;
private readonly StrategyParam<DataType> _candleType;
private readonly List<decimal> _prices = new();
private decimal? _prevMa;
private decimal? _prevOpen;
/// <summary>
/// Moving average period.
/// </summary>
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
/// <summary>
/// Reverse trading signals.
/// </summary>
public bool Reverse
{
get => _reverse.Value;
set => _reverse.Value = value;
}
/// <summary>
/// Candle type used for calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public JsMaDayStrategy()
{
_maPeriod = Param(nameof(MaPeriod), 5)
.SetGreaterThanZero()
.SetDisplay("MA Period", "SMA period on daily candles", "Parameters")
.SetOptimize(2, 20, 1);
_reverse = Param(nameof(Reverse), false)
.SetDisplay("Reverse Signals", "Reverse entry direction", "Parameters");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles for moving average", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prices.Clear();
_prevMa = null;
_prevOpen = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
SubscribeCandles(CandleType)
.Bind(ProcessCandle)
.Start();
StartProtection(
new Unit(2000m, UnitTypes.Absolute),
new Unit(1000m, UnitTypes.Absolute));
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
_prices.Add(candle.ClosePrice);
if (_prices.Count > MaPeriod)
_prices.RemoveAt(0);
if (_prices.Count < MaPeriod)
return;
var sum = 0m;
foreach (var price in _prices)
sum += price;
var ma = sum / _prices.Count;
var open = candle.OpenPrice;
if (_prevMa is decimal prevMa && _prevOpen is decimal prevOpen)
{
var buyCondition = ma > open && prevMa <= prevOpen;
var sellCondition = ma < open && prevMa >= prevOpen;
if (buyCondition)
{
if (!Reverse && Position <= 0)
BuyMarket();
else if (Reverse && Position >= 0)
SellMarket();
}
else if (sellCondition)
{
if (!Reverse && Position >= 0)
SellMarket();
else if (Reverse && Position <= 0)
BuyMarket();
}
}
_prevMa = ma;
_prevOpen = open;
}
}
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.Strategies import Strategy
class js_ma_day_strategy(Strategy):
"""
Daily SMA strategy comparing manual moving average to open price.
Trades when MA crosses daily open. Uses StartProtection for SL/TP.
"""
def __init__(self):
super(js_ma_day_strategy, self).__init__()
self._ma_period = self.Param("MaPeriod", 5) \
.SetDisplay("MA Period", "SMA period on daily candles", "Parameters")
self._reverse = self.Param("Reverse", False) \
.SetDisplay("Reverse Signals", "Reverse entry direction", "Parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles for moving average", "General")
self._prices = []
self._prev_ma = None
self._prev_open = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(js_ma_day_strategy, self).OnReseted()
self._prices = []
self._prev_ma = None
self._prev_open = None
def OnStarted2(self, time):
super(js_ma_day_strategy, self).OnStarted2(time)
self.StartProtection(
Unit(2000.0, UnitTypes.Absolute),
Unit(1000.0, UnitTypes.Absolute))
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._process_candle).Start()
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
open_price = float(candle.OpenPrice)
period = self._ma_period.Value
self._prices.append(close)
if len(self._prices) > period:
self._prices.pop(0)
if len(self._prices) < period:
return
ma = sum(self._prices) / len(self._prices)
if self._prev_ma is not None and self._prev_open is not None:
buy_cond = ma > open_price and self._prev_ma <= self._prev_open
sell_cond = ma < open_price and self._prev_ma >= self._prev_open
reverse = self._reverse.Value
if buy_cond:
if not reverse and self.Position <= 0:
self.BuyMarket()
elif reverse and self.Position >= 0:
self.SellMarket()
elif sell_cond:
if not reverse and self.Position >= 0:
self.SellMarket()
elif reverse and self.Position <= 0:
self.BuyMarket()
self._prev_ma = ma
self._prev_open = open_price
def CreateClone(self):
return js_ma_day_strategy()