Estratégia Adaptativa XRP AI de 15 m v3.1
Esta estratégia opera XRP em velas de 15 minutos usando um filtro de tendência de período temporal superior. Seleciona entre pequenos recuos, descargas de volume médias ou grandes explosões de momentum, e aplica stops, alvos baseados em ATR, stop trailing e uma saída baseada em tempo.
Parâmetros
- Risk Mult – multiplicador ATR para o stop inicial.
- Small TP – multiplicador ATR para take profit em um pequeno recuo.
- Med TP – multiplicador ATR para take profit em uma descarga de volume média.
- Large TP – multiplicador ATR para take profit em uma grande explosão de momentum.
- Volume Mult – multiplicador de volume SMA-20 para detectar picos.
- Trail Percent – percentagem ATR do stop trailing a partir do preço mais alto.
- Trail Arm – ganho aberto em múltiplos ATR antes de ativar o trailing.
- Max Bars – número máximo de velas de 15 minutos para manter uma posição.
- Candle Type – tipo de vela usado para os cálculos principais.
- Trend Candle Type – tipo de vela usado para o filtro de tendência.
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>
/// XRP AI 15-m Adaptive v3.1 strategy.
/// Long-only entries with RSI/EMA filter and StdDev-based management.
/// Uses higher timeframe EMA trend filter.
/// </summary>
public class XrpAi15mAdaptiveV31Strategy : Strategy
{
private readonly StrategyParam<decimal> _stopPct;
private readonly StrategyParam<decimal> _tpSmall;
private readonly StrategyParam<decimal> _tpLarge;
private readonly StrategyParam<decimal> _trailPct;
private readonly StrategyParam<int> _maxBars;
private readonly StrategyParam<DataType> _candleType;
private bool _trendUp;
private int _barIndex;
private int _entryBar;
private decimal _entryPrice;
private decimal _highWater;
private bool _trailLive;
private decimal _stopPrice;
private decimal _takePrice;
public decimal StopPct { get => _stopPct.Value; set => _stopPct.Value = value; }
public decimal TpSmall { get => _tpSmall.Value; set => _tpSmall.Value = value; }
public decimal TpLarge { get => _tpLarge.Value; set => _tpLarge.Value = value; }
public decimal TrailPct { get => _trailPct.Value; set => _trailPct.Value = value; }
public int MaxBars { get => _maxBars.Value; set => _maxBars.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public XrpAi15mAdaptiveV31Strategy()
{
_stopPct = Param(nameof(StopPct), 1.5m)
.SetGreaterThanZero()
.SetDisplay("Stop %", "Stop loss percent", "Risk");
_tpSmall = Param(nameof(TpSmall), 2m)
.SetGreaterThanZero()
.SetDisplay("Small TP %", "Take profit for small setups", "Risk");
_tpLarge = Param(nameof(TpLarge), 4m)
.SetGreaterThanZero()
.SetDisplay("Large TP %", "Take profit for large setups", "Risk");
_trailPct = Param(nameof(TrailPct), 1m)
.SetGreaterThanZero()
.SetDisplay("Trail %", "Trailing stop percent", "Risk");
_maxBars = Param(nameof(MaxBars), 48)
.SetGreaterThanZero()
.SetDisplay("Max Bars", "Maximum bars to hold", "Parameters");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Main candle type", "Parameters");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
protected override void OnReseted()
{
base.OnReseted();
_trendUp = false;
_barIndex = 0;
_entryBar = -1;
_entryPrice = 0;
_highWater = 0;
_trailLive = false;
_stopPrice = 0;
_takePrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema13 = new ExponentialMovingAverage { Length = 13 };
var ema34 = new ExponentialMovingAverage { Length = 34 };
var rsi = new RelativeStrengthIndex { Length = 14 };
_trendUp = false;
_barIndex = 0;
_entryBar = -1;
_entryPrice = 0;
_highWater = 0;
_trailLive = false;
_stopPrice = 0;
_takePrice = 0;
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema13, ema34, rsi, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema13);
DrawIndicator(area, ema34);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal ema13, decimal ema34, decimal rsi)
{
if (candle.State != CandleStates.Finished)
return;
_barIndex++;
// Use EMA cross for trend
_trendUp = ema13 > ema34;
// Exit management
if (Position > 0 && _entryPrice > 0)
{
if (candle.HighPrice > _highWater)
_highWater = candle.HighPrice;
// Stop loss
if (candle.ClosePrice <= _stopPrice)
{
SellMarket();
ResetTrade();
return;
}
// Take profit
if (candle.ClosePrice >= _takePrice)
{
SellMarket();
ResetTrade();
return;
}
// Trailing stop
if (!_trailLive && _highWater >= _entryPrice * (1 + TrailPct / 100m))
_trailLive = true;
if (_trailLive)
{
var trailStop = _highWater * (1 - TrailPct / 200m);
if (candle.ClosePrice <= trailStop)
{
SellMarket();
ResetTrade();
return;
}
}
// Time-based exit
if (_barIndex - _entryBar >= MaxBars)
{
SellMarket();
ResetTrade();
return;
}
}
// Entry conditions - long only
if (Position == 0)
{
// Large setup: extreme oversold + trend up
var largeOk = rsi < 25m && candle.ClosePrice > ema34 && _trendUp;
// Small setup: pullback to EMA in uptrend
var smallOk = candle.ClosePrice <= ema13 * 0.998m &&
rsi < 45m &&
candle.ClosePrice > candle.OpenPrice &&
_trendUp;
if (largeOk)
{
BuyMarket();
_entryPrice = candle.ClosePrice;
_entryBar = _barIndex;
_highWater = candle.ClosePrice;
_trailLive = false;
_stopPrice = _entryPrice * (1 - StopPct / 100m);
_takePrice = _entryPrice * (1 + TpLarge / 100m);
}
else if (smallOk)
{
BuyMarket();
_entryPrice = candle.ClosePrice;
_entryBar = _barIndex;
_highWater = candle.ClosePrice;
_trailLive = false;
_stopPrice = _entryPrice * (1 - StopPct / 100m);
_takePrice = _entryPrice * (1 + TpSmall / 100m);
}
}
}
private void ResetTrade()
{
_entryBar = -1;
_entryPrice = 0;
_highWater = 0;
_trailLive = false;
_stopPrice = 0;
_takePrice = 0;
}
}
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 xrp_ai15m_adaptive_v31_strategy(Strategy):
def __init__(self):
super(xrp_ai15m_adaptive_v31_strategy, self).__init__()
self._stop_pct = self.Param("StopPct", 1.5) \
.SetDisplay("Stop %", "Stop loss percent", "Risk")
self._tp_small = self.Param("TpSmall", 2) \
.SetDisplay("Small TP %", "Take profit for small setups", "Risk")
self._tp_large = self.Param("TpLarge", 4) \
.SetDisplay("Large TP %", "Take profit for large setups", "Risk")
self._trail_pct = self.Param("TrailPct", 1) \
.SetDisplay("Trail %", "Trailing stop percent", "Risk")
self._max_bars = self.Param("MaxBars", 48) \
.SetDisplay("Max Bars", "Maximum bars to hold", "Parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Main candle type", "Parameters")
self._trend_up = False
self._bar_index = 0
self._entry_bar = 0
self._entry_price = 0.0
self._high_water = 0.0
self._trail_live = False
self._stop_price = 0.0
self._take_price = 0.0
@property
def stop_pct(self):
return self._stop_pct.Value
@property
def tp_small(self):
return self._tp_small.Value
@property
def tp_large(self):
return self._tp_large.Value
@property
def trail_pct(self):
return self._trail_pct.Value
@property
def max_bars(self):
return self._max_bars.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(xrp_ai15m_adaptive_v31_strategy, self).OnReseted()
self._trend_up = False
self._bar_index = 0
self._entry_bar = 0
self._entry_price = 0.0
self._high_water = 0.0
self._trail_live = False
self._stop_price = 0.0
self._take_price = 0.0
def OnStarted2(self, time):
super(xrp_ai15m_adaptive_v31_strategy, self).OnStarted2(time)
ema13 = ExponentialMovingAverage()
ema13.Length = 13
ema34 = ExponentialMovingAverage()
ema34.Length = 34
rsi = RelativeStrengthIndex()
rsi.Length = 14
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema13, ema34, rsi, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema13)
self.DrawIndicator(area, ema34)
self.DrawOwnTrades(area)
def on_process(self, candle, ema13, ema34, rsi):
if candle.State != CandleStates.Finished:
return
self._bar_index += 1
# Use EMA cross for trend
self._trend_up = ema13 > ema34
# Exit management
if self.Position > 0 and self._entry_price > 0:
if candle.HighPrice > self._high_water:
self._high_water = candle.HighPrice
# Stop loss
if candle.ClosePrice <= self._stop_price:
self.SellMarket()
# ResetTrade()
return
# Take profit
if candle.ClosePrice >= self._take_price:
self.SellMarket()
# ResetTrade()
return
# Trailing stop
if not self._trail_live and self._high_water >= self._entry_price * (1 + self.trail_pct / 100):
self._trail_live = True
if self._trail_live:
trail_stop = self._high_water * (1 - self.trail_pct / 200)
if candle.ClosePrice <= trail_stop:
self.SellMarket()
# ResetTrade()
return
# Time-based exit
if self._bar_index - self._entry_bar >= self.max_bars:
self.SellMarket()
# ResetTrade()
return
# Entry conditions - long only
if self.Position == 0:
# Large setup: extreme oversold + trend up
large_ok = rsi < 25 and candle.ClosePrice > ema34 and self._trend_up
# Small setup: pullback to EMA in uptrend
small_ok = (candle.ClosePrice <= ema13 * 0.998 and
rsi < 45 and
candle.ClosePrice > candle.OpenPrice and
self._trend_up)
if large_ok:
self.BuyMarket()
self._entry_price = candle.ClosePrice
self._entry_bar = self._bar_index
self._high_water = candle.ClosePrice
self._trail_live = False
self._stop_price = self._entry_price * (1 - self.stop_pct / 100)
self._take_price = self._entry_price * (1 + self.tp_large / 100)
elif small_ok:
self.BuyMarket()
self._entry_price = candle.ClosePrice
self._entry_bar = self._bar_index
self._high_water = candle.ClosePrice
self._trail_live = False
self._stop_price = self._entry_price * (1 - self.stop_pct / 100)
self._take_price = self._entry_price * (1 + self.tp_small / 100)
def reset_trade(self):
self._entry_bar = -1
self._entry_price = 0
self._high_water = 0
self._trail_live = False
self._stop_price = 0
self._take_price = 0
def CreateClone(self):
return xrp_ai15m_adaptive_v31_strategy()