Estrategia de contratendencia con cotización
Descripción general
StairsCountertrendStrategy es una estrategia de negociación de contratendencia que abre posiciones contra una tendencia establecida de una longitud específica, usando un mecanismo de cotización para una entrada más precisa en el mercado.
Componentes principales
public class StairsCountertrendStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleDataType;
private readonly StrategyParam<int> _length;
private QuotingProcessor _quotingProcessor;
private int _bullLength;
private int _bearLength;
}
Parámetros de estrategia
La estrategia permite personalizar los siguientes parámetros:
- CandleDataType - tipo de vela con el que trabajar (predeterminado 1 minuto)
Length- número de velas consecutivas en una dirección para identificar una tendencia (predeterminado 5)
El parámetro Length está disponible para optimización en el rango de 2 a 10 con un paso de 1.
Inicialización de la estrategia
En el método OnStarted2, se restablecen los contadores, se crea la suscripción a velas y se prepara la visualización:
protected override void OnStarted2(DateTime time)
{
// Restablecer contadores al inicio
_bullLength = 0;
_bearLength = 0;
// Crear suscripción a velas
var subscription = SubscribeCandles(CandleDataType);
subscription
.Bind(ProcessCandle)
.Start();
// Configurar visualización en el gráfico
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
base.OnStarted2(time);
}
Procesamiento de velas
El método ProcessCandle se llama para cada vela completada e implementa la lógica de detección de tendencia y gestión del procesador de cotización:
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
// Identificar vela alcista o bajista
if (candle.OpenPrice < candle.ClosePrice)
{
_bullLength++;
_bearLength = 0;
this.AddInfoLog($"Vela alcista detectada. Racha: {_bullLength}");
}
else if (candle.OpenPrice > candle.ClosePrice)
{
_bullLength = 0;
_bearLength++;
this.AddInfoLog($"Vela bajista detectada. Racha: {_bearLength}");
}
// Detener el procesador existente cuando se requiere cambio de dirección
if (_quotingProcessor != null)
{
// Comprobar si el procesador debe limpiarse (cambio de tendencia o posición)
var shouldClearProcessor = false;
// Hay que vender si hay tendencia alcista y no hay posición corta
if (_bullLength >= Length && Position >= 0)
shouldClearProcessor = true;
// Hay que comprar si hay tendencia bajista y no hay posición larga
else if (_bearLength >= Length && Position <= 0)
shouldClearProcessor = true;
if (shouldClearProcessor)
{
_quotingProcessor?.Dispose();
_quotingProcessor = null;
}
}
// Crear nuevo procesador de cotización cuando sea necesario
if (_quotingProcessor == null && IsFormedAndOnlineAndAllowTrading())
{
if (_bullLength >= Length && Position >= 0)
{
// Tendencia alcista - abrir posición corta
CreateQuotingProcessor(Sides.Sell);
this.AddInfoLog($"Iniciando cotización de venta tras {_bullLength} velas alcistas");
}
else if (_bearLength >= Length && Position <= 0)
{
// Tendencia bajista - abrir posición larga
CreateQuotingProcessor(Sides.Buy);
this.AddInfoLog($"Iniciando cotización de compra tras {_bearLength} velas bajistas");
}
}
}
Crear procesador de cotización
El método CreateQuotingProcessor crea un procesador de cotización con la dirección especificada:
private void CreateQuotingProcessor(Sides side)
{
// Crear comportamiento para cotización de mercado
var behavior = new MarketQuotingBehavior(
0, // Sin desplazamiento de precio
new Unit(0.1m, UnitTypes.Percent), // Usar 0.1% como desviación mínima
MarketPriceTypes.Following // Seguir el precio de mercado
);
// Crear procesador de cotización
_quotingProcessor = new(
behavior,
Security,
Portfolio,
side,
Volume, // Volumen de cotización
Volume, // Volumen máximo de orden
TimeSpan.Zero, // Sin timeout
this, // Strategy implementa ISubscriptionProvider
this, // Strategy implementa IMarketRuleContainer
this, // Strategy implementa ITransactionProvider
this, // Strategy implementa ITimeProvider
this, // Strategy implementa IMarketDataProvider
IsFormedAndOnlineAndAllowTrading, // Comprobar permiso de negociación
true, // Usar precios del libro de órdenes
true // Usar precio de la última operación si el libro de órdenes está vacío
)
{
Parent = this
};
// Suscribirse a eventos del procesador
_quotingProcessor.OrderRegistered += order =>
this.AddInfoLog($"Orden {order.TransactionId} registrada al precio {order.Price}");
_quotingProcessor.OrderFailed += fail =>
this.AddInfoLog($"Error de orden: {fail.Error.Message}");
_quotingProcessor.OwnTrade += trade =>
this.AddInfoLog($"Operación ejecutada: {trade.Trade.Volume} a {trade.Trade.Price}");
_quotingProcessor.Finished += isOk =>
{
_quotingProcessor?.Dispose();
_quotingProcessor = null;
};
// Inicializar procesador
_quotingProcessor.Start();
}
Lógica de negociación
- Señal de venta:
Lengthvelas alcistas consecutivas (precio de cierre por encima del precio de apertura) cuando no hay posición corta - Señal de compra:
Lengthvelas bajistas consecutivas (precio de cierre por debajo del precio de apertura) cuando no hay posición larga - Se usa un procesador de cotización para la entrada al mercado, siguiendo el precio de mercado
Características
- La estrategia determina automáticamente los instrumentos con los que trabajar mediante el método
GetWorkingSecurities() - La estrategia solo trabaja con velas completadas
- Se usa cotización en lugar de órdenes de mercado para una entrada al mercado más eficiente
- La estrategia aplica un enfoque de contratendencia, abriendo posiciones contra la tendencia establecida
- Se implementa registro detallado de los eventos principales para depuración
- El procesador de cotización se limpia automáticamente cuando cambia la dirección de tendencia o se alcanzan objetivos
- Se admite visualización de velas y operaciones en el gráfico
- Se implementa optimización del parámetro de longitud de secuencia para la configuración de la estrategia