Estrategia Ride Alligator Williams
Esta estrategia implementa el indicador Alligator de Bill Williams. Las líneas de labios, dientes y mandíbula se calculan desde el precio medio usando medias móviles suavizadas con longitudes derivadas de un período base a través de la razón áurea. Se abre una posición larga cuando los labios cruzan por encima de la mandíbula mientras los dientes permanecen por debajo. Se abre una posición corta cuando los labios cruzan por debajo de la mandíbula mientras los dientes permanecen por encima. Para una posición abierta, un trailing stop sigue la línea de la mandíbula.
Parámetros
- Base Period – período raíz usado para derivar las longitudes del Alligator.
- Candle Type – marco temporal de las velas de entrada.
Indicadores
- Media Móvil Suavizada (labios, dientes, mandíbula)
Reglas de entrada
- Largo cuando los labios cruzan por encima de la mandíbula y los dientes están por debajo.
- Corto cuando los labios cruzan por debajo de la mandíbula y los dientes están por encima.
Reglas de salida
- Un cruce opuesto cierra la posición.
- El trailing stop en la línea de la mandíbula sale cuando el precio la cruza.
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>
/// Strategy based on Bill Williams Alligator.
/// Buys when the lips cross above the jaws while the teeth remain below.
/// Sells when the lips cross below the jaws while the teeth remain above.
/// A trailing stop is placed at the jaws line.
/// </summary>
public class RideAlligatorWilliamsStrategy : Strategy
{
private readonly StrategyParam<int> _basePeriod;
private readonly StrategyParam<DataType> _candleType;
private SmoothedMovingAverage _jaw;
private SmoothedMovingAverage _teeth;
private SmoothedMovingAverage _lips;
private bool _prevLipsAboveJaw;
private decimal? _stopPrice;
/// <summary>
/// Base period used to calculate Alligator lengths.
/// </summary>
public int BasePeriod
{
get => _basePeriod.Value;
set => _basePeriod.Value = value;
}
/// <summary>
/// Candle type for strategy calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of <see cref="RideAlligatorWilliamsStrategy"/>.
/// </summary>
public RideAlligatorWilliamsStrategy()
{
_basePeriod = Param(nameof(BasePeriod), 8)
.SetGreaterThanZero()
.SetDisplay("Base Period", "Root period for Alligator lines", "Alligator");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for strategy", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevLipsAboveJaw = false;
_stopPrice = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var a1 = (int)Math.Round(BasePeriod * 1.61803398874989m);
var a2 = (int)Math.Round(a1 * 1.61803398874989m);
var a3 = (int)Math.Round(a2 * 1.61803398874989m);
_jaw = new SmoothedMovingAverage { Length = a3 };
_teeth = new SmoothedMovingAverage { Length = a2 };
_lips = new SmoothedMovingAverage { Length = a1 };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ProcessCandle);
subscription.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _jaw);
DrawIndicator(area, _teeth);
DrawIndicator(area, _lips);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
var median = (candle.HighPrice + candle.LowPrice) / 2m;
var isFinal = candle.State == CandleStates.Finished;
var jawVal = _jaw.Process(new DecimalIndicatorValue(_jaw, median, candle.ServerTime) { IsFinal = isFinal });
var teethVal = _teeth.Process(new DecimalIndicatorValue(_teeth, median, candle.ServerTime) { IsFinal = isFinal });
var lipsVal = _lips.Process(new DecimalIndicatorValue(_lips, median, candle.ServerTime) { IsFinal = isFinal });
if (!isFinal)
return;
if (!_jaw.IsFormed || !_teeth.IsFormed || !_lips.IsFormed)
return;
var jaw = jawVal.GetValue<decimal>();
var teeth = teethVal.GetValue<decimal>();
var lips = lipsVal.GetValue<decimal>();
var lipsAboveJaw = lips > jaw;
var lipsBelowJaw = lips < jaw;
var teethAboveJaw = teeth > jaw;
var teethBelowJaw = teeth < jaw;
if (Position <= 0 && !_prevLipsAboveJaw && lipsAboveJaw && teethBelowJaw)
{
BuyMarket();
_stopPrice = null;
}
else if (Position >= 0 && _prevLipsAboveJaw && lipsBelowJaw && teethAboveJaw)
{
SellMarket();
_stopPrice = null;
}
if (Position > 0)
{
if (jaw < candle.ClosePrice)
{
var step = Security.PriceStep ?? 0m;
if (_stopPrice is null || jaw > _stopPrice + step)
_stopPrice = jaw;
}
if (_stopPrice != null && candle.ClosePrice <= _stopPrice)
{
SellMarket(Position);
_stopPrice = null;
}
}
else if (Position < 0)
{
if (jaw > candle.ClosePrice)
{
var step = Security.PriceStep ?? 0m;
if (_stopPrice is null || jaw < _stopPrice - step)
_stopPrice = jaw;
}
if (_stopPrice != null && candle.ClosePrice >= _stopPrice)
{
BuyMarket(Math.Abs(Position));
_stopPrice = null;
}
}
_prevLipsAboveJaw = lipsAboveJaw;
}
}
import clr
import math
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SmoothedMovingAverage
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class ride_alligator_williams_strategy(Strategy):
def __init__(self):
super(ride_alligator_williams_strategy, self).__init__()
self._base_period = self.Param("BasePeriod", 8)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30)))
self._jaw = None
self._teeth = None
self._lips = None
self._prev_lips_above_jaw = False
self._stop_price = None
@property
def BasePeriod(self):
return self._base_period.Value
@BasePeriod.setter
def BasePeriod(self, value):
self._base_period.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(ride_alligator_williams_strategy, self).OnStarted2(time)
self._prev_lips_above_jaw = False
self._stop_price = None
bp = int(self.BasePeriod)
phi = 1.61803398874989
a1 = int(round(bp * phi))
a2 = int(round(a1 * phi))
a3 = int(round(a2 * phi))
self._jaw = SmoothedMovingAverage()
self._jaw.Length = a3
self._teeth = SmoothedMovingAverage()
self._teeth.Length = a2
self._lips = SmoothedMovingAverage()
self._lips.Length = a1
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self.ProcessCandle).Start()
def ProcessCandle(self, candle):
h = float(candle.HighPrice)
l = float(candle.LowPrice)
median = (h + l) / 2.0
is_final = candle.State == CandleStates.Finished
jaw_result = process_float(self._jaw, median, candle.ServerTime, is_final)
teeth_result = process_float(self._teeth, median, candle.ServerTime, is_final)
lips_result = process_float(self._lips, median, candle.ServerTime, is_final)
if not is_final:
return
if not self._jaw.IsFormed or not self._teeth.IsFormed or not self._lips.IsFormed:
return
jaw_val = float(jaw_result)
teeth_val = float(teeth_result)
lips_val = float(lips_result)
close = float(candle.ClosePrice)
lips_above_jaw = lips_val > jaw_val
lips_below_jaw = lips_val < jaw_val
teeth_above_jaw = teeth_val > jaw_val
teeth_below_jaw = teeth_val < jaw_val
pos = float(self.Position)
if pos <= 0 and not self._prev_lips_above_jaw and lips_above_jaw and teeth_below_jaw:
self.BuyMarket()
self._stop_price = None
elif pos >= 0 and self._prev_lips_above_jaw and lips_below_jaw and teeth_above_jaw:
self.SellMarket()
self._stop_price = None
pos = float(self.Position)
if pos > 0:
if jaw_val < close:
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 0.0
if self._stop_price is None or jaw_val > self._stop_price + step:
self._stop_price = jaw_val
if self._stop_price is not None and close <= self._stop_price:
self.SellMarket(pos)
self._stop_price = None
elif pos < 0:
if jaw_val > close:
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 0.0
if self._stop_price is None or jaw_val < self._stop_price - step:
self._stop_price = jaw_val
if self._stop_price is not None and close >= self._stop_price:
self.BuyMarket(abs(pos))
self._stop_price = None
self._prev_lips_above_jaw = lips_above_jaw
def OnReseted(self):
super(ride_alligator_williams_strategy, self).OnReseted()
self._jaw = None
self._teeth = None
self._lips = None
self._prev_lips_above_jaw = False
self._stop_price = None
def CreateClone(self):
return ride_alligator_williams_strategy()