Inicio
/
Ejemplos de estrategias
Ver en GitHub
Estrategia de Vela Color XMACD
Esta estrategia es una implementación en StockSharp del asesor experto "ColorXMACDCandle". Opera utilizando el indicador MACD e interpreta los cambios de color del histograma o su línea de señal como señales de entrada.
Idea
La estrategia analiza la pendiente de un componente MACD:
Modo Histogram – Una nueva barra del histograma que sube por encima de la barra anterior señala un impulso alcista creciente. Una nueva barra que cae por debajo de la anterior señala impulso bajista.
Modo Signal line – En su lugar se utiliza la pendiente de la línea de señal MACD. Una pendiente ascendente actúa como señal de compra, mientras que una descendente actúa como señal de venta.
Cuando el componente elegido gira hacia arriba y no estaba subiendo antes, cualquier posición corta puede cerrarse y puede abrirse una nueva posición larga. Cuando el componente gira hacia abajo y no estaba cayendo antes, cualquier posición larga puede cerrarse y puede abrirse una posición corta.
El comportamiento de apertura y cierre de posiciones está controlado por parámetros separados, permitiendo al usuario habilitar o deshabilitar cada acción de forma independiente.
Parámetros
Mode – Fuente de señales: Histogram o SignalLine.
FastPeriod – Período de la EMA rápida para MACD.
SlowPeriod – Período de la EMA lenta para MACD.
SignalPeriod – Período de suavizado de la señal MACD.
EnableBuyOpen – Permitir abrir posiciones largas.
EnableSellOpen – Permitir abrir posiciones cortas.
EnableBuyClose – Permitir cerrar posiciones largas.
EnableSellClose – Permitir cerrar posiciones cortas.
CandleType – Tipo de vela para los cálculos.
Reglas de trading
Suscribirse a la serie de velas seleccionada y calcular el indicador MACD.
Rastrear la pendiente del histograma o la línea de señal según el modo seleccionado.
Cuando la pendiente gira hacia arriba, cerrar cualquier posición corta (si está permitido) y opcionalmente abrir una posición larga.
Cuando la pendiente gira hacia abajo, cerrar cualquier posición larga (si está permitido) y opcionalmente abrir una posición corta.
La estrategia no incluye mecanismos de stop-loss ni take-profit. La gestión del riesgo puede añadirse por separado si es necesario.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy that reacts to slope changes of the MACD histogram.
/// Buys when histogram slope turns up, sells when it turns down.
/// </summary>
public class ColorXMacdCandleStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _signalPeriod;
private readonly StrategyParam<DataType> _candleType;
private ExponentialMovingAverage _signalMa;
private decimal? _prevHist;
private decimal? _prevPrevHist;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int SignalPeriod { get => _signalPeriod.Value; set => _signalPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ColorXMacdCandleStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA period", "MACD");
_slowPeriod = Param(nameof(SlowPeriod), 26)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA period", "MACD");
_signalPeriod = Param(nameof(SignalPeriod), 9)
.SetGreaterThanZero()
.SetDisplay("Signal Period", "Signal line period", "MACD");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle type for calculations", "Common");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_signalMa = null;
_prevHist = null;
_prevPrevHist = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var macd = new MovingAverageConvergenceDivergence();
macd.ShortMa.Length = FastPeriod;
macd.LongMa.Length = SlowPeriod;
_signalMa = new ExponentialMovingAverage { Length = SignalPeriod };
Indicators.Add(_signalMa);
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(macd, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, macd);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!macdValue.IsFormed)
return;
var macdLine = macdValue.GetValue<decimal>();
var signalResult = _signalMa.Process(macdValue);
if (!signalResult.IsFormed)
return;
var signalLine = signalResult.GetValue<decimal>();
var hist = macdLine - signalLine;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevPrevHist = _prevHist;
_prevHist = hist;
return;
}
if (_prevHist is decimal ph && _prevPrevHist is decimal pph)
{
var wasRising = ph > pph;
var nowRising = hist > ph;
// Histogram slope turns up -> buy
if (!wasRising && nowRising && Position <= 0)
BuyMarket();
// Histogram slope turns down -> sell
else if (wasRising && !nowRising && Position >= 0)
SellMarket();
}
_prevPrevHist = _prevHist;
_prevHist = hist;
}
}
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 MovingAverageConvergenceDivergence, ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class color_xmacd_candle_strategy(Strategy):
def __init__(self):
super(color_xmacd_candle_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 12) \
.SetDisplay("Fast Period", "Fast EMA period", "MACD")
self._slow_period = self.Param("SlowPeriod", 26) \
.SetDisplay("Slow Period", "Slow EMA period", "MACD")
self._signal_period = self.Param("SignalPeriod", 9) \
.SetDisplay("Signal Period", "Signal line period", "MACD")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle type for calculations", "Common")
self._signal_ma = None
self._prev_hist = None
self._prev_prev_hist = None
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def signal_period(self):
return self._signal_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(color_xmacd_candle_strategy, self).OnReseted()
self._signal_ma = None
self._prev_hist = None
self._prev_prev_hist = None
def OnStarted2(self, time):
super(color_xmacd_candle_strategy, self).OnStarted2(time)
macd = MovingAverageConvergenceDivergence()
macd.ShortMa.Length = self.fast_period
macd.LongMa.Length = self.slow_period
self._signal_ma = ExponentialMovingAverage()
self._signal_ma.Length = self.signal_period
self.Indicators.Add(self._signal_ma)
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(macd, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, macd)
self.DrawOwnTrades(area)
def process_candle(self, candle, macd_value):
if candle.State != CandleStates.Finished:
return
if not macd_value.IsFormed:
return
macd_line = float(macd_value)
signal_result = self._signal_ma.Process(macd_value)
if not signal_result.IsFormed:
return
signal_line = float(signal_result)
hist = macd_line - signal_line
if self._prev_hist is not None and self._prev_prev_hist is not None:
was_rising = self._prev_hist > self._prev_prev_hist
now_rising = hist > self._prev_hist
if not was_rising and now_rising and self.Position <= 0:
self.BuyMarket()
elif was_rising and not now_rising and self.Position >= 0:
self.SellMarket()
self._prev_prev_hist = self._prev_hist
self._prev_hist = hist
def CreateClone(self):
return color_xmacd_candle_strategy()