Williams Alligator ATR
Reglas de negociación
Las tres líneas Alligator suavizan el precio mediano (máximo+mínimo)/2; Length y Shift controlan suavizado y retraso en velas completas. Teeth se calcula y debe estar formado, sin filtro adicional. Con líneas y ATR de Wilder formados, Lips−Jaw de <=0 a >0 abre Volume largo desde cero; de >=0 a <0 cierra todo el largo real. Nunca abre corto. Fijar ATR×AtrMultiplier como distancia de stop local nativo desde ejecución real; bid/ask puede activarlo entre velas. Sin espera, toma de beneficios ni stop ATR móvil.
Parámetros
| Parámetro | Predeterminado |
|---|---|
CandleType |
TimeSpan.FromMinutes(30).TimeFrame() |
JawLength |
13 |
TeethLength |
8 |
LipsLength |
5 |
JawShift |
8 |
TeethShift |
5 |
LipsShift |
3 |
AtrPeriod |
14 |
AtrMultiplier |
2 |
Verificación
Ambos lenguajes se verifican con BTC/TON incluido, fórmulas independientes, dirección/tamaño de órdenes, ejecuciones, posiciones y salidas. Datos fechados de precios/factores y calendarios verifican mecánica; OHLC/volúmenes trasladados no son historia plurianual. Dos grupos, TopN=1 y SMA=2 son perfiles explícitos pequeños. Ventanas largas y valores originales se comprueban aparte. Sin promesas de rentabilidad.
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>Long-only shifted median-price Alligator crosses with an entry-frozen native ATR stop.</summary>
public class WilliamsAlligatorAtrStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _jawLength;
private readonly StrategyParam<int> _teethLength;
private readonly StrategyParam<int> _lipsLength;
private readonly StrategyParam<int> _jawShift;
private readonly StrategyParam<int> _teethShift;
private readonly StrategyParam<int> _lipsShift;
private readonly StrategyParam<int> _atrPeriod;
private readonly StrategyParam<decimal> _atrMultiplier;
private Order _pending;
private AlligatorLine _jaw;
private AlligatorLine _teeth;
private AlligatorLine _lips;
private AverageTrueRange _atr;
private decimal? _previousSpread;
/// <summary>Finished signal candle type.</summary>
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
/// <summary>Jaw smoothed median-price window.</summary>
public int JawLength { get => _jawLength.Value; set => _jawLength.Value = value; }
/// <summary>Teeth smoothed median-price window.</summary>
public int TeethLength { get => _teethLength.Value; set => _teethLength.Value = value; }
/// <summary>Lips smoothed median-price window.</summary>
public int LipsLength { get => _lipsLength.Value; set => _lipsLength.Value = value; }
/// <summary>Completed bars delaying the Jaw line.</summary>
public int JawShift { get => _jawShift.Value; set => _jawShift.Value = value; }
/// <summary>Completed bars delaying the Teeth line.</summary>
public int TeethShift { get => _teethShift.Value; set => _teethShift.Value = value; }
/// <summary>Completed bars delaying the Lips line.</summary>
public int LipsShift { get => _lipsShift.Value; set => _lipsShift.Value = value; }
/// <summary>Wilder true-range window.</summary>
public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
/// <summary>Entry-frozen ATR stop multiplier.</summary>
public decimal AtrMultiplier { get => _atrMultiplier.Value; set => _atrMultiplier.Value = value; }
/// <summary>Initialize the strategy parameters.</summary>
public WilliamsAlligatorAtrStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("CandleType", "Finished signal candle type.", "Parameters");
_jawLength = Param(nameof(JawLength), 13).SetRange(1, int.MaxValue)
.SetDisplay("JawLength", "Jaw smoothed median-price window.", "Parameters");
_teethLength = Param(nameof(TeethLength), 8).SetRange(1, int.MaxValue)
.SetDisplay("TeethLength", "Teeth smoothed median-price window.", "Parameters");
_lipsLength = Param(nameof(LipsLength), 5).SetRange(1, int.MaxValue)
.SetDisplay("LipsLength", "Lips smoothed median-price window.", "Parameters");
_jawShift = Param(nameof(JawShift), 8).SetRange(1, int.MaxValue)
.SetDisplay("JawShift", "Completed bars delaying the Jaw line.", "Parameters");
_teethShift = Param(nameof(TeethShift), 5).SetRange(1, int.MaxValue)
.SetDisplay("TeethShift", "Completed bars delaying the Teeth line.", "Parameters");
_lipsShift = Param(nameof(LipsShift), 3).SetRange(1, int.MaxValue)
.SetDisplay("LipsShift", "Completed bars delaying the Lips line.", "Parameters");
_atrPeriod = Param(nameof(AtrPeriod), 14).SetRange(1, int.MaxValue)
.SetDisplay("AtrPeriod", "Wilder true-range window.", "Parameters");
_atrMultiplier = Param(nameof(AtrMultiplier), 2m).SetRange(0.000001m, decimal.MaxValue)
.SetDisplay("AtrMultiplier", "Entry-frozen ATR stop multiplier.", "Parameters");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_pending = null;
_jaw = null;
_teeth = null;
_lips = null;
_atr = null;
_previousSpread = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
foreach (var field in new[] { Level1Fields.BestBidPrice, Level1Fields.BestAskPrice })
{
var quote = new Subscription(DataType.Level1, Security);
quote.MarketData.BuildField = field;
SubscribeLevel1(quote).Start();
}
_jaw = new AlligatorLine { Length = JawLength, Shift = JawShift };
_teeth = new AlligatorLine { Length = TeethLength, Shift = TeethShift };
_lips = new AlligatorLine { Length = LipsLength, Shift = LipsShift };
_atr = new AverageTrueRange { Length = AtrPeriod };
SubscribeCandles(CandleType).Bind(ProcessCandle).Start();
}
private bool IsPending => _pending is not null && _pending.State is not (OrderStates.Done or OrderStates.Failed);
private void Submit(Sides side, decimal quantity, string comment)
{
_pending = CreateOrder(side, 0m, quantity);
_pending.Type = OrderTypes.Market;
_pending.Comment = comment;
RegisterOrder(_pending);
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished) return;
var jaw = _jaw.Process(candle);
var teeth = _teeth.Process(candle);
var lips = _lips.Process(candle);
var atr = _atr.Process(candle);
if (!_jaw.IsFormed || !_teeth.IsFormed || !_lips.IsFormed || !_atr.IsFormed
|| jaw.IsEmpty || teeth.IsEmpty || lips.IsEmpty || atr.IsEmpty) return;
var spread = lips.ToDecimal() - jaw.ToDecimal();
var previous = _previousSpread;
_previousSpread = spread;
if (previous is null || IsPending || !IsFormedAndOnlineAndAllowTrading()) return;
if (previous >= 0m && spread < 0m && Position > 0m)
Submit(Sides.Sell, Position, "0512CrossExit");
else if (previous <= 0m && spread > 0m && Position == 0m && atr.ToDecimal() > 0m)
{
StartProtection(new Unit(), new Unit(atr.ToDecimal() * AtrMultiplier, UnitTypes.Absolute), useMarketOrders: true, isLocalStop: true);
Submit(Sides.Buy, Volume, "0512Entry");
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.BusinessEntities")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import DateTime, Decimal, Math, TimeSpan, InvalidOperationException
from System.Globalization import CultureInfo, DateTimeStyles
from System.IO import File
from StockSharp.Algo.Indicators import ExponentialMovingAverage, SimpleMovingAverage, AverageTrueRange, AlligatorLine, CandleIndicatorValue
from StockSharp.Algo.Strategies import Strategy
from StockSharp.BusinessEntities import Subscription
from StockSharp.Messages import Level1Fields, ITickTradeMessage, CandleStates, DataType, OrderStates, OrderTypes, Sides, Unit, UnitTypes
class williams_alligator_atr_strategy(Strategy):
"""Long-only shifted median-price Alligator crosses with an entry-frozen native ATR stop."""
def __init__(self):
super(williams_alligator_atr_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("CandleType", "Finished signal candle type.", "Parameters")
self._jaw_length = self.Param("JawLength", 13).SetRange(1, 2147483647) \
.SetDisplay("JawLength", "Jaw smoothed median-price window.", "Parameters")
self._teeth_length = self.Param("TeethLength", 8).SetRange(1, 2147483647) \
.SetDisplay("TeethLength", "Teeth smoothed median-price window.", "Parameters")
self._lips_length = self.Param("LipsLength", 5).SetRange(1, 2147483647) \
.SetDisplay("LipsLength", "Lips smoothed median-price window.", "Parameters")
self._jaw_shift = self.Param("JawShift", 8).SetRange(1, 2147483647) \
.SetDisplay("JawShift", "Completed bars delaying the Jaw line.", "Parameters")
self._teeth_shift = self.Param("TeethShift", 5).SetRange(1, 2147483647) \
.SetDisplay("TeethShift", "Completed bars delaying the Teeth line.", "Parameters")
self._lips_shift = self.Param("LipsShift", 3).SetRange(1, 2147483647) \
.SetDisplay("LipsShift", "Completed bars delaying the Lips line.", "Parameters")
self._atr_period = self.Param("AtrPeriod", 14).SetRange(1, 2147483647) \
.SetDisplay("AtrPeriod", "Wilder true-range window.", "Parameters")
self._atr_multiplier = self.Param("AtrMultiplier", Decimal(2)).SetRange(Decimal(0.000001), Decimal.MaxValue) \
.SetDisplay("AtrMultiplier", "Entry-frozen ATR stop multiplier.", "Parameters")
self._clear_state()
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def JawLength(self):
return self._jaw_length.Value
@JawLength.setter
def JawLength(self, value):
self._jaw_length.Value = value
@property
def TeethLength(self):
return self._teeth_length.Value
@TeethLength.setter
def TeethLength(self, value):
self._teeth_length.Value = value
@property
def LipsLength(self):
return self._lips_length.Value
@LipsLength.setter
def LipsLength(self, value):
self._lips_length.Value = value
@property
def JawShift(self):
return self._jaw_shift.Value
@JawShift.setter
def JawShift(self, value):
self._jaw_shift.Value = value
@property
def TeethShift(self):
return self._teeth_shift.Value
@TeethShift.setter
def TeethShift(self, value):
self._teeth_shift.Value = value
@property
def LipsShift(self):
return self._lips_shift.Value
@LipsShift.setter
def LipsShift(self, value):
self._lips_shift.Value = value
@property
def AtrPeriod(self):
return self._atr_period.Value
@AtrPeriod.setter
def AtrPeriod(self, value):
self._atr_period.Value = value
@property
def AtrMultiplier(self):
return self._atr_multiplier.Value
@AtrMultiplier.setter
def AtrMultiplier(self, value):
self._atr_multiplier.Value = value
def _clear_state(self):
self._pending = None
self._jaw = None
self._teeth = None
self._lips = None
self._atr = None
self._previous_spread = None
def OnReseted(self):
super(williams_alligator_atr_strategy, self).OnReseted()
self._clear_state()
def GetWorkingSecurities(self):
return [(self.Security, self.CandleType)]
def OnStarted2(self, time):
super(williams_alligator_atr_strategy, self).OnStarted2(time)
for field in (Level1Fields.BestBidPrice, Level1Fields.BestAskPrice):
quote = Subscription(DataType.Level1, self.Security)
quote.MarketData.BuildField = field
self.SubscribeLevel1(quote).Start()
self._jaw = AlligatorLine()
self._jaw.Length = self.JawLength
self._jaw.Shift = self.JawShift
self._teeth = AlligatorLine()
self._teeth.Length = self.TeethLength
self._teeth.Shift = self.TeethShift
self._lips = AlligatorLine()
self._lips.Length = self.LipsLength
self._lips.Shift = self.LipsShift
self._atr = AverageTrueRange()
self._atr.Length = self.AtrPeriod
self.SubscribeCandles(self.CandleType).Bind(self._process_candle).Start()
def _is_pending(self):
return self._pending is not None and self._pending.State not in (OrderStates.Done, OrderStates.Failed)
def _submit(self, side, quantity, comment):
self._pending = self.CreateOrder(side, Decimal(0), quantity)
self._pending.Type = OrderTypes.Market
self._pending.Comment = comment
self.RegisterOrder(self._pending)
@staticmethod
def _process(indicator, candle):
value = CandleIndicatorValue(indicator, candle)
value.IsFinal = True
result = indicator.Process(value)
return None if result.IsEmpty else result.GetValue[Decimal](None)
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
jaw = self._process(self._jaw, candle)
teeth = self._process(self._teeth, candle)
lips = self._process(self._lips, candle)
atr = self._process(self._atr, candle)
if not self._jaw.IsFormed or not self._teeth.IsFormed or not self._lips.IsFormed or not self._atr.IsFormed or jaw is None or teeth is None or lips is None or atr is None:
return
spread = lips - jaw
previous = self._previous_spread
self._previous_spread = spread
if previous is None or self._is_pending() or not self.IsFormedAndOnlineAndAllowTrading():
return
if previous >= 0 and spread < 0 and self.Position > 0:
self._submit(Sides.Sell, self.Position, "0512CrossExit")
elif previous <= 0 and spread > 0 and self.Position == 0 and atr > 0:
self.StartProtection(Unit(), Unit(atr * self.AtrMultiplier, UnitTypes.Absolute), useMarketOrders=True, isLocalStop=True)
self._submit(Sides.Buy, self.Volume, "0512Entry")
def CreateClone(self):
return williams_alligator_atr_strategy()