Estrategia Javo v1
Javo v1 combina velas Heikin Ashi con un par de medias móviles exponenciales. Se abre una posición cuando la dirección de HA y el cruce del EMA rápido/lento se alinean. El enfoque intenta captar tendencias emergentes mientras suaviza el ruido.
Detalles
- Criterios de entrada:
- Largo: HA alcista y
EMA_fast > EMA_slow - Corto: HA bajista y
EMA_fast < EMA_slow
- Largo: HA alcista y
- Largo/Corto: Ambos
- Criterios de salida: Señal opuesta
- Stops: Ninguno
- Valores predeterminados:
FastEmaPeriod= 1SlowEmaPeriod= 30
- Filtros:
- Categoría: Seguimiento de tendencia
- Dirección: Ambos
- Indicadores: Heikin Ashi, EMA
- Stops: No
- Complejidad: Bajo
- Marco temporal: Por hora
- 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>
/// Javo v1 strategy.
/// Builds Heikin Ashi candles and runs a fast and a slow EMA on the Heikin Ashi close. Goes long when the Heikin Ashi
/// candle is bullish and the fast EMA is above the slow one, short when the candle is bearish and the fast EMA is below
/// the slow one. The opposite signal reverses the position.
/// </summary>
public class JavoV1Strategy : Strategy
{
private readonly StrategyParam<int> _fastEmaPeriod;
private readonly StrategyParam<int> _slowEmaPeriod;
private readonly StrategyParam<DataType> _candleType;
private ExponentialMovingAverage _fastEma;
private ExponentialMovingAverage _slowEma;
private decimal? _prevHaOpen;
private decimal? _prevHaClose;
/// <summary>
/// Fast EMA period.
/// </summary>
public int FastEmaPeriod
{
get => _fastEmaPeriod.Value;
set => _fastEmaPeriod.Value = value;
}
/// <summary>
/// Slow EMA period.
/// </summary>
public int SlowEmaPeriod
{
get => _slowEmaPeriod.Value;
set => _slowEmaPeriod.Value = value;
}
/// <summary>
/// Candle type for strategy calculation.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public JavoV1Strategy()
{
_fastEmaPeriod = Param(nameof(FastEmaPeriod), 1)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period on the Heikin Ashi close", "Moving Averages");
_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "Slow EMA period on the Heikin Ashi close", "Moving Averages");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle type", "Candle type for strategy calculation", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_fastEma = null;
_slowEma = null;
_prevHaOpen = null;
_prevHaClose = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevHaOpen = null;
_prevHaClose = null;
_fastEma = new ExponentialMovingAverage { Length = FastEmaPeriod };
_slowEma = new ExponentialMovingAverage { Length = SlowEmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _fastEma);
DrawIndicator(area, _slowEma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var haClose = (candle.OpenPrice + candle.HighPrice + candle.LowPrice + candle.ClosePrice) / 4m;
var haOpen = _prevHaOpen is decimal prevOpen && _prevHaClose is decimal prevClose
? (prevOpen + prevClose) / 2m
: (candle.OpenPrice + candle.ClosePrice) / 2m;
_prevHaOpen = haOpen;
_prevHaClose = haClose;
var fast = _fastEma.Process(haClose, candle.ServerTime, true).ToDecimal();
var slow = _slowEma.Process(haClose, candle.ServerTime, true).ToDecimal();
if (!_fastEma.IsFormed || !_slowEma.IsFormed)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (haClose > haOpen && fast > slow && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (haClose < haOpen && fast < slow && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
}
}
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 javo_v1_strategy(Strategy):
"""
Javo v1 strategy.
Builds Heikin Ashi candles and runs a fast and a slow EMA on the Heikin Ashi close. Goes long when the Heikin Ashi
candle is bullish and the fast EMA is above the slow one, short when the candle is bearish and the fast EMA is below
the slow one. The opposite signal reverses the position.
"""
def __init__(self):
super(javo_v1_strategy, self).__init__()
self._fast_ema_period = self.Param("FastEmaPeriod", 1) \
.SetGreaterThanZero() \
.SetDisplay("Fast EMA", "Fast EMA period on the Heikin Ashi close", "Moving Averages")
self._slow_ema_period = self.Param("SlowEmaPeriod", 30) \
.SetGreaterThanZero() \
.SetDisplay("Slow EMA", "Slow EMA period on the Heikin Ashi close", "Moving Averages")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle type", "Candle type for strategy calculation", "General")
self._fast_ema = None
self._slow_ema = None
self._prev_ha_open = None
self._prev_ha_close = None
@property
def CandleType(self):
return self._candle_type.Value
def GetWorkingSecurities(self):
return [(self.Security, self.CandleType)]
def OnReseted(self):
super(javo_v1_strategy, self).OnReseted()
self._fast_ema = None
self._slow_ema = None
self._prev_ha_open = None
self._prev_ha_close = None
def OnStarted2(self, time):
super(javo_v1_strategy, self).OnStarted2(time)
self._prev_ha_open = None
self._prev_ha_close = None
self._fast_ema = ExponentialMovingAverage()
self._fast_ema.Length = self._fast_ema_period.Value
self._slow_ema = ExponentialMovingAverage()
self._slow_ema.Length = self._slow_ema_period.Value
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, self._fast_ema)
self.DrawIndicator(area, self._slow_ema)
self.DrawOwnTrades(area)
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
open_price = float(candle.OpenPrice)
close = float(candle.ClosePrice)
ha_close = (open_price + float(candle.HighPrice) + float(candle.LowPrice) + close) / 4.0
if self._prev_ha_open is not None and self._prev_ha_close is not None:
ha_open = (self._prev_ha_open + self._prev_ha_close) / 2.0
else:
ha_open = (open_price + close) / 2.0
self._prev_ha_open = ha_open
self._prev_ha_close = ha_close
fast = float(to_decimal(process_float(self._fast_ema, ha_close, candle.ServerTime, True)))
slow = float(to_decimal(process_float(self._slow_ema, ha_close, candle.ServerTime, True)))
if not self._fast_ema.IsFormed or not self._slow_ema.IsFormed:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
if ha_close > ha_open and fast > slow and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif ha_close < ha_open and fast < slow and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
def CreateClone(self):
return javo_v1_strategy()