Estrategia Forex Fire EMA MA RSI
Estrategia de tendencia multi-marco temporal que utiliza EMA, MA y confirmación de RSI. Usa velas de 4h para confluencia y velas de 15m para entradas.
Detalles
- Criterios de entrada:
- Largo: EMA corta por encima de la EMA larga, precio por encima de la MA, RSI rápido por encima del RSI lento y >50, volumen creciente con confirmación del marco temporal superior.
- Corto: Condiciones opuestas.
- Largo/Corto: Ambos.
- Criterios de salida:
- Cruce de EMA o RSI alcanzando umbrales.
- Stop loss, take profit, trailing stop y salida basada en ATR opcionales.
- Stops: Sí, configurable.
- Valores predeterminados:
EmaShortLength= 13EmaLongLength= 62MaLength= 200MaType= MovingAverageTypeEnum.SimpleRsiSlowLength= 28RsiFastLength= 7RsiOverbought= 70RsiOversold= 30UseStopLoss= trueStopLossPercent= 2UseTakeProfit= trueTakeProfitPercent= 4UseTrailingStop= trueTrailingPercent= 1.5UseAtrExits= trueAtrMultiplier= 2AtrLength= 14EntryCandleType= TimeSpan.FromMinutes(15).TimeFrame()ConfluenceCandleType= TimeSpan.FromHours(4).TimeFrame()
- Filtros:
- Categoría: Tendencia
- Dirección: Ambos
- Indicadores: EMA, MA, RSI, ATR
- Stops: Sí
- Complejidad: Medio
- Marco temporal: Multi-marco temporal
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
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>
/// Forex Fire EMA MA RSI strategy.
/// On entry candles it goes long when the short EMA is above the long EMA, the close is above the moving average, the fast RSI is
/// above the slow RSI and above 50, volume rose against the previous candle and on the confluence timeframe the short EMA is above the
/// long EMA; the short entry mirrors every condition. An opposite entry reverses the position. A long closes when the short EMA drops
/// below the long EMA or the fast RSI reaches RsiOverbought, a short when the short EMA rises above the long EMA or the fast RSI
/// reaches RsiOversold. Optional percent stop loss, take profit and trailing stop, and an ATR exit AtrMultiplier ATRs against the
/// entry, close the position as well.
/// </summary>
public class ForexFireEmaMaRsiStrategy : Strategy
{
/// <summary>
/// Moving average types.
/// </summary>
public enum MovingAverageTypeEnum
{
/// <summary>
/// Simple moving average.
/// </summary>
Simple,
/// <summary>
/// Exponential moving average.
/// </summary>
Exponential,
/// <summary>
/// Weighted moving average.
/// </summary>
Weighted,
/// <summary>
/// Smoothed moving average.
/// </summary>
Smoothed,
}
private const decimal _rsiMiddle = 50m;
private readonly StrategyParam<int> _emaShortLength;
private readonly StrategyParam<int> _emaLongLength;
private readonly StrategyParam<int> _maLength;
private readonly StrategyParam<MovingAverageTypeEnum> _maType;
private readonly StrategyParam<int> _rsiSlowLength;
private readonly StrategyParam<int> _rsiFastLength;
private readonly StrategyParam<decimal> _rsiOverbought;
private readonly StrategyParam<decimal> _rsiOversold;
private readonly StrategyParam<bool> _useStopLoss;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<bool> _useTakeProfit;
private readonly StrategyParam<decimal> _takeProfitPercent;
private readonly StrategyParam<bool> _useTrailingStop;
private readonly StrategyParam<decimal> _trailingPercent;
private readonly StrategyParam<bool> _useAtrExits;
private readonly StrategyParam<decimal> _atrMultiplier;
private readonly StrategyParam<int> _atrLength;
private readonly StrategyParam<DataType> _entryCandleType;
private readonly StrategyParam<DataType> _confluenceCandleType;
private int _htfTrend;
private decimal? _prevVolume;
private decimal _entryPrice;
private decimal _bestPrice;
/// <summary>
/// Short EMA length.
/// </summary>
public int EmaShortLength
{
get => _emaShortLength.Value;
set => _emaShortLength.Value = value;
}
/// <summary>
/// Long EMA length.
/// </summary>
public int EmaLongLength
{
get => _emaLongLength.Value;
set => _emaLongLength.Value = value;
}
/// <summary>
/// Trend moving average length.
/// </summary>
public int MaLength
{
get => _maLength.Value;
set => _maLength.Value = value;
}
/// <summary>
/// Trend moving average type.
/// </summary>
public MovingAverageTypeEnum MaType
{
get => _maType.Value;
set => _maType.Value = value;
}
/// <summary>
/// Slow RSI length.
/// </summary>
public int RsiSlowLength
{
get => _rsiSlowLength.Value;
set => _rsiSlowLength.Value = value;
}
/// <summary>
/// Fast RSI length.
/// </summary>
public int RsiFastLength
{
get => _rsiFastLength.Value;
set => _rsiFastLength.Value = value;
}
/// <summary>
/// Fast RSI level that closes a long.
/// </summary>
public decimal RsiOverbought
{
get => _rsiOverbought.Value;
set => _rsiOverbought.Value = value;
}
/// <summary>
/// Fast RSI level that closes a short.
/// </summary>
public decimal RsiOversold
{
get => _rsiOversold.Value;
set => _rsiOversold.Value = value;
}
/// <summary>
/// Use the percent stop loss.
/// </summary>
public bool UseStopLoss
{
get => _useStopLoss.Value;
set => _useStopLoss.Value = value;
}
/// <summary>
/// Stop loss percentage from entry price.
/// </summary>
public decimal StopLossPercent
{
get => _stopLossPercent.Value;
set => _stopLossPercent.Value = value;
}
/// <summary>
/// Use the percent take profit.
/// </summary>
public bool UseTakeProfit
{
get => _useTakeProfit.Value;
set => _useTakeProfit.Value = value;
}
/// <summary>
/// Take profit percentage from entry price.
/// </summary>
public decimal TakeProfitPercent
{
get => _takeProfitPercent.Value;
set => _takeProfitPercent.Value = value;
}
/// <summary>
/// Use the percent trailing stop.
/// </summary>
public bool UseTrailingStop
{
get => _useTrailingStop.Value;
set => _useTrailingStop.Value = value;
}
/// <summary>
/// Trailing stop percentage from the best price.
/// </summary>
public decimal TrailingPercent
{
get => _trailingPercent.Value;
set => _trailingPercent.Value = value;
}
/// <summary>
/// Use the ATR exit.
/// </summary>
public bool UseAtrExits
{
get => _useAtrExits.Value;
set => _useAtrExits.Value = value;
}
/// <summary>
/// ATR multiplier of the exit distance.
/// </summary>
public decimal AtrMultiplier
{
get => _atrMultiplier.Value;
set => _atrMultiplier.Value = value;
}
/// <summary>
/// ATR length.
/// </summary>
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
/// <summary>
/// Entry candle type.
/// </summary>
public DataType EntryCandleType
{
get => _entryCandleType.Value;
set => _entryCandleType.Value = value;
}
/// <summary>
/// Confluence candle type.
/// </summary>
public DataType ConfluenceCandleType
{
get => _confluenceCandleType.Value;
set => _confluenceCandleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public ForexFireEmaMaRsiStrategy()
{
_emaShortLength = Param(nameof(EmaShortLength), 13)
.SetGreaterThanZero()
.SetDisplay("EMA Short", "Short EMA length", "Indicators");
_emaLongLength = Param(nameof(EmaLongLength), 62)
.SetGreaterThanZero()
.SetDisplay("EMA Long", "Long EMA length", "Indicators");
_maLength = Param(nameof(MaLength), 200)
.SetGreaterThanZero()
.SetDisplay("MA Length", "Trend moving average length", "Indicators");
_maType = Param(nameof(MaType), MovingAverageTypeEnum.Simple)
.SetDisplay("MA Type", "Trend moving average type", "Indicators");
_rsiSlowLength = Param(nameof(RsiSlowLength), 28)
.SetGreaterThanZero()
.SetDisplay("RSI Slow", "Slow RSI length", "Indicators");
_rsiFastLength = Param(nameof(RsiFastLength), 7)
.SetGreaterThanZero()
.SetDisplay("RSI Fast", "Fast RSI length", "Indicators");
_rsiOverbought = Param(nameof(RsiOverbought), 70m)
.SetDisplay("RSI Overbought", "Fast RSI level that closes a long", "Indicators");
_rsiOversold = Param(nameof(RsiOversold), 30m)
.SetDisplay("RSI Oversold", "Fast RSI level that closes a short", "Indicators");
_useStopLoss = Param(nameof(UseStopLoss), true)
.SetDisplay("Use Stop Loss", "Use the percent stop loss", "Risk");
_stopLossPercent = Param(nameof(StopLossPercent), 2m)
.SetNotNegative()
.SetDisplay("Stop Loss %", "Stop loss percentage from entry price", "Risk");
_useTakeProfit = Param(nameof(UseTakeProfit), true)
.SetDisplay("Use Take Profit", "Use the percent take profit", "Risk");
_takeProfitPercent = Param(nameof(TakeProfitPercent), 4m)
.SetNotNegative()
.SetDisplay("Take Profit %", "Take profit percentage from entry price", "Risk");
_useTrailingStop = Param(nameof(UseTrailingStop), true)
.SetDisplay("Use Trailing Stop", "Use the percent trailing stop", "Risk");
_trailingPercent = Param(nameof(TrailingPercent), 1.5m)
.SetNotNegative()
.SetDisplay("Trailing %", "Trailing stop percentage from the best price", "Risk");
_useAtrExits = Param(nameof(UseAtrExits), true)
.SetDisplay("Use ATR Exits", "Use the ATR exit", "Risk");
_atrMultiplier = Param(nameof(AtrMultiplier), 2m)
.SetNotNegative()
.SetDisplay("ATR Multiplier", "ATR multiplier of the exit distance", "Risk");
_atrLength = Param(nameof(AtrLength), 14)
.SetGreaterThanZero()
.SetDisplay("ATR Length", "ATR length", "Risk");
_entryCandleType = Param(nameof(EntryCandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Entry Candles", "Candles for entries", "General");
_confluenceCandleType = Param(nameof(ConfluenceCandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Confluence Candles", "Higher timeframe candles for confluence", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, EntryCandleType), (Security, ConfluenceCandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
ResetState();
}
private void ResetState()
{
_htfTrend = 0;
_prevVolume = null;
_entryPrice = 0m;
_bestPrice = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
ResetState();
var emaShort = new ExponentialMovingAverage { Length = EmaShortLength };
var emaLong = new ExponentialMovingAverage { Length = EmaLongLength };
var ma = CreateMovingAverage(MaType, MaLength);
var rsiFast = new RelativeStrengthIndex { Length = RsiFastLength };
var rsiSlow = new RelativeStrengthIndex { Length = RsiSlowLength };
var atr = new AverageTrueRange { Length = AtrLength };
var htfEmaShort = new ExponentialMovingAverage { Length = EmaShortLength };
var htfEmaLong = new ExponentialMovingAverage { Length = EmaLongLength };
SubscribeCandles(ConfluenceCandleType)
.Bind(htfEmaShort, htfEmaLong, ProcessConfluence)
.Start();
var subscription = SubscribeCandles(EntryCandleType);
subscription
.Bind(emaShort, emaLong, ma, rsiFast, rsiSlow, atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, emaShort);
DrawIndicator(area, emaLong);
DrawIndicator(area, ma);
DrawOwnTrades(area);
}
}
private static DecimalLengthIndicator CreateMovingAverage(MovingAverageTypeEnum type, int length)
{
return type switch
{
MovingAverageTypeEnum.Exponential => new ExponentialMovingAverage { Length = length },
MovingAverageTypeEnum.Weighted => new WeightedMovingAverage { Length = length },
MovingAverageTypeEnum.Smoothed => new SmoothedMovingAverage { Length = length },
_ => new SimpleMovingAverage { Length = length },
};
}
private void ProcessConfluence(ICandleMessage candle, decimal emaShort, decimal emaLong)
{
if (candle.State != CandleStates.Finished)
return;
_htfTrend = emaShort > emaLong ? 1 : emaShort < emaLong ? -1 : 0;
}
private void ProcessCandle(ICandleMessage candle, decimal emaShort, decimal emaLong, decimal ma, decimal rsiFast, decimal rsiSlow, decimal atr)
{
if (candle.State != CandleStates.Finished)
return;
var prevVolume = _prevVolume;
_prevVolume = candle.TotalVolume;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
if (Position > 0)
{
_bestPrice = Math.Max(_bestPrice, candle.HighPrice);
if (emaShort < emaLong || rsiFast >= RsiOverbought || LongStopHit(candle, atr))
{
SellMarket(Position);
return;
}
}
else if (Position < 0)
{
_bestPrice = _bestPrice == 0 ? candle.LowPrice : Math.Min(_bestPrice, candle.LowPrice);
if (emaShort > emaLong || rsiFast <= RsiOversold || ShortStopHit(candle, atr))
{
BuyMarket(-Position);
return;
}
}
if (prevVolume is not decimal lastVolume)
return;
var volumeRising = candle.TotalVolume > lastVolume;
var longSignal = emaShort > emaLong && close > ma && rsiFast > rsiSlow && rsiFast > _rsiMiddle && volumeRising && _htfTrend > 0;
var shortSignal = emaShort < emaLong && close < ma && rsiFast < rsiSlow && rsiFast < _rsiMiddle && volumeRising && _htfTrend < 0;
if (longSignal && Position <= 0)
{
BuyMarket(Volume + Math.Abs(Position));
_entryPrice = close;
_bestPrice = close;
}
else if (shortSignal && Position >= 0)
{
SellMarket(Volume + Math.Abs(Position));
_entryPrice = close;
_bestPrice = close;
}
}
private bool LongStopHit(ICandleMessage candle, decimal atr)
{
if (_entryPrice <= 0)
return false;
if (UseStopLoss && StopLossPercent > 0 && candle.LowPrice <= _entryPrice * (1 - StopLossPercent / 100m))
return true;
if (UseTakeProfit && TakeProfitPercent > 0 && candle.HighPrice >= _entryPrice * (1 + TakeProfitPercent / 100m))
return true;
if (UseTrailingStop && TrailingPercent > 0 && candle.LowPrice <= _bestPrice * (1 - TrailingPercent / 100m))
return true;
return UseAtrExits && AtrMultiplier > 0 && candle.ClosePrice <= _entryPrice - AtrMultiplier * atr;
}
private bool ShortStopHit(ICandleMessage candle, decimal atr)
{
if (_entryPrice <= 0)
return false;
if (UseStopLoss && StopLossPercent > 0 && candle.HighPrice >= _entryPrice * (1 + StopLossPercent / 100m))
return true;
if (UseTakeProfit && TakeProfitPercent > 0 && candle.LowPrice <= _entryPrice * (1 - TakeProfitPercent / 100m))
return true;
if (UseTrailingStop && TrailingPercent > 0 && candle.HighPrice >= _bestPrice * (1 + TrailingPercent / 100m))
return true;
return UseAtrExits && AtrMultiplier > 0 && candle.ClosePrice >= _entryPrice + AtrMultiplier * atr;
}
}
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, SimpleMovingAverage, WeightedMovingAverage, SmoothedMovingAverage, RelativeStrengthIndex, AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
MA_SIMPLE = 0
MA_EXPONENTIAL = 1
MA_WEIGHTED = 2
MA_SMOOTHED = 3
RSI_MIDDLE = 50.0
class forex_fire_ema_ma_rsi_strategy(Strategy):
"""
Forex Fire EMA MA RSI strategy.
On entry candles it goes long when the short EMA is above the long EMA, the close is above the moving average, the fast RSI is
above the slow RSI and above 50, volume rose against the previous candle and on the confluence timeframe the short EMA is above the
long EMA; the short entry mirrors every condition. An opposite entry reverses the position. A long closes when the short EMA drops
below the long EMA or the fast RSI reaches RsiOverbought, a short when the short EMA rises above the long EMA or the fast RSI
reaches RsiOversold. Optional percent stop loss, take profit and trailing stop, and an ATR exit AtrMultiplier ATRs against the
entry, close the position as well.
"""
def __init__(self):
super(forex_fire_ema_ma_rsi_strategy, self).__init__()
self._ema_short_length = self.Param("EmaShortLength", 13).SetGreaterThanZero().SetDisplay("EMA Short", "Short EMA length", "Indicators")
self._ema_long_length = self.Param("EmaLongLength", 62).SetGreaterThanZero().SetDisplay("EMA Long", "Long EMA length", "Indicators")
self._ma_length = self.Param("MaLength", 200).SetGreaterThanZero().SetDisplay("MA Length", "Trend moving average length", "Indicators")
self._ma_type = self.Param("MaType", MA_SIMPLE).SetDisplay("MA Type", "Trend moving average type (0 Simple, 1 Exponential, 2 Weighted, 3 Smoothed)", "Indicators")
self._rsi_slow_length = self.Param("RsiSlowLength", 28).SetGreaterThanZero().SetDisplay("RSI Slow", "Slow RSI length", "Indicators")
self._rsi_fast_length = self.Param("RsiFastLength", 7).SetGreaterThanZero().SetDisplay("RSI Fast", "Fast RSI length", "Indicators")
self._rsi_overbought = self.Param("RsiOverbought", 70.0).SetDisplay("RSI Overbought", "Fast RSI level that closes a long", "Indicators")
self._rsi_oversold = self.Param("RsiOversold", 30.0).SetDisplay("RSI Oversold", "Fast RSI level that closes a short", "Indicators")
self._use_stop_loss = self.Param("UseStopLoss", True).SetDisplay("Use Stop Loss", "Use the percent stop loss", "Risk")
self._stop_loss_percent = self.Param("StopLossPercent", 2.0).SetNotNegative().SetDisplay("Stop Loss %", "Stop loss percentage from entry price", "Risk")
self._use_take_profit = self.Param("UseTakeProfit", True).SetDisplay("Use Take Profit", "Use the percent take profit", "Risk")
self._take_profit_percent = self.Param("TakeProfitPercent", 4.0).SetNotNegative().SetDisplay("Take Profit %", "Take profit percentage from entry price", "Risk")
self._use_trailing_stop = self.Param("UseTrailingStop", True).SetDisplay("Use Trailing Stop", "Use the percent trailing stop", "Risk")
self._trailing_percent = self.Param("TrailingPercent", 1.5).SetNotNegative().SetDisplay("Trailing %", "Trailing stop percentage from the best price", "Risk")
self._use_atr_exits = self.Param("UseAtrExits", True).SetDisplay("Use ATR Exits", "Use the ATR exit", "Risk")
self._atr_multiplier = self.Param("AtrMultiplier", 2.0).SetNotNegative().SetDisplay("ATR Multiplier", "ATR multiplier of the exit distance", "Risk")
self._atr_length = self.Param("AtrLength", 14).SetGreaterThanZero().SetDisplay("ATR Length", "ATR length", "Risk")
self._entry_candle_type = self.Param("EntryCandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))).SetDisplay("Entry Candles", "Candles for entries", "General")
self._confluence_candle_type = self.Param("ConfluenceCandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).SetDisplay("Confluence Candles", "Higher timeframe candles for confluence", "General")
self._reset_state()
def _reset_state(self):
self._htf_trend = 0
self._prev_volume = None
self._entry_price = 0.0
self._best_price = 0.0
def GetWorkingSecurities(self):
return [(self.Security, self._entry_candle_type.Value), (self.Security, self._confluence_candle_type.Value)]
def OnReseted(self):
super(forex_fire_ema_ma_rsi_strategy, self).OnReseted()
self._reset_state()
def OnStarted2(self, time):
super(forex_fire_ema_ma_rsi_strategy, self).OnStarted2(time)
self._reset_state()
ema_short = ExponentialMovingAverage()
ema_short.Length = self._ema_short_length.Value
ema_long = ExponentialMovingAverage()
ema_long.Length = self._ema_long_length.Value
ma = self._create_ma(int(self._ma_type.Value), self._ma_length.Value)
rsi_fast = RelativeStrengthIndex()
rsi_fast.Length = self._rsi_fast_length.Value
rsi_slow = RelativeStrengthIndex()
rsi_slow.Length = self._rsi_slow_length.Value
atr = AverageTrueRange()
atr.Length = self._atr_length.Value
htf_ema_short = ExponentialMovingAverage()
htf_ema_short.Length = self._ema_short_length.Value
htf_ema_long = ExponentialMovingAverage()
htf_ema_long.Length = self._ema_long_length.Value
self.SubscribeCandles(self._confluence_candle_type.Value).Bind(htf_ema_short, htf_ema_long, self._process_confluence).Start()
subscription = self.SubscribeCandles(self._entry_candle_type.Value)
subscription.Bind(ema_short, ema_long, ma, rsi_fast, rsi_slow, atr, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema_short)
self.DrawIndicator(area, ema_long)
self.DrawIndicator(area, ma)
self.DrawOwnTrades(area)
def _create_ma(self, ma_type, length):
if ma_type == MA_EXPONENTIAL:
ma = ExponentialMovingAverage()
elif ma_type == MA_WEIGHTED:
ma = WeightedMovingAverage()
elif ma_type == MA_SMOOTHED:
ma = SmoothedMovingAverage()
else:
ma = SimpleMovingAverage()
ma.Length = length
return ma
def _process_confluence(self, candle, ema_short_value, ema_long_value):
if candle.State != CandleStates.Finished:
return
ema_short = float(ema_short_value)
ema_long = float(ema_long_value)
self._htf_trend = 1 if ema_short > ema_long else (-1 if ema_short < ema_long else 0)
def _process_candle(self, candle, ema_short_value, ema_long_value, ma_value, rsi_fast_value, rsi_slow_value, atr_value):
if candle.State != CandleStates.Finished:
return
last_volume = self._prev_volume
volume = float(candle.TotalVolume)
self._prev_volume = volume
if not self.IsFormedAndOnlineAndAllowTrading():
return
ema_short = float(ema_short_value)
ema_long = float(ema_long_value)
ma = float(ma_value)
rsi_fast = float(rsi_fast_value)
rsi_slow = float(rsi_slow_value)
atr = float(atr_value)
close = float(candle.ClosePrice)
if self.Position > 0:
self._best_price = max(self._best_price, float(candle.HighPrice))
if ema_short < ema_long or rsi_fast >= float(self._rsi_overbought.Value) or self._long_stop_hit(candle, atr):
self.SellMarket(self.Position)
return
elif self.Position < 0:
self._best_price = float(candle.LowPrice) if self._best_price == 0 else min(self._best_price, float(candle.LowPrice))
if ema_short > ema_long or rsi_fast <= float(self._rsi_oversold.Value) or self._short_stop_hit(candle, atr):
self.BuyMarket(-self.Position)
return
if last_volume is None:
return
volume_rising = volume > last_volume
long_signal = ema_short > ema_long and close > ma and rsi_fast > rsi_slow and rsi_fast > RSI_MIDDLE and volume_rising and self._htf_trend > 0
short_signal = ema_short < ema_long and close < ma and rsi_fast < rsi_slow and rsi_fast < RSI_MIDDLE and volume_rising and self._htf_trend < 0
if long_signal and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
self._entry_price = close
self._best_price = close
elif short_signal and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
self._entry_price = close
self._best_price = close
def _long_stop_hit(self, candle, atr):
if self._entry_price <= 0:
return False
low = float(candle.LowPrice)
high = float(candle.HighPrice)
sl = float(self._stop_loss_percent.Value)
tp = float(self._take_profit_percent.Value)
trail = float(self._trailing_percent.Value)
mult = float(self._atr_multiplier.Value)
if self._use_stop_loss.Value and sl > 0 and low <= self._entry_price * (1.0 - sl / 100.0):
return True
if self._use_take_profit.Value and tp > 0 and high >= self._entry_price * (1.0 + tp / 100.0):
return True
if self._use_trailing_stop.Value and trail > 0 and low <= self._best_price * (1.0 - trail / 100.0):
return True
return self._use_atr_exits.Value and mult > 0 and float(candle.ClosePrice) <= self._entry_price - mult * atr
def _short_stop_hit(self, candle, atr):
if self._entry_price <= 0:
return False
low = float(candle.LowPrice)
high = float(candle.HighPrice)
sl = float(self._stop_loss_percent.Value)
tp = float(self._take_profit_percent.Value)
trail = float(self._trailing_percent.Value)
mult = float(self._atr_multiplier.Value)
if self._use_stop_loss.Value and sl > 0 and high >= self._entry_price * (1.0 + sl / 100.0):
return True
if self._use_take_profit.Value and tp > 0 and low <= self._entry_price * (1.0 - tp / 100.0):
return True
if self._use_trailing_stop.Value and trail > 0 and high >= self._best_price * (1.0 + trail / 100.0):
return True
return self._use_atr_exits.Value and mult > 0 and float(candle.ClosePrice) >= self._entry_price + mult * atr
def CreateClone(self):
return forex_fire_ema_ma_rsi_strategy()