Diese Strategie ist eine Interpretation des originalen MQL5-Expertenberaters "MA Rounding Candle". Sie verwendet zwei geglättete gleitende Durchschnitte, die auf die Eröffnungs- und Schlusskurse der Kerzen angewendet werden. Die relative Position dieser Durchschnitte definiert die Farbe einer synthetischen Kerze: grün, wenn der geglättete Schlusskurs über der Eröffnung liegt, rot, wenn der Schluss unterhalb der Eröffnung liegt, und grau, wenn beide gleich sind. Ein Farbwechsel gegenüber dem vorherigen Balken erzeugt Handelssignale.
Algorithmus
Für jede abgeschlossene Kerze werden die Eröffnungs- und Schlusswerte mit einem einfachen gleitenden Durchschnitt konfigurierbarer Länge geglättet.
Die Kerzenfarbe wird durch den Vergleich der geglätteten Werte definiert:
Aufwärtskerze – der geglättete Schlusskurs ist höher als die geglättete Eröffnung.
Abwärtskerze – der geglättete Schlusskurs ist niedriger als die geglättete Eröffnung.
Neutral – beide Werte sind gleich.
War die vorherige Kerze eine Aufwärtskerze und ist die aktuelle keine Aufwärtskerze, eröffnet die Strategie eine Long-Position und schließt alle Short-Positionen.
War die vorherige Kerze eine Abwärtskerze und ist die aktuelle keine Abwärtskerze, eröffnet die Strategie eine Short-Position und schließt alle Long-Positionen.
Parameter
MaLength – Periode der glättenden gleitenden Durchschnitte (Standard 12).
CandleType – Zeitrahmen der verarbeiteten Kerzen.
Hinweise
Die Strategie zeigt, wie Signale eines benutzerdefinierten Indikators ausschließlich mit integrierten StockSharp-Tools nachgebildet werden können. Es wird kein Stop-Loss oder Take-Profit verwendet; Positionen werden sofort umgekehrt, wenn das gegenteilige Signal erscheint.
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>
/// MA Rounding Candle strategy.
/// Opens a long position when a smoothed candle is bullish and a short position when it is bearish.
/// </summary>
public class MaRoundingCandleStrategy : Strategy
{
private readonly StrategyParam<int> _maLength;
private readonly StrategyParam<DataType> _candleType;
private ExponentialMovingAverage _openMa;
private ExponentialMovingAverage _closeMa;
private int _prevColor = 1;
public MaRoundingCandleStrategy()
{
_maLength = Param(nameof(MaLength), 12)
.SetDisplay("MA Length", "Moving average length", "Parameters");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame());
}
public int MaLength { get => _maLength.Value; set => _maLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_openMa = default;
_closeMa = default;
_prevColor = 1;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_openMa = new ExponentialMovingAverage { Length = MaLength };
_closeMa = new ExponentialMovingAverage { Length = MaLength };
Indicators.Add(_openMa);
Indicators.Add(_closeMa);
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _openMa);
DrawIndicator(area, _closeMa);
DrawOwnTrades(area);
}
StartProtection(null, null);
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var openVal = _openMa.Process(candle.OpenPrice, candle.OpenTime, true).ToDecimal();
var closeVal = _closeMa.Process(candle.ClosePrice, candle.OpenTime, true).ToDecimal();
if (!_openMa.IsFormed || !_closeMa.IsFormed)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var color = openVal < closeVal ? 2 : openVal > closeVal ? 0 : 1;
if (_prevColor == 2 && color != 2 && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (_prevColor == 0 && color != 0 && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevColor = color;
}
}
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
from indicator_extensions import *
class ma_rounding_candle_strategy(Strategy):
def __init__(self):
super(ma_rounding_candle_strategy, self).__init__()
self._ma_length = self.Param("MaLength", 12) \
.SetDisplay("MA Length", "Moving average length", "Parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4)))
self._open_ma = None
self._close_ma = None
self._prev_color = 1
@property
def ma_length(self):
return self._ma_length.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(ma_rounding_candle_strategy, self).OnReseted()
self._open_ma = None
self._close_ma = None
self._prev_color = 1
def OnStarted2(self, time):
super(ma_rounding_candle_strategy, self).OnStarted2(time)
self._open_ma = ExponentialMovingAverage()
self._open_ma.Length = self.ma_length
self._close_ma = ExponentialMovingAverage()
self._close_ma.Length = self.ma_length
self.Indicators.Add(self._open_ma)
self.Indicators.Add(self._close_ma)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, self._open_ma)
self.DrawIndicator(area, self._close_ma)
self.DrawOwnTrades(area)
def process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
open_result = process_float(self._open_ma, candle.OpenPrice, candle.OpenTime, True)
close_result = process_float(self._close_ma, candle.ClosePrice, candle.OpenTime, True)
if not self._open_ma.IsFormed or not self._close_ma.IsFormed:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
open_val = float(open_result)
close_val = float(close_result)
if open_val < close_val:
color = 2
elif open_val > close_val:
color = 0
else:
color = 1
if self._prev_color == 2 and color != 2 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._prev_color == 0 and color != 0 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_color = color
def CreateClone(self):
return ma_rounding_candle_strategy()