La Reversión Upthrust es el complemento bajista del spring y ocurre cuando el precio rompe brevemente por encima de la resistencia pero cae rápidamente de nuevo.
El movimiento elimina a los compradores tardíos antes de revertir a la baja.
Las pruebas indican un rendimiento anual promedio de aproximadamente 58%. Funciona mejor en el mercado de acciones.
Esta estrategia vende en corto una vez que el precio cae de nuevo por debajo del nivel de rompimiento, esperando que la oferta supere a la demanda.
Un stop justo por encima del máximo del upthrust gestiona el riesgo y las posiciones salen si el precio se recupera por encima de ese nivel.
Detalles
Criterios de entrada: señal de indicador
Largo/Corto: Ambos
Criterios de salida: stop-loss o señal opuesta
Stops: Sí, basados en porcentaje
Valores predeterminados:
CandleType = 15 minute
LookbackPeriod = 20
StopLossPercent = 2
La resistencia es el máximo más alto de las LookbackPeriod velas anteriores. La estrategia solo vende: una vela bajista que supera la resistencia y cierra de nuevo por debajo. El stop se coloca StopLossPercent por encima del máximo del upthrust y la posición se cierra cuando una vela cierra por encima.
Filtros:
Categoría: Reversión
Dirección: Ambos
Indicadores: Wyckoff
Stops: Sí
Complejidad: Intermedio
Marco temporal: Intradía
Estacionalidad: No
Redes neuronales: No
Divergencia: No
Nivel de riesgo: Medio
using System;
using System.Collections.Generic;
using System.Linq;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Upthrust Reversal strategy.
/// Resistance is the highest high of the previous LookbackPeriod candles. A bearish candle that breaks above resistance and closes back below it
/// is an upthrust and sells while flat. The stop lies StopLossPercent above the upthrust high, and a close above it closes the position.
/// </summary>
public class UpthrustReversalStrategy : Strategy
{
private readonly StrategyParam<int> _lookbackPeriod;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<DataType> _candleType;
private readonly List<(decimal High, decimal Low)> _candles = [];
private decimal _stopPrice;
/// <summary>
/// Number of previous candles that form the level.
/// </summary>
public int LookbackPeriod
{
get => _lookbackPeriod.Value;
set => _lookbackPeriod.Value = value;
}
/// <summary>
/// Distance of the stop beyond the level, in percent.
/// </summary>
public decimal StopLossPercent
{
get => _stopLossPercent.Value;
set => _stopLossPercent.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public UpthrustReversalStrategy()
{
_lookbackPeriod = Param(nameof(LookbackPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("LookbackPeriod", "Number of previous candles that form the level", "Pattern");
_stopLossPercent = Param(nameof(StopLossPercent), 2m)
.SetNotNegative()
.SetDisplay("Stop Loss %", "Distance of the stop beyond the level, in percent", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_candles.Clear();
_stopPrice = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_candles.Clear();
_stopPrice = default;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
// The level is formed by the candles before this one.
var ready = _candles.Count == LookbackPeriod;
var high = ready ? _candles.Max(c => c.High) : 0m;
var low = ready ? _candles.Min(c => c.Low) : 0m;
_candles.Add((candle.HighPrice, candle.LowPrice));
if (_candles.Count > LookbackPeriod)
_candles.RemoveAt(0);
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
if (Position < 0)
{
if (close >= _stopPrice)
BuyMarket(-Position);
return;
}
if (Position != 0 || !ready || !(candle.HighPrice > high && close < high && close < candle.OpenPrice))
return;
SellMarket(Volume);
_stopPrice = candle.HighPrice * (1 + StopLossPercent / 100m);
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Strategies import Strategy
class upthrust_reversal_strategy(Strategy):
"""
Upthrust Reversal strategy.
Resistance is the highest high of the previous LookbackPeriod candles. A bearish candle that breaks above resistance and closes back below it
is an upthrust and sells while flat. The stop lies StopLossPercent above the upthrust high, and a close above it closes the position.
"""
def __init__(self):
super(upthrust_reversal_strategy, self).__init__()
self._lookback_period = self.Param("LookbackPeriod", 20).SetGreaterThanZero().SetDisplay("LookbackPeriod", "Number of previous candles that form the level", "Pattern")
self._stop_loss_percent = self.Param("StopLossPercent", 2.0).SetNotNegative().SetDisplay("Stop Loss %", "Distance of the stop beyond the level, in percent", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._candles = []
self._stop_price = Decimal(0)
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(upthrust_reversal_strategy, self).OnReseted()
self._candles = []
self._stop_price = Decimal(0)
def OnStarted2(self, time):
super(upthrust_reversal_strategy, self).OnStarted2(time)
self._candles = []
self._stop_price = Decimal(0)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
# The level is formed by the candles before this one.
period = self._lookback_period.Value
ready = len(self._candles) == period
high = max(c[0] for c in self._candles) if ready else Decimal(0)
low = min(c[1] for c in self._candles) if ready else Decimal(0)
self._candles.append((candle.HighPrice, candle.LowPrice))
if len(self._candles) > period:
self._candles.pop(0)
if not self.IsFormedAndOnlineAndAllowTrading():
return
close = candle.ClosePrice
if self.Position < 0:
if close >= self._stop_price:
self.BuyMarket(-self.Position)
return
if self.Position != 0 or not ready or not (candle.HighPrice > high and close < high and close < candle.OpenPrice):
return
percent = Decimal(self._stop_loss_percent.Value) / Decimal(100)
self.SellMarket(self.Volume)
self._stop_price = candle.HighPrice * (Decimal(1) + percent)
def CreateClone(self):
return upthrust_reversal_strategy()