Estrategia Supertrend Volume
Supertrend Volume aumenta el indicador Supertrend con confirmación de volumen. El volumen creciente durante un cambio de dirección del Supertrend refuerza la probabilidad de un nuevo movimiento impulsivo.
Las pruebas indican un rendimiento anual promedio de aproximadamente 145%. Funciona mejor en el mercado de criptomonedas.
La estrategia entra en la dirección de la tendencia con una señal Supertrend solo cuando va acompañada de volumen superior al promedio.
Los stops siguen la línea Supertrend, saliendo cuando el precio cierra al otro lado.
Detalles
- Criterios de entrada: señal de indicador
- Largo/Corto: Ambos
- Criterios de salida: stop-loss o señal opuesta
- Stops: Sí, basado en porcentaje
- Valores predeterminados:
CandleType= 15 minuteStopLoss= 2%
- Filtros:
- Categoría: Seguimiento de tendencia
- Dirección: Ambos
- Indicadores: Supertrend, Volume
- 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 Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy that combines manual Supertrend calculation with ATR for trend direction
/// and volume confirmation for entries.
/// </summary>
public class SupertrendVolumeStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _supertrendPeriod;
private readonly StrategyParam<decimal> _supertrendMultiplier;
private readonly StrategyParam<int> _cooldownBars;
private decimal _atrValue;
private decimal? _upperBand;
private decimal? _lowerBand;
private decimal? _supertrend;
private bool? _isBullish;
private int _cooldown;
/// <summary>
/// Data type for candles.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Period for Supertrend ATR calculation.
/// </summary>
public int SupertrendPeriod
{
get => _supertrendPeriod.Value;
set => _supertrendPeriod.Value = value;
}
/// <summary>
/// Multiplier for Supertrend ATR calculation.
/// </summary>
public decimal SupertrendMultiplier
{
get => _supertrendMultiplier.Value;
set => _supertrendMultiplier.Value = value;
}
/// <summary>
/// Cooldown bars between trades.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="SupertrendVolumeStrategy"/>.
/// </summary>
public SupertrendVolumeStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_supertrendPeriod = Param(nameof(SupertrendPeriod), 10)
.SetRange(5, 30)
.SetDisplay("Supertrend Period", "Period for Supertrend ATR calculation", "Supertrend Settings");
_supertrendMultiplier = Param(nameof(SupertrendMultiplier), 3.0m)
.SetRange(1.0m, 5.0m)
.SetDisplay("Supertrend Multiplier", "Multiplier for Supertrend ATR", "Supertrend Settings");
_cooldownBars = Param(nameof(CooldownBars), 100)
.SetDisplay("Cooldown Bars", "Bars between trades", "General")
.SetRange(5, 500);
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_atrValue = 0;
_upperBand = null;
_lowerBand = null;
_supertrend = null;
_isBullish = null;
_cooldown = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var atr = new AverageTrueRange { Length = SupertrendPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
var atrArea = CreateChartArea();
if (atrArea != null)
DrawIndicator(atrArea, atr);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue atrValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (!atrValue.IsFormed)
return;
var atr = atrValue.ToDecimal();
if (atr <= 0)
return;
_atrValue = atr;
// Calculate Supertrend
var basicPrice = (candle.HighPrice + candle.LowPrice) / 2;
var newUpperBand = basicPrice + (SupertrendMultiplier * _atrValue);
var newLowerBand = basicPrice - (SupertrendMultiplier * _atrValue);
if (_upperBand == null || _lowerBand == null || _supertrend == null || _isBullish == null)
{
_upperBand = newUpperBand;
_lowerBand = newLowerBand;
_supertrend = newUpperBand;
_isBullish = false;
return;
}
// Update upper band
if (newUpperBand < _upperBand || candle.ClosePrice > _upperBand)
_upperBand = newUpperBand;
// Update lower band
if (newLowerBand > _lowerBand || candle.ClosePrice < _lowerBand)
_lowerBand = newLowerBand;
// Determine trend direction
if (_supertrend == _upperBand)
{
if (candle.ClosePrice > _upperBand)
{
_supertrend = _lowerBand;
_isBullish = true;
}
else
{
_supertrend = _upperBand;
_isBullish = false;
}
}
else
{
if (candle.ClosePrice < _lowerBand)
{
_supertrend = _upperBand;
_isBullish = false;
}
else
{
_supertrend = _lowerBand;
_isBullish = true;
}
}
if (_cooldown > 0)
{
_cooldown--;
return;
}
// Entry: bullish supertrend
if (_isBullish.Value && candle.ClosePrice > _supertrend.Value && Position == 0)
{
BuyMarket();
_cooldown = CooldownBars;
}
// Entry: bearish supertrend
else if (!_isBullish.Value && candle.ClosePrice < _supertrend.Value && Position == 0)
{
SellMarket();
_cooldown = CooldownBars;
}
// Exit long on bearish flip
if (Position > 0 && !_isBullish.Value)
{
SellMarket();
_cooldown = CooldownBars;
}
// Exit short on bullish flip
else if (Position < 0 && _isBullish.Value)
{
BuyMarket();
_cooldown = CooldownBars;
}
}
}
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 AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class supertrend_volume_strategy(Strategy):
"""
Supertrend Volume strategy.
Manual Supertrend calculation with ATR for trend direction.
Entries and exits based on Supertrend direction.
"""
def __init__(self):
super(supertrend_volume_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._supertrend_period = self.Param("SupertrendPeriod", 10).SetDisplay("Supertrend Period", "Period for Supertrend ATR calculation", "Supertrend Settings")
self._supertrend_multiplier = self.Param("SupertrendMultiplier", 3.0).SetDisplay("Supertrend Multiplier", "Multiplier for Supertrend ATR", "Supertrend Settings")
self._cooldown_bars = self.Param("CooldownBars", 100).SetDisplay("Cooldown Bars", "Bars between trades", "General")
self._upper_band = None
self._lower_band = None
self._supertrend = None
self._is_bullish = None
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(supertrend_volume_strategy, self).OnReseted()
self._upper_band = None
self._lower_band = None
self._supertrend = None
self._is_bullish = None
self._cooldown = 0
def OnStarted2(self, time):
super(supertrend_volume_strategy, self).OnStarted2(time)
self._upper_band = None
self._lower_band = None
self._supertrend = None
self._is_bullish = None
self._cooldown = 0
atr = AverageTrueRange()
atr.Length = self._supertrend_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(atr, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
atr_area = self.CreateChartArea()
if atr_area is not None:
self.DrawIndicator(atr_area, atr)
def _process_candle(self, candle, atr_iv):
if candle.State != CandleStates.Finished:
return
if not atr_iv.IsFormed:
return
atr = float(atr_iv.Value)
if atr <= 0:
return
close = float(candle.ClosePrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
mult = float(self._supertrend_multiplier.Value)
cd = self._cooldown_bars.Value
# Calculate Supertrend
basic_price = (high + low) / 2.0
new_upper = basic_price + mult * atr
new_lower = basic_price - mult * atr
if self._upper_band is None or self._lower_band is None or self._supertrend is None or self._is_bullish is None:
self._upper_band = new_upper
self._lower_band = new_lower
self._supertrend = new_upper
self._is_bullish = False
return
# Update upper band
if new_upper < self._upper_band or close > self._upper_band:
self._upper_band = new_upper
# Update lower band
if new_lower > self._lower_band or close < self._lower_band:
self._lower_band = new_lower
# Determine trend direction
if self._supertrend == self._upper_band:
if close > self._upper_band:
self._supertrend = self._lower_band
self._is_bullish = True
else:
self._supertrend = self._upper_band
self._is_bullish = False
else:
if close < self._lower_band:
self._supertrend = self._upper_band
self._is_bullish = False
else:
self._supertrend = self._lower_band
self._is_bullish = True
if self._cooldown > 0:
self._cooldown -= 1
return
# Entry: bullish supertrend
if self._is_bullish and close > self._supertrend and self.Position == 0:
self.BuyMarket()
self._cooldown = cd
# Entry: bearish supertrend
elif not self._is_bullish and close < self._supertrend and self.Position == 0:
self.SellMarket()
self._cooldown = cd
# Exit long on bearish flip
if self.Position > 0 and not self._is_bullish:
self.SellMarket()
self._cooldown = cd
# Exit short on bullish flip
elif self.Position < 0 and self._is_bullish:
self.BuyMarket()
self._cooldown = cd
def CreateClone(self):
return supertrend_volume_strategy()