Estrategia TSI Largo/Corto para BTC 2H
Utiliza rupturas del Índice de Fuerza Verdadera en un gráfico de dos horas. Las operaciones largas comienzan cuando el TSI cruza por encima de su máximo de 100 barras, mientras que las operaciones cortas comienzan cuando cae por debajo de su mínimo de 100 barras.
- Indicadores: True Strength Index, Highest, Lowest
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>
/// True Strength Index-inspired breakout strategy.
/// Uses RSI as momentum oscillator with EMA trend filter.
/// </summary>
public class TsiLongShortForBtc2HStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<int> _lookback;
private decimal _prevRsi;
private decimal _prevEmaFast;
private decimal _prevEmaSlow;
private int _cooldown;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
public int Lookback { get => _lookback.Value; set => _lookback.Value = value; }
public TsiLongShortForBtc2HStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
_rsiLength = Param(nameof(RsiLength), 14)
.SetDisplay("RSI Length", "RSI period", "Indicators");
_lookback = Param(nameof(Lookback), 21)
.SetDisplay("Lookback", "EMA slow period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
protected override void OnReseted()
{
base.OnReseted();
_prevRsi = 0;
_prevEmaFast = 0;
_prevEmaSlow = 0;
_cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var emaFast = new ExponentialMovingAverage { Length = 10 };
var emaSlow = new ExponentialMovingAverage { Length = Lookback };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, emaFast, emaSlow, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, emaFast);
DrawIndicator(area, emaSlow);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsiVal, decimal emaFast, decimal emaSlow)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevRsi == 0 || _prevEmaFast == 0 || _prevEmaSlow == 0)
{
_prevRsi = rsiVal;
_prevEmaFast = emaFast;
_prevEmaSlow = emaSlow;
return;
}
if (_cooldown > 0)
{
_cooldown--;
_prevRsi = rsiVal;
_prevEmaFast = emaFast;
_prevEmaSlow = emaSlow;
return;
}
// RSI cross 50
var rsiCrossUp = _prevRsi <= 50m && rsiVal > 50m;
var rsiCrossDown = _prevRsi >= 50m && rsiVal < 50m;
// EMA trend
var trendUp = emaFast > emaSlow;
var trendDown = emaFast < emaSlow;
// Exit
if (Position > 0 && rsiCrossDown)
{
SellMarket();
_cooldown = 80;
}
else if (Position < 0 && rsiCrossUp)
{
BuyMarket();
_cooldown = 80;
}
// Entry
if (Position == 0)
{
if (rsiCrossUp && trendUp)
{
BuyMarket();
_cooldown = 80;
}
else if (rsiCrossDown && trendDown)
{
SellMarket();
_cooldown = 80;
}
}
_prevRsi = rsiVal;
_prevEmaFast = emaFast;
_prevEmaSlow = emaSlow;
}
}
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 ExponentialMovingAverage, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class tsi_long_short_for_btc2_h_strategy(Strategy):
def __init__(self):
super(tsi_long_short_for_btc2_h_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "RSI period", "Indicators")
self._lookback = self.Param("Lookback", 21) \
.SetDisplay("Lookback", "EMA slow period", "Indicators")
self._prev_rsi = 0.0
self._prev_fast = 0.0
self._prev_slow = 0.0
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
@property
def rsi_length(self):
return self._rsi_length.Value
@property
def lookback(self):
return self._lookback.Value
def OnReseted(self):
super(tsi_long_short_for_btc2_h_strategy, self).OnReseted()
self._prev_rsi = 0.0
self._prev_fast = 0.0
self._prev_slow = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(tsi_long_short_for_btc2_h_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.rsi_length
ema_fast = ExponentialMovingAverage()
ema_fast.Length = 10
ema_slow = ExponentialMovingAverage()
ema_slow.Length = int(self.lookback)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(rsi, ema_fast, ema_slow, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema_fast)
self.DrawIndicator(area, ema_slow)
self.DrawOwnTrades(area)
def on_process(self, candle, rsi_val, ema_fast, ema_slow):
if candle.State != CandleStates.Finished:
return
rsi_val = float(rsi_val)
ema_fast = float(ema_fast)
ema_slow = float(ema_slow)
if self._prev_rsi == 0 or self._prev_fast == 0 or self._prev_slow == 0:
self._prev_rsi = rsi_val
self._prev_fast = ema_fast
self._prev_slow = ema_slow
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_rsi = rsi_val
self._prev_fast = ema_fast
self._prev_slow = ema_slow
return
hist = ema_fast - ema_slow
hist_up = hist > 0
hist_down = hist < 0
rsi_cross_up = self._prev_rsi <= 50 and rsi_val > 50
rsi_cross_down = self._prev_rsi >= 50 and rsi_val < 50
if self.Position > 0 and rsi_cross_down:
self.SellMarket()
self._cooldown = 80
elif self.Position < 0 and rsi_cross_up:
self.BuyMarket()
self._cooldown = 80
if self.Position == 0:
if rsi_cross_up and hist_up:
self.BuyMarket()
self._cooldown = 80
elif rsi_cross_down and hist_down:
self.SellMarket()
self._cooldown = 80
self._prev_rsi = rsi_val
self._prev_fast = ema_fast
self._prev_slow = ema_slow
def CreateClone(self):
return tsi_long_short_for_btc2_h_strategy()