Innocent Heikin Ashi Ethereum-Strategie
Diese Strategie kauft Ethereum, wenn auf eine Sequenz bärischer Kerzen unterhalb der EMA50 eine bullische Kerze oberhalb der EMA50 folgt. Der Stop Loss wird am niedrigsten Tief der letzten 28 Bars gesetzt, das Take Profit mit dem RiskReward-Multiplikator berechnet. Der optionale Moon Mode erlaubt Einstiege oberhalb der EMA200. Die Position kann bei Verkaufs- oder Fallensignalen vorzeitig geschlossen werden.
Details
- Einstiegskriterien:
- Long: Mindestens
ConfirmationLevelrote Kerzen unterhalb der EMA50, gefolgt von einer grünen Kerze oberhalb der EMA50. - Aggressiv: Wenn
EnableMoonModewahr ist und der Preis über der EMA200 liegt.
- Long: Mindestens
- Long/Short: Nur Long.
- Ausstiegskriterien:
- Stop Loss am niedrigsten Tief der letzten 28 Bars.
- Take Profit mit dem
RiskReward-Multiplikator. - Optionale Verkaufs- oder Fallensignale für frühzeitigen Ausstieg.
- Stops: Ja.
- Standardwerte:
RiskReward= 1.ConfirmationLevel= 1.EnableMoonMode= true.
- Filter:
- Kategorie: Trendfolge
- Richtung: Nur Long
- Indikatoren: EMA
- Stops: Ja
- Komplexität: Mittel
- Zeitrahmen: Intraday
- 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>
/// Goes long on Ethereum after bearish activity below EMA50 followed by a
/// bullish candle above EMA50.
/// </summary>
public class InnocentHeikinAshiEthereumStrategy : Strategy {
private readonly StrategyParam<decimal> _riskReward;
private readonly StrategyParam<int> _confirmationLevel;
private readonly StrategyParam<bool> _enableMoonMode;
private readonly StrategyParam<bool> _showSellSignals;
private readonly StrategyParam<bool> _showBullTraps;
private readonly StrategyParam<bool> _showBearTraps;
private readonly StrategyParam<DataType> _candleType;
private ExponentialMovingAverage _ema50;
private ExponentialMovingAverage _ema200;
private Lowest _lowest;
private int? _lastRedVectorBelowEma50;
private int? _lastBuySignalIndex;
private int? _lastSellSignalIndex;
private int _redCountUnderEma50;
private int _greenCountAboveEma200;
private int _barIndex;
private decimal _prevHaOpen;
private decimal _prevHaClose;
private decimal _stopPrice;
private decimal _takePrice;
/// <summary>
/// Initializes a new instance of the <see
/// cref="InnocentHeikinAshiEthereumStrategy"/> class.
/// </summary>
public InnocentHeikinAshiEthereumStrategy() {
_riskReward =
Param(nameof(RiskReward), 1m)
.SetGreaterThanZero()
.SetDisplay("Risk/Reward", "Take profit to stop ratio", "Risk")
.SetOptimize(0.5m, 3m, 0.5m);
_confirmationLevel =
Param(nameof(ConfirmationLevel), 1)
.SetNotNegative()
.SetDisplay(
"Confirmation Level",
"Number of red candles below EMA50 required before entry",
"General");
_enableMoonMode =
Param(nameof(EnableMoonMode), true)
.SetDisplay("Enable Moon Mode", "Allow entries above EMA200",
"General");
_showSellSignals = Param(nameof(ShowSellSignals), true)
.SetDisplay("Show Sell Signals",
"Close on sell signals", "General");
_showBullTraps =
Param(nameof(ShowBullTraps), true)
.SetDisplay("Show Bull Traps",
"Close if next candle after buy is red", "General");
_showBearTraps =
Param(nameof(ShowBearTraps), true)
.SetDisplay("Show Bear Traps", "Close if sell signal fails",
"General");
_candleType =
Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <summary>
/// Risk/reward multiplier.
/// </summary>
public decimal RiskReward {
get => _riskReward.Value;
set => _riskReward.Value = value;
}
/// <summary>
/// Required number of red candles below EMA50.
/// </summary>
public int ConfirmationLevel {
get => _confirmationLevel.Value;
set => _confirmationLevel.Value = value;
}
/// <summary>
/// Allow aggressive entries above EMA200.
/// </summary>
public bool EnableMoonMode {
get => _enableMoonMode.Value;
set => _enableMoonMode.Value = value;
}
/// <summary>
/// Close position on sell signals.
/// </summary>
public bool ShowSellSignals {
get => _showSellSignals.Value;
set => _showSellSignals.Value = value;
}
/// <summary>
/// Close if the candle after a buy is bearish.
/// </summary>
public bool ShowBullTraps {
get => _showBullTraps.Value;
set => _showBullTraps.Value = value;
}
/// <summary>
/// Close if sell signal fails.
/// </summary>
public bool ShowBearTraps {
get => _showBearTraps.Value;
set => _showBearTraps.Value = value;
}
/// <summary>
/// Candle type used for calculations.
/// </summary>
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();
_lastRedVectorBelowEma50 = null;
_lastBuySignalIndex = null;
_lastSellSignalIndex = null;
_redCountUnderEma50 = 0;
_greenCountAboveEma200 = 0;
_barIndex = 0;
_prevHaOpen = 0m;
_prevHaClose = 0m;
_stopPrice = 0m;
_takePrice = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time) {
base.OnStarted2(time);
StartProtection(null, null);
_ema50 = new ExponentialMovingAverage { Length = 50 };
_ema200 = new ExponentialMovingAverage { Length = 200 };
_lowest = new Lowest { Length = 28 };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(_ema50, _ema200, _lowest, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal ema50,
decimal ema200, decimal lowest) {
if (candle.State != CandleStates.Finished)
return;
decimal haOpen;
decimal haClose;
if (_barIndex == 0) {
haOpen = (candle.OpenPrice + candle.ClosePrice) / 2;
haClose = (candle.OpenPrice + candle.HighPrice + candle.LowPrice +
candle.ClosePrice) /
4;
} else {
haOpen = (_prevHaOpen + _prevHaClose) / 2;
haClose = (candle.OpenPrice + candle.HighPrice + candle.LowPrice +
candle.ClosePrice) /
4;
}
var isGreen = haClose > haOpen;
var isRed = !isGreen;
if (isRed && candle.ClosePrice < ema50)
_redCountUnderEma50++;
if (isRed && candle.OpenPrice < ema50 && candle.ClosePrice < ema50)
_lastRedVectorBelowEma50 = _barIndex;
if (isGreen && candle.OpenPrice > ema200 && candle.OpenPrice > ema50)
_lastSellSignalIndex = _barIndex;
if (isGreen && candle.ClosePrice > ema200)
_greenCountAboveEma200++;
if (_lastRedVectorBelowEma50.HasValue && isGreen) {
_stopPrice = lowest;
_takePrice = candle.ClosePrice +
(candle.ClosePrice - _stopPrice) * RiskReward;
}
var canBuy =
_lastRedVectorBelowEma50.HasValue && isGreen &&
candle.OpenPrice > ema50 &&
(_lastBuySignalIndex == null || _barIndex > _lastBuySignalIndex);
if (canBuy) {
if (candle.ClosePrice < ema200 &&
_redCountUnderEma50 >= ConfirmationLevel) {
BuyMarket();
_lastBuySignalIndex = _barIndex;
_lastRedVectorBelowEma50 = null;
_redCountUnderEma50 = 0;
} else if (EnableMoonMode && candle.ClosePrice > ema200 &&
_redCountUnderEma50 >= ConfirmationLevel) {
BuyMarket();
_lastBuySignalIndex = _barIndex;
_lastRedVectorBelowEma50 = null;
_redCountUnderEma50 = 0;
}
}
if (Position > 0) {
if (candle.LowPrice <= _stopPrice || candle.HighPrice >= _takePrice)
SellMarket();
}
if (ShowSellSignals && _lastSellSignalIndex.HasValue && isRed &&
candle.OpenPrice > ema200 && candle.ClosePrice > ema200 &&
_barIndex == _lastSellSignalIndex + 1) {
if (_greenCountAboveEma200 >= ConfirmationLevel) {
SellMarket();
_lastSellSignalIndex = null;
_greenCountAboveEma200 = 0;
}
}
if (ShowBullTraps && _lastBuySignalIndex.HasValue &&
_barIndex == _lastBuySignalIndex + 1 && isRed)
SellMarket();
if (ShowBearTraps && _lastSellSignalIndex.HasValue &&
_barIndex == _lastSellSignalIndex + 1 && isGreen) {
SellMarket();
_lastSellSignalIndex = null;
_greenCountAboveEma200 = 0;
}
_prevHaOpen = haOpen;
_prevHaClose = haClose;
_barIndex++;
}
}
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, Lowest
from StockSharp.Algo.Strategies import Strategy
class innocent_heikin_ashi_ethereum_strategy(Strategy):
def __init__(self):
super(innocent_heikin_ashi_ethereum_strategy, self).__init__()
self._risk_reward = self.Param("RiskReward", 1.0) \
.SetGreaterThanZero() \
.SetDisplay("Risk/Reward", "Take profit to stop ratio", "Risk")
self._confirmation_level = self.Param("ConfirmationLevel", 1) \
.SetDisplay("Confirmation Level", "Number of red candles below EMA50 required before entry", "General")
self._enable_moon_mode = self.Param("EnableMoonMode", True) \
.SetDisplay("Enable Moon Mode", "Allow entries above EMA200", "General")
self._show_sell_signals = self.Param("ShowSellSignals", True) \
.SetDisplay("Show Sell Signals", "Close on sell signals", "General")
self._show_bull_traps = self.Param("ShowBullTraps", True) \
.SetDisplay("Show Bull Traps", "Close if next candle after buy is red", "General")
self._show_bear_traps = self.Param("ShowBearTraps", True) \
.SetDisplay("Show Bear Traps", "Close if sell signal fails", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._last_red_vector_below_ema50 = None
self._last_buy_signal_index = None
self._last_sell_signal_index = None
self._red_count_under_ema50 = 0
self._green_count_above_ema200 = 0
self._bar_index = 0
self._prev_ha_open = 0.0
self._prev_ha_close = 0.0
self._stop_price = 0.0
self._take_price = 0.0
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(innocent_heikin_ashi_ethereum_strategy, self).OnReseted()
self._last_red_vector_below_ema50 = None
self._last_buy_signal_index = None
self._last_sell_signal_index = None
self._red_count_under_ema50 = 0
self._green_count_above_ema200 = 0
self._bar_index = 0
self._prev_ha_open = 0.0
self._prev_ha_close = 0.0
self._stop_price = 0.0
self._take_price = 0.0
def OnStarted2(self, time):
super(innocent_heikin_ashi_ethereum_strategy, self).OnStarted2(time)
ema50 = ExponentialMovingAverage()
ema50.Length = 50
ema200 = ExponentialMovingAverage()
ema200.Length = 200
lowest = Lowest()
lowest.Length = 28
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema50, ema200, lowest, self.OnProcess).Start()
def OnProcess(self, candle, ema50_val, ema200_val, lowest_val):
if candle.State != CandleStates.Finished:
return
open_p = float(candle.OpenPrice)
high_p = float(candle.HighPrice)
low_p = float(candle.LowPrice)
close_p = float(candle.ClosePrice)
ema50 = float(ema50_val)
ema200 = float(ema200_val)
lowest_v = float(lowest_val)
rr = float(self._risk_reward.Value)
conf = self._confirmation_level.Value
if self._bar_index == 0:
ha_open = (open_p + close_p) / 2.0
ha_close = (open_p + high_p + low_p + close_p) / 4.0
else:
ha_open = (self._prev_ha_open + self._prev_ha_close) / 2.0
ha_close = (open_p + high_p + low_p + close_p) / 4.0
is_green = ha_close > ha_open
is_red = not is_green
if is_red and close_p < ema50:
self._red_count_under_ema50 += 1
if is_red and open_p < ema50 and close_p < ema50:
self._last_red_vector_below_ema50 = self._bar_index
if is_green and open_p > ema200 and open_p > ema50:
self._last_sell_signal_index = self._bar_index
if is_green and close_p > ema200:
self._green_count_above_ema200 += 1
if self._last_red_vector_below_ema50 is not None and is_green:
self._stop_price = lowest_v
self._take_price = close_p + (close_p - self._stop_price) * rr
can_buy = (self._last_red_vector_below_ema50 is not None and
is_green and open_p > ema50 and
(self._last_buy_signal_index is None or self._bar_index > self._last_buy_signal_index))
if can_buy:
if close_p < ema200 and self._red_count_under_ema50 >= conf:
self.BuyMarket()
self._last_buy_signal_index = self._bar_index
self._last_red_vector_below_ema50 = None
self._red_count_under_ema50 = 0
elif self._enable_moon_mode.Value and close_p > ema200 and self._red_count_under_ema50 >= conf:
self.BuyMarket()
self._last_buy_signal_index = self._bar_index
self._last_red_vector_below_ema50 = None
self._red_count_under_ema50 = 0
if self.Position > 0:
if low_p <= self._stop_price or high_p >= self._take_price:
self.SellMarket()
if self._show_sell_signals.Value and self._last_sell_signal_index is not None and is_red:
if open_p > ema200 and close_p > ema200 and self._bar_index == self._last_sell_signal_index + 1:
if self._green_count_above_ema200 >= conf:
self.SellMarket()
self._last_sell_signal_index = None
self._green_count_above_ema200 = 0
if self._show_bull_traps.Value and self._last_buy_signal_index is not None:
if self._bar_index == self._last_buy_signal_index + 1 and is_red:
self.SellMarket()
if self._show_bear_traps.Value and self._last_sell_signal_index is not None:
if self._bar_index == self._last_sell_signal_index + 1 and is_green:
self.SellMarket()
self._last_sell_signal_index = None
self._green_count_above_ema200 = 0
self._prev_ha_open = ha_open
self._prev_ha_close = ha_close
self._bar_index += 1
def CreateClone(self):
return innocent_heikin_ashi_ethereum_strategy()