Diese Strategie verwendet die Steigungsrichtung eines Jurik Moving Average (JMA), um Trades zu generieren. Der JMA approximiert den "ColorJFatl_Digit"-Indikator aus dem ursprünglichen MQL5-Experten. Eine Long-Position wird eröffnet, wenn der JMA aufwärts dreht, während eine Short-Position eröffnet wird, wenn der JMA abwärts dreht. Entgegengesetzte Positionen werden geschlossen, wenn sich die Steigung umkehrt.
Das System handelt in beide Richtungen und verwendet standardmäßig keine harten Stops. Es eignet sich für Instrumente, bei denen Trendwechsel durch einen glatten adaptiven gleitenden Durchschnitt erfasst werden können.
Details
Einstiegskriterien:
Long: JMA-Steigung wechselt von negativ zu positiv.
Short: JMA-Steigung wechselt von positiv zu negativ.
Long/Short: Beide Seiten.
Ausstiegskriterien:
Long: JMA-Steigung wird negativ.
Short: JMA-Steigung wird positiv.
Stops: Standardmäßig keine.
Standardwerte:
JMA Length = 5
Timeframe = 4 Stunden
Filter:
Kategorie: Trendfolge
Richtung: Beide
Indikatoren: Einzeln
Stops: Nein
Komplexität: Einfach
Zeitrahmen: Mittelfristig
Saisonalität: Nein
Neuronale Netze: Nein
Divergenz: Nein
Risikolevel: Mittel
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 the slope changes of Jurik Moving Average (JMA).
/// Opens long when JMA turns up, opens short when JMA turns down.
/// </summary>
public class ColorJFatlDigitStrategy : Strategy
{
private readonly StrategyParam<int> _jmaLength;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevJma;
private decimal? _prevSlope;
public int JmaLength { get => _jmaLength.Value; set => _jmaLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ColorJFatlDigitStrategy()
{
_jmaLength = Param(nameof(JmaLength), 5)
.SetGreaterThanZero()
.SetDisplay("JMA Length", "Period for Jurik Moving Average", "Parameters");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe of indicator", "Parameters");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevJma = null;
_prevSlope = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevJma = null;
_prevSlope = null;
var jma = new JurikMovingAverage { Length = JmaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(jma, Process)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, jma);
DrawOwnTrades(area);
}
}
private void Process(ICandleMessage candle, decimal jmaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var slope = _prevJma is decimal prev ? jmaValue - prev : (decimal?)null;
if (slope is decimal s && _prevSlope is decimal ps)
{
// JMA slope turns positive -> buy
if (ps <= 0m && s > 0m && Position <= 0)
BuyMarket();
// JMA slope turns negative -> sell
else if (ps >= 0m && s < 0m && Position >= 0)
SellMarket();
}
_prevSlope = slope;
_prevJma = jmaValue;
}
}
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 JurikMovingAverage
from StockSharp.Algo.Strategies import Strategy
class color_j_fatl_digit_strategy(Strategy):
def __init__(self):
super(color_j_fatl_digit_strategy, self).__init__()
self._jma_length = self.Param("JmaLength", 5) \
.SetDisplay("JMA Length", "Period for Jurik Moving Average", "Parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe of indicator", "Parameters")
self._prev_jma = None
self._prev_slope = None
@property
def jma_length(self):
return self._jma_length.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(color_j_fatl_digit_strategy, self).OnReseted()
self._prev_jma = None
self._prev_slope = None
def OnStarted2(self, time):
super(color_j_fatl_digit_strategy, self).OnStarted2(time)
self._prev_jma = None
self._prev_slope = None
jma = JurikMovingAverage()
jma.Length = self.jma_length
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(jma, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, jma)
self.DrawOwnTrades(area)
def process_candle(self, candle, jma_value):
if candle.State != CandleStates.Finished:
return
jma_value = float(jma_value)
slope = None
if self._prev_jma is not None:
slope = jma_value - self._prev_jma
if slope is not None and self._prev_slope is not None:
if self._prev_slope <= 0 and slope > 0 and self.Position <= 0:
self.BuyMarket()
elif self._prev_slope >= 0 and slope < 0 and self.Position >= 0:
self.SellMarket()
self._prev_slope = slope
self._prev_jma = jma_value
def CreateClone(self):
return color_j_fatl_digit_strategy()