Medico Action Zone Self Adjust TF Version 2 Strategie
EMA-Crossover-Strategie mit Bestätigung durch einen höheren Zeitrahmen. Eine Position wird eröffnet, wenn die schnelle EMA die langsame EMA kreuzt und der Schlusskurs des höheren Zeitrahmens über der schnellen EMA liegt. Bei gegenteiligem Signal wird die Position umgekehrt.
Details
- Einstiegskriterien: Schnelle EMA kreuzt über die langsame EMA, während der Schlusskurs des höheren Zeitrahmens über der schnellen EMA liegt.
- Long/Short: Beide Richtungen.
- Ausstiegskriterien: Gegenteiliger Crossover mit Bestätigung.
- Stops: Keine.
- Standardwerte:
CandleType= TimeSpan.FromDays(1)HigherCandleType= TimeSpan.FromDays(7)FastEmaLength= 12SlowEmaLength= 26
- Filter:
- Kategorie: Trend
- Richtung: Beide
- Indikatoren: EMA
- Stops: Nein
- Komplexität: Grundlegend
- Zeitrahmen: Täglich
- Saisonalität: Nein
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Mittel
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>
/// EMA crossover strategy with higher timeframe confirmation.
/// </summary>
public class MedicoActionZoneSelfAdjustTfVersion2Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<DataType> _higherCandleType;
private readonly StrategyParam<int> _fastEmaLength;
private readonly StrategyParam<int> _slowEmaLength;
private readonly StrategyParam<int> _signalCooldownBars;
private ExponentialMovingAverage _fastEmaCur;
private ExponentialMovingAverage _slowEmaCur;
private ExponentialMovingAverage _fastEmaHtf;
private ExponentialMovingAverage _slowEmaHtf;
private decimal _fastEmaHtfValue;
private decimal _slowEmaHtfValue;
private decimal _closeHtf;
private decimal _prevFast;
private decimal _prevSlow;
private int _barsFromSignal;
public MedicoActionZoneSelfAdjustTfVersion2Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Candle Type", "Primary timeframe", "General");
_higherCandleType = Param(nameof(HigherCandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Higher Candle Type", "EMA calculation timeframe", "General");
_fastEmaLength = Param(nameof(FastEmaLength), 12)
.SetDisplay("Fast EMA Length", "Short EMA period", "Indicators");
_slowEmaLength = Param(nameof(SlowEmaLength), 26)
.SetDisplay("Slow EMA Length", "Long EMA period", "Indicators");
_signalCooldownBars = Param(nameof(SignalCooldownBars), 8)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown Bars", "Minimum bars between entries", "Indicators");
}
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public DataType HigherCandleType { get => _higherCandleType.Value; set => _higherCandleType.Value = value; }
public int FastEmaLength { get => _fastEmaLength.Value; set => _fastEmaLength.Value = value; }
public int SlowEmaLength { get => _slowEmaLength.Value; set => _slowEmaLength.Value = value; }
public int SignalCooldownBars { get => _signalCooldownBars.Value; set => _signalCooldownBars.Value = value; }
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> HigherCandleType == CandleType
? [(Security, CandleType)]
: [(Security, CandleType), (Security, HigherCandleType)];
protected override void OnReseted()
{
base.OnReseted();
_fastEmaHtfValue = 0m;
_slowEmaHtfValue = 0m;
_closeHtf = 0m;
_prevFast = 0m;
_prevSlow = 0m;
_barsFromSignal = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
StartProtection(null, null);
_fastEmaCur = new EMA { Length = FastEmaLength };
_slowEmaCur = new EMA { Length = SlowEmaLength };
_fastEmaHtf = new EMA { Length = FastEmaLength };
_slowEmaHtf = new EMA { Length = SlowEmaLength };
_barsFromSignal = SignalCooldownBars;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_fastEmaCur, _slowEmaCur, ProcessCandle)
.Start();
if (HigherCandleType != CandleType)
{
var higherSubscription = SubscribeCandles(HigherCandleType);
higherSubscription
.Bind(_fastEmaHtf, _slowEmaHtf, ProcessHigher)
.Start();
}
}
private void ProcessHigher(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
_fastEmaHtfValue = fast;
_slowEmaHtfValue = slow;
_closeHtf = candle.ClosePrice;
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (HigherCandleType == CandleType)
{
if (!_fastEmaCur.IsFormed || !_slowEmaCur.IsFormed)
return;
}
else
{
if (!_fastEmaHtf.IsFormed || !_slowEmaHtf.IsFormed)
return;
}
var emaFast = HigherCandleType == CandleType ? fast : _fastEmaHtfValue;
var emaSlow = HigherCandleType == CandleType ? slow : _slowEmaHtfValue;
var closeHtf = HigherCandleType == CandleType ? candle.ClosePrice : _closeHtf;
var buySignal = _prevFast <= _prevSlow && emaFast > emaSlow && closeHtf > emaFast;
var sellSignal = _prevFast >= _prevSlow && emaFast < emaSlow && closeHtf < emaSlow;
_barsFromSignal++;
if (_barsFromSignal >= SignalCooldownBars && buySignal && Position <= 0)
{
var volume = Volume + Math.Abs(Position);
BuyMarket(volume);
_barsFromSignal = 0;
}
else if (_barsFromSignal >= SignalCooldownBars && sellSignal && Position >= 0)
{
var volume = Volume + Math.Abs(Position);
SellMarket(volume);
_barsFromSignal = 0;
}
_prevFast = emaFast;
_prevSlow = emaSlow;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage as EMA
from StockSharp.Algo.Strategies import Strategy
class medico_action_zone_self_adjust_tf_version_2_strategy(Strategy):
def __init__(self):
super(medico_action_zone_self_adjust_tf_version_2_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))) \
.SetDisplay("Candle Type", "Primary timeframe", "General")
self._higher_candle_type = self.Param("HigherCandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))) \
.SetDisplay("Higher Candle Type", "EMA calculation timeframe", "General")
self._fast_ema_length = self.Param("FastEmaLength", 12) \
.SetDisplay("Fast EMA Length", "Short EMA period", "Indicators")
self._slow_ema_length = self.Param("SlowEmaLength", 26) \
.SetDisplay("Slow EMA Length", "Long EMA period", "Indicators")
self._signal_cooldown_bars = self.Param("SignalCooldownBars", 8) \
.SetDisplay("Signal Cooldown Bars", "Minimum bars between entries", "Indicators")
self._fast_ema_htf_value = 0.0
self._slow_ema_htf_value = 0.0
self._close_htf = 0.0
self._prev_fast = 0.0
self._prev_slow = 0.0
self._bars_from_signal = 0
@property
def candle_type(self):
return self._candle_type.Value
@property
def higher_candle_type(self):
return self._higher_candle_type.Value
@property
def fast_ema_length(self):
return self._fast_ema_length.Value
@property
def slow_ema_length(self):
return self._slow_ema_length.Value
@property
def signal_cooldown_bars(self):
return self._signal_cooldown_bars.Value
def OnReseted(self):
super(medico_action_zone_self_adjust_tf_version_2_strategy, self).OnReseted()
self._fast_ema_htf_value = 0.0
self._slow_ema_htf_value = 0.0
self._close_htf = 0.0
self._prev_fast = 0.0
self._prev_slow = 0.0
self._bars_from_signal = 0
def OnStarted2(self, time):
super(medico_action_zone_self_adjust_tf_version_2_strategy, self).OnStarted2(time)
self.StartProtection(None, None)
self._fast_ema_cur = EMA()
self._fast_ema_cur.Length = self.fast_ema_length
self._slow_ema_cur = EMA()
self._slow_ema_cur.Length = self.slow_ema_length
self._fast_ema_htf = EMA()
self._fast_ema_htf.Length = self.fast_ema_length
self._slow_ema_htf = EMA()
self._slow_ema_htf.Length = self.slow_ema_length
self._bars_from_signal = int(self.signal_cooldown_bars)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._fast_ema_cur, self._slow_ema_cur, self._process_candle).Start()
if self.higher_candle_type != self.candle_type:
higher_sub = self.SubscribeCandles(self.higher_candle_type)
higher_sub.Bind(self._fast_ema_htf, self._slow_ema_htf, self._process_higher).Start()
def _process_higher(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
self._fast_ema_htf_value = float(fast)
self._slow_ema_htf_value = float(slow)
self._close_htf = float(candle.ClosePrice)
def _process_candle(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
same_tf = (self.higher_candle_type == self.candle_type)
if same_tf:
if not self._fast_ema_cur.IsFormed or not self._slow_ema_cur.IsFormed:
return
else:
if not self._fast_ema_htf.IsFormed or not self._slow_ema_htf.IsFormed:
return
ema_fast = float(fast) if same_tf else self._fast_ema_htf_value
ema_slow = float(slow) if same_tf else self._slow_ema_htf_value
close_htf = float(candle.ClosePrice) if same_tf else self._close_htf
buy_signal = self._prev_fast <= self._prev_slow and ema_fast > ema_slow and close_htf > ema_fast
sell_signal = self._prev_fast >= self._prev_slow and ema_fast < ema_slow and close_htf < ema_slow
self._bars_from_signal += 1
if self._bars_from_signal >= int(self.signal_cooldown_bars) and buy_signal and self.Position <= 0:
self.BuyMarket()
self._bars_from_signal = 0
elif self._bars_from_signal >= int(self.signal_cooldown_bars) and sell_signal and self.Position >= 0:
self.SellMarket()
self._bars_from_signal = 0
self._prev_fast = ema_fast
self._prev_slow = ema_slow
def CreateClone(self):
return medico_action_zone_self_adjust_tf_version_2_strategy()