Estrategia Three Kilos BTC 15m
La estrategia Three Kilos BTC 15m combina tres Medias Móviles Exponenciales Triples (TEMA) con un filtro Supertrend. Se abre una posición larga cuando la TEMA media cruza por encima de la TEMA corta, permanece por encima de la TEMA lenta y el Supertrend indica una tendencia alcista. Se abre una posición corta cuando la TEMA corta cruza por encima de la TEMA media, permanece por debajo de la TEMA lenta y el Supertrend muestra una tendencia bajista. Un take profit y stop loss de porcentaje fijo gestionan el riesgo.
Detalles
- Criterios de entrada:
- Largo: TEMA2 cruza por encima de TEMA1, TEMA2 > TEMA3, tendencia alcista en Supertrend.
- Corto: TEMA1 cruza por encima de TEMA2, TEMA2 < TEMA3, tendencia bajista en Supertrend.
- Largo/Corto: Ambos lados.
- Criterios de salida:
- Take profit o stop loss.
- Stops: Take profit del 1% y stop loss del 1%.
- Valores predeterminados:
ShortPeriod= 30LongPeriod= 50Long2Period= 140AtrLength= 10Multiplier= 2TakeProfit= 1%StopLoss= 1%
- Filtros:
- Categoría: Seguimiento de tendencia
- Dirección: Ambos
- Indicadores: TEMA, Supertrend, ATR
- Stops: Take profit y stop loss
- Complejidad: Moderado
- Marco temporal: 15m
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>
/// Triple EMA crossover with Supertrend filter strategy (simplified 3Kilos).
/// Uses fast/slow EMA crossover for entries.
/// Uses SuperTrend indicator for trend confirmation and exits.
/// </summary>
public class ThreeKilosBtc15mStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<int> _cooldownBars;
private ExponentialMovingAverage _fastEma;
private ExponentialMovingAverage _slowEma;
private SuperTrend _superTrend;
private decimal _prevFast;
private decimal _prevSlow;
private int _cooldownRemaining;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastLength
{
get => _fastLength.Value;
set => _fastLength.Value = value;
}
public int SlowLength
{
get => _slowLength.Value;
set => _slowLength.Value = value;
}
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
public ThreeKilosBtc15mStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle type for strategy calculation", "General");
_fastLength = Param(nameof(FastLength), 8)
.SetDisplay("Fast EMA", "Fast EMA length", "Indicators")
.SetGreaterThanZero();
_slowLength = Param(nameof(SlowLength), 21)
.SetDisplay("Slow EMA", "Slow EMA length", "Indicators")
.SetGreaterThanZero();
_cooldownBars = Param(nameof(CooldownBars), 12)
.SetDisplay("Cooldown Bars", "Bars between trades", "Risk");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_fastEma = null;
_slowEma = null;
_superTrend = null;
_prevFast = 0;
_prevSlow = 0;
_cooldownRemaining = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fastEma = new ExponentialMovingAverage { Length = FastLength };
_slowEma = new ExponentialMovingAverage { Length = SlowLength };
_superTrend = new SuperTrend { Length = 10, Multiplier = 2m };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(_fastEma, _slowEma, _superTrend, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _fastEma);
DrawIndicator(area, _slowEma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue fastVal, IIndicatorValue slowVal, IIndicatorValue stVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!_fastEma.IsFormed || !_slowEma.IsFormed || !_superTrend.IsFormed)
return;
var fast = fastVal.ToDecimal();
var slow = slowVal.ToDecimal();
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevFast = fast;
_prevSlow = slow;
return;
}
// SuperTrend direction
var isUpTrend = stVal is SuperTrendIndicatorValue sv && sv.IsUpTrend;
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
_prevFast = fast;
_prevSlow = slow;
return;
}
// EMA crossover
var bullCross = _prevFast > 0 && _prevFast <= _prevSlow && fast > slow;
var bearCross = _prevFast > 0 && _prevFast >= _prevSlow && fast < slow;
// Buy: bullish EMA cross + Supertrend uptrend
if (bullCross && isUpTrend && Position <= 0)
{
if (Position < 0)
BuyMarket(Math.Abs(Position));
BuyMarket(Volume);
_cooldownRemaining = CooldownBars;
}
// Sell: bearish EMA cross + Supertrend downtrend
else if (bearCross && !isUpTrend && Position >= 0)
{
if (Position > 0)
SellMarket(Math.Abs(Position));
SellMarket(Volume);
_cooldownRemaining = CooldownBars;
}
// Exit long: Supertrend flips to downtrend
else if (Position > 0 && !isUpTrend && bearCross)
{
SellMarket(Math.Abs(Position));
_cooldownRemaining = CooldownBars;
}
// Exit short: Supertrend flips to uptrend
else if (Position < 0 && isUpTrend && bullCross)
{
BuyMarket(Math.Abs(Position));
_cooldownRemaining = CooldownBars;
}
_prevFast = fast;
_prevSlow = slow;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage, SuperTrend, IndicatorHelper
from StockSharp.Algo.Strategies import Strategy
class three_kilos_btc_15m_strategy(Strategy):
"""Triple EMA crossover with Supertrend filter strategy."""
def __init__(self):
super(three_kilos_btc_15m_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("Candle Type", "Candle type for strategy calculation", "General")
self._fast_length = self.Param("FastLength", 8) \
.SetDisplay("Fast EMA", "Fast EMA length", "Indicators")
self._slow_length = self.Param("SlowLength", 21) \
.SetDisplay("Slow EMA", "Slow EMA length", "Indicators")
self._cooldown_bars = self.Param("CooldownBars", 12) \
.SetDisplay("Cooldown Bars", "Bars between trades", "Risk")
self._fast_ema = None
self._slow_ema = None
self._super_trend = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._cooldown_remaining = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(three_kilos_btc_15m_strategy, self).OnReseted()
self._fast_ema = None
self._slow_ema = None
self._super_trend = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._cooldown_remaining = 0
def OnStarted2(self, time):
super(three_kilos_btc_15m_strategy, self).OnStarted2(time)
self._fast_ema = ExponentialMovingAverage()
self._fast_ema.Length = int(self._fast_length.Value)
self._slow_ema = ExponentialMovingAverage()
self._slow_ema.Length = int(self._slow_length.Value)
self._super_trend = SuperTrend()
self._super_trend.Length = 10
self._super_trend.Multiplier = 2.0
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(self._fast_ema, self._slow_ema, self._super_trend, self._on_process).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 _on_process(self, candle, fast_val, slow_val, st_val):
if candle.State != CandleStates.Finished:
return
if not self._fast_ema.IsFormed or not self._slow_ema.IsFormed or not self._super_trend.IsFormed:
return
if fast_val.IsEmpty or slow_val.IsEmpty or st_val.IsEmpty:
return
fast = float(IndicatorHelper.ToDecimal(fast_val))
slow = float(IndicatorHelper.ToDecimal(slow_val))
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_fast = fast
self._prev_slow = slow
return
is_up_trend = st_val.IsUpTrend
cooldown = int(self._cooldown_bars.Value)
if self._cooldown_remaining > 0:
self._cooldown_remaining -= 1
self._prev_fast = fast
self._prev_slow = slow
return
bull_cross = self._prev_fast > 0 and self._prev_fast <= self._prev_slow and fast > slow
bear_cross = self._prev_fast > 0 and self._prev_fast >= self._prev_slow and fast < slow
if bull_cross and is_up_trend and self.Position <= 0:
if self.Position < 0:
self.BuyMarket(Math.Abs(self.Position))
self.BuyMarket(self.Volume)
self._cooldown_remaining = cooldown
elif bear_cross and not is_up_trend and self.Position >= 0:
if self.Position > 0:
self.SellMarket(Math.Abs(self.Position))
self.SellMarket(self.Volume)
self._cooldown_remaining = cooldown
elif self.Position > 0 and not is_up_trend and bear_cross:
self.SellMarket(Math.Abs(self.Position))
self._cooldown_remaining = cooldown
elif self.Position < 0 and is_up_trend and bull_cross:
self.BuyMarket(Math.Abs(self.Position))
self._cooldown_remaining = cooldown
self._prev_fast = fast
self._prev_slow = slow
def CreateClone(self):
return three_kilos_btc_15m_strategy()