FrakTrak XonaX es una estrategia de ruptura basada en niveles de fractales calculados en un marco temporal superior. Cuando el precio se mueve más allá del fractal más reciente por un pequeño offset, la estrategia entra en la dirección de la ruptura. Un take profit fijo y un trailing stop gestionan la posición abierta.
Parámetros
Volume – tamaño de la orden.
Take Profit – distancia en puntos para el nivel de take-profit.
Trailing Stop – distancia en puntos utilizada para el trailing del stop-loss.
Trailing Correction – distancia adicional añadida al trailing stop.
Candle Type – marco temporal utilizado para construir velas y fractales.
Reglas de trading
Calcular fractales superiores e inferiores usando los últimos candles completados.
Comprar cuando el precio de cierre supera el fractal superior más 15 puntos y no existe posición larga. El stop-loss se coloca en el último fractal inferior y el take-profit se configura usando Take Profit.
Vender cuando el precio de cierre cae por debajo del fractal inferior menos 15 puntos y no existe posición corta. El stop-loss se coloca en el último fractal superior y el take-profit se configura usando Take Profit.
Cuando una posición se vuelve rentable en más de Trailing Stop puntos, el stop-loss sigue al precio con un offset adicional de Trailing Correction.
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>
/// FrakTrak XonaX strategy.
/// Uses fractal breakouts to generate entry signals.
/// </summary>
public class FraktrakXonaxStrategy : Strategy
{
private readonly StrategyParam<decimal> _fractalOffset;
private readonly StrategyParam<DataType> _candleType;
private decimal _h1, _h2, _h3, _h4, _h5;
private decimal _l1, _l2, _l3, _l4, _l5;
private decimal? _upFractal;
private decimal? _downFractal;
private decimal? _lastUpFractal;
private decimal? _lastDownFractal;
/// <summary>
/// Price offset added beyond fractal for entry trigger.
/// </summary>
public decimal FractalOffset
{
get => _fractalOffset.Value;
set => _fractalOffset.Value = value;
}
/// <summary>
/// Candle type used by the strategy.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public FraktrakXonaxStrategy()
{
_fractalOffset = Param(nameof(FractalOffset), 50m)
.SetDisplay("Fractal Offset", "Price offset beyond fractal for entry", "Signals");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Source candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_h1 = _h2 = _h3 = _h4 = _h5 = 0m;
_l1 = _l2 = _l3 = _l4 = _l5 = 0m;
_upFractal = _downFractal = _lastUpFractal = _lastDownFractal = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
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;
// Shift high and low buffers
_h1 = _h2; _h2 = _h3; _h3 = _h4; _h4 = _h5; _h5 = candle.HighPrice;
_l1 = _l2; _l2 = _l3; _l3 = _l4; _l4 = _l5; _l5 = candle.LowPrice;
// Need at least 5 bars for fractal detection
if (_h1 == 0 || _l1 == 0)
return;
// Detect new fractals (bar 3 is the middle of 5 bars)
if (_h3 > _h1 && _h3 > _h2 && _h3 > _h4 && _h3 > _h5)
_upFractal = _h3;
if (_l3 < _l1 && _l3 < _l2 && _l3 < _l4 && _l3 < _l5)
_downFractal = _l3;
// Buy signal: close above up fractal + offset
if (_upFractal is decimal up && _lastUpFractal != up)
{
var trigger = up + FractalOffset;
if (candle.ClosePrice > trigger && Position <= 0)
{
BuyMarket();
_lastUpFractal = up;
}
}
// Sell signal: close below down fractal - offset
if (_downFractal is decimal low && _lastDownFractal != low)
{
var trigger = low - FractalOffset;
if (candle.ClosePrice < trigger && Position >= 0)
{
SellMarket();
_lastDownFractal = low;
}
}
}
}
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.Strategies import Strategy
class fraktrak_xonax_strategy(Strategy):
def __init__(self):
super(fraktrak_xonax_strategy, self).__init__()
self._fractal_offset = self.Param("FractalOffset", 50.0) \
.SetDisplay("Fractal Offset", "Price offset beyond fractal for entry", "Signals")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Source candles", "General")
self._h1 = 0.0
self._h2 = 0.0
self._h3 = 0.0
self._h4 = 0.0
self._h5 = 0.0
self._l1 = 0.0
self._l2 = 0.0
self._l3 = 0.0
self._l4 = 0.0
self._l5 = 0.0
self._up_fractal = None
self._down_fractal = None
self._last_up_fractal = None
self._last_down_fractal = None
@property
def fractal_offset(self):
return self._fractal_offset.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(fraktrak_xonax_strategy, self).OnReseted()
self._h1 = self._h2 = self._h3 = self._h4 = self._h5 = 0.0
self._l1 = self._l2 = self._l3 = self._l4 = self._l5 = 0.0
self._up_fractal = None
self._down_fractal = None
self._last_up_fractal = None
self._last_down_fractal = None
def OnStarted2(self, time):
super(fraktrak_xonax_strategy, self).OnStarted2(time)
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
# Shift high and low buffers
self._h1 = self._h2
self._h2 = self._h3
self._h3 = self._h4
self._h4 = self._h5
self._h5 = float(candle.HighPrice)
self._l1 = self._l2
self._l2 = self._l3
self._l3 = self._l4
self._l4 = self._l5
self._l5 = float(candle.LowPrice)
# Need at least 5 bars for fractal detection
if self._h1 == 0 or self._l1 == 0:
return
# Detect new fractals (bar 3 is the middle of 5 bars)
if self._h3 > self._h1 and self._h3 > self._h2 and self._h3 > self._h4 and self._h3 > self._h5:
self._up_fractal = self._h3
if self._l3 < self._l1 and self._l3 < self._l2 and self._l3 < self._l4 and self._l3 < self._l5:
self._down_fractal = self._l3
close = float(candle.ClosePrice)
offset = float(self.fractal_offset)
# Buy signal: close above up fractal + offset
if self._up_fractal is not None and self._last_up_fractal != self._up_fractal:
trigger = self._up_fractal + offset
if close > trigger and self.Position <= 0:
self.BuyMarket()
self._last_up_fractal = self._up_fractal
# Sell signal: close below down fractal - offset
if self._down_fractal is not None and self._last_down_fractal != self._down_fractal:
trigger = self._down_fractal - offset
if close < trigger and self.Position >= 0:
self.SellMarket()
self._last_down_fractal = self._down_fractal
def CreateClone(self):
return fraktrak_xonax_strategy()