Five Ema NoTouch Breakout
Handelsregeln
Nur abgeschlossene Kerzen nach EMA-Bildung verwenden. Vollständig unter EMA: Long über dem Kerzenhoch vormerken; vollständig darüber: Short unter dem Tief. Die vorherige Vorgabe vor einer Ersetzung prüfen; Berührung genügt nicht. Nur aus leerer Position mit Volume einsteigen, während des Haltens Vorgabe löschen. Stop am gegenüberliegenden Extrem fixieren. Beim ersten tatsächlichen Einstieg den Abstand zum Stop als Risiko und RewardRisk×Risiko als Gewinnabstand festhalten. Nativer lokaler Marktschutz beobachtet Bid/Ask zwischen Kerzen. Eine Ausführung jenseits des Stops wird sofort glattgestellt. Keine Wartebalken oder Aufstockung.
Parameter
| Parameter | Standard |
|---|---|
CandleType |
TimeSpan.FromMinutes(5).TimeFrame() |
EmaPeriod |
5 |
RewardRisk |
3 |
Prüfung
Beide Sprachen werden mit gebündelten BTC/TON-Daten, unabhängigen Formeln, Orderseiten/-mengen, Ausführungen, Positionen und Ausstiegen geprüft. Datierte Preis-/Faktor- und Kalenderfixtures prüfen Mechanik; verschobene OHLC/Volumina sind keine mehrjährige Marktgeschichte. Zwei Ranggruppen, TopN=1 und SMA=2 sind ausdrücklich kleine Testprofile. Lange Originalfenster und Standardwerte werden separat geprüft. Keine Renditezusage.
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>Finished no-touch EMA setups with native protection fixed from actual entry risk.</summary>
public class FiveEmaNoTouchBreakoutStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<decimal> _rewardRisk;
private Order _pending;
private ExponentialMovingAverage _ema;
private (decimal high, decimal low, Sides side)? _setup;
private decimal _setupStop;
private bool _isProtectionArmed;
/// <summary>Finished signal candle type.</summary>
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
/// <summary>EMA length.</summary>
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
/// <summary>Take-profit distance divided by initial risk.</summary>
public decimal RewardRisk { get => _rewardRisk.Value; set => _rewardRisk.Value = value; }
/// <summary>Initialize the strategy parameters.</summary>
public FiveEmaNoTouchBreakoutStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("CandleType", "Finished signal candle type.", "Parameters");
_emaPeriod = Param(nameof(EmaPeriod), 5).SetRange(1, int.MaxValue)
.SetDisplay("EmaPeriod", "EMA length.", "Parameters");
_rewardRisk = Param(nameof(RewardRisk), 3m).SetRange(0.000001m, decimal.MaxValue)
.SetDisplay("RewardRisk", "Take-profit distance divided by initial risk.", "Parameters");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_pending = null;
_ema = null;
_setup = null;
_setupStop = 0m;
_isProtectionArmed = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
foreach (var field in new[] { Level1Fields.BestBidPrice, Level1Fields.BestAskPrice })
{
var quote = new Subscription(DataType.Level1, Security);
quote.MarketData.BuildField = field;
SubscribeLevel1(quote).Start();
}
_ema = new ExponentialMovingAverage { Length = EmaPeriod };
SubscribeCandles(CandleType).Bind(_ema, ProcessCandle).Start();
}
private bool IsPending => _pending is not null && _pending.State is not (OrderStates.Done or OrderStates.Failed);
private void Submit(Sides side, decimal quantity, string comment)
{
_pending = CreateOrder(side, 0m, quantity);
_pending.Type = OrderTypes.Market;
_pending.Comment = comment;
RegisterOrder(_pending);
}
private void ProcessCandle(ICandleMessage candle, decimal ema)
{
if (candle.State != CandleStates.Finished || !_ema.IsFormed || !IsFormedAndOnlineAndAllowTrading() || IsPending) return;
if (Position != 0m)
{
_setup = null;
return;
}
// Test the previous finished setup before a new candle can replace it.
if (_setup is { } setup && ((setup.side == Sides.Buy && candle.HighPrice > setup.high && candle.ClosePrice > setup.low)
|| (setup.side == Sides.Sell && candle.LowPrice < setup.low && candle.ClosePrice < setup.high)))
{
_setupStop = setup.side == Sides.Buy ? setup.low : setup.high;
_isProtectionArmed = false;
_setup = null;
Submit(setup.side, Volume, "0483Entry");
return;
}
if (candle.HighPrice < ema) _setup = (candle.HighPrice, candle.LowPrice, Sides.Buy);
else if (candle.LowPrice > ema) _setup = (candle.HighPrice, candle.LowPrice, Sides.Sell);
}
/// <inheritdoc />
protected override void OnOwnTradeReceived(MyTrade trade)
{
base.OnOwnTradeReceived(trade);
if (trade.Order.Comment != "0483Entry" || _isProtectionArmed) return;
_isProtectionArmed = true;
var risk = trade.Order.Side == Sides.Buy ? trade.Trade.Price - _setupStop : _setupStop - trade.Trade.Price;
if (risk <= 0m)
{
Submit(trade.Order.Side == Sides.Buy ? Sides.Sell : Sides.Buy, Math.Abs(Position), "0483InvalidFillExit");
return;
}
StartProtection(new Unit(risk * RewardRisk, UnitTypes.Absolute), new Unit(risk, UnitTypes.Absolute),
useMarketOrders: true, isLocalStop: true);
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.BusinessEntities")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import DateTime, Decimal, Math, TimeSpan, InvalidOperationException
from System.Globalization import CultureInfo, DateTimeStyles
from System.IO import File
from StockSharp.Algo.Indicators import ExponentialMovingAverage, SimpleMovingAverage, AverageTrueRange, AlligatorLine, CandleIndicatorValue
from StockSharp.Algo.Strategies import Strategy
from StockSharp.BusinessEntities import Subscription
from StockSharp.Messages import Level1Fields, ITickTradeMessage, CandleStates, DataType, OrderStates, OrderTypes, Sides, Unit, UnitTypes
class five_ema_no_touch_breakout_strategy(Strategy):
"""Finished no-touch EMA setups with native protection fixed from actual entry risk."""
def __init__(self):
super(five_ema_no_touch_breakout_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("CandleType", "Finished signal candle type.", "Parameters")
self._ema_period = self.Param("EmaPeriod", 5).SetRange(1, 2147483647) \
.SetDisplay("EmaPeriod", "EMA length.", "Parameters")
self._reward_risk = self.Param("RewardRisk", Decimal(3)).SetRange(Decimal(0.000001), Decimal.MaxValue) \
.SetDisplay("RewardRisk", "Take-profit distance divided by initial risk.", "Parameters")
self._clear_state()
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def EmaPeriod(self):
return self._ema_period.Value
@EmaPeriod.setter
def EmaPeriod(self, value):
self._ema_period.Value = value
@property
def RewardRisk(self):
return self._reward_risk.Value
@RewardRisk.setter
def RewardRisk(self, value):
self._reward_risk.Value = value
def _clear_state(self):
self._pending = None
self._ema = None
self._setup = None
self._setup_stop = Decimal(0)
self._is_protection_armed = False
def OnReseted(self):
super(five_ema_no_touch_breakout_strategy, self).OnReseted()
self._clear_state()
def GetWorkingSecurities(self):
return [(self.Security, self.CandleType)]
def OnStarted2(self, time):
super(five_ema_no_touch_breakout_strategy, self).OnStarted2(time)
for field in (Level1Fields.BestBidPrice, Level1Fields.BestAskPrice):
quote = Subscription(DataType.Level1, self.Security)
quote.MarketData.BuildField = field
self.SubscribeLevel1(quote).Start()
self._ema = ExponentialMovingAverage()
self._ema.Length = self.EmaPeriod
self.SubscribeCandles(self.CandleType).Bind(self._ema, self._process_candle).Start()
def _is_pending(self):
return self._pending is not None and self._pending.State not in (OrderStates.Done, OrderStates.Failed)
def _submit(self, side, quantity, comment):
self._pending = self.CreateOrder(side, Decimal(0), quantity)
self._pending.Type = OrderTypes.Market
self._pending.Comment = comment
self.RegisterOrder(self._pending)
@staticmethod
def _process(indicator, candle):
value = CandleIndicatorValue(indicator, candle)
value.IsFinal = True
result = indicator.Process(value)
return None if result.IsEmpty else result.GetValue[Decimal](None)
def _process_candle(self, candle, ema):
if candle.State != CandleStates.Finished or not self._ema.IsFormed or not self.IsFormedAndOnlineAndAllowTrading() or self._is_pending():
return
if self.Position != 0:
self._setup = None
return
if self._setup is not None:
high, low, side = self._setup
if (side == Sides.Buy and candle.HighPrice > high and candle.ClosePrice > low) or (side == Sides.Sell and candle.LowPrice < low and candle.ClosePrice < high):
self._setup_stop = low if side == Sides.Buy else high
self._is_protection_armed = False
self._setup = None
self._submit(side, self.Volume, "0483Entry")
return
if candle.HighPrice < ema:
self._setup = (candle.HighPrice, candle.LowPrice, Sides.Buy)
elif candle.LowPrice > ema:
self._setup = (candle.HighPrice, candle.LowPrice, Sides.Sell)
def OnOwnTradeReceived(self, trade):
super(five_ema_no_touch_breakout_strategy, self).OnOwnTradeReceived(trade)
if trade.Order.Comment != "0483Entry" or self._is_protection_armed:
return
self._is_protection_armed = True
risk = ITickTradeMessage.Price.__get__(trade.Trade) - self._setup_stop if trade.Order.Side == Sides.Buy else self._setup_stop - ITickTradeMessage.Price.__get__(trade.Trade)
if risk <= 0:
self._submit(Sides.Sell if trade.Order.Side == Sides.Buy else Sides.Buy, abs(self.Position), "0483InvalidFillExit")
return
self.StartProtection(Unit(risk * self.RewardRisk, UnitTypes.Absolute), Unit(risk, UnitTypes.Absolute), useMarketOrders=True, isLocalStop=True)
def CreateClone(self):
return five_ema_no_touch_breakout_strategy()