Williams Alligator ATR
Regras de negociação
As três linhas Alligator suavizam preço mediano (máxima+mínima)/2; Length e Shift controlam suavização e atraso em velas completas. Teeth é calculado e precisa estar formado, sem filtro adicional. Com linhas e ATR de Wilder formados, Lips−Jaw de <=0 para >0 abre Volume comprado sem posição; de >=0 para <0 encerra toda compra real. Nunca abre venda a descoberto. Fixar ATR×AtrMultiplier como distância do stop local nativo desde execução real; bid/ask pode ativá-lo entre velas. Sem espera, alvo de lucro ou stop ATR móvel.
Parâmetros
| Parâmetro | Padrão |
|---|---|
CandleType |
TimeSpan.FromMinutes(30).TimeFrame() |
JawLength |
13 |
TeethLength |
8 |
LipsLength |
5 |
JawShift |
8 |
TeethShift |
5 |
LipsShift |
3 |
AtrPeriod |
14 |
AtrMultiplier |
2 |
Verificação
Ambas as linguagens são verificadas com BTC/TON incluído, fórmulas independentes, direção/tamanho das ordens, execuções, posições e saídas. Dados datados de preços/fatores e calendário verificam mecânica; OHLC/volumes deslocados não são história plurianual. Dois grupos, TopN=1 e SMA=2 são perfis pequenos explícitos. Janelas longas e valores originais são verificados separadamente. Sem promessa de rentabilidade.
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()