Estratégia Javo v1
Javo v1 combina velas Heikin Ashi com um par de médias móveis exponenciais. Uma posição é aberta quando a direção HA e o cruzamento do EMA rápido/lento se alinham. A abordagem tenta capturar tendências emergentes enquanto suaviza o ruído.
Detalhes
- Critérios de entrada:
- Comprado: HA altista e
EMA_fast > EMA_slow - Vendido: HA baixista e
EMA_fast < EMA_slow
- Comprado: HA altista e
- Comprado/Vendido: Ambos
- Critérios de saída: Sinal oposto
- Stops: Nenhum
- Valores padrão:
FastEmaPeriod= 1SlowEmaPeriod= 30
- Filtros:
- Categoria: Seguidor de tendência
- Direção: Ambos
- Indicadores: Heikin Ashi, EMA
- Stops: Não
- Complexidade: Baixo
- Período: Por hora
- Sazonalidade: Não
- Redes neurais: Não
- Divergência: Não
- Nível de risco: Médio
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()