Momentum Alligator 4h Bitcoin Strategy
The Momentum Alligator 4h Bitcoin strategy combines the Awesome Oscillator with the Bill Williams Alligator on the daily timeframe. A long position is opened when the oscillator crosses above its 5-period SMA and price trades above all three daily Alligator lines. A dynamic stop-loss uses the greater of a percentage drop from entry and the Alligator jaw line. After a profitable exit the strategy skips the next two signals.
Details
- Entry Criteria: AO crosses above its 5-period SMA and close is above daily Alligator lines.
- Long/Short: Long only.
- Exit Criteria: Dynamic stop-loss at max of percent stop and Alligator jaw.
- Stops: Yes.
- Default Values:
StopLossPercent= 0.02mCandleType= TimeSpan.FromHours(4)TradeStart= 2023-01-01TradeStop= 2025-01-01
- Filters:
- Category: Momentum
- Direction: Long
- Indicators: Awesome Oscillator, Alligator
- Stops: Yes
- Complexity: Basic
- Timeframe: Mid-term
- Seasonality: No
- Neural Networks: No
- Divergence: No
- Risk Level: Medium
using System;
using System.Linq;
using Ecng.Common;
using StockSharp.Algo;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Momentum Alligator strategy for Bitcoin.
/// </summary>
public class MomentumAlligator4hBitcoinStrategy : Strategy
{
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<int> _signalCooldownBars;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevAo;
private bool _hasPrev;
private decimal _entryPrice;
private int _barsFromSignal;
public decimal StopLossPercent { get => _stopLossPercent.Value; set => _stopLossPercent.Value = value; }
public int SignalCooldownBars { get => _signalCooldownBars.Value; set => _signalCooldownBars.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MomentumAlligator4hBitcoinStrategy()
{
_stopLossPercent = Param(nameof(StopLossPercent), 0.02m).SetGreaterThanZero();
_signalCooldownBars = Param(nameof(SignalCooldownBars), 2).SetGreaterThanZero();
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame());
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevAo = 0m;
_hasPrev = false;
_entryPrice = 0m;
_barsFromSignal = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevAo = 0;
_hasPrev = false;
_entryPrice = 0;
_barsFromSignal = SignalCooldownBars;
var jaw = new SmoothedMovingAverage { Length = 13 };
var teeth = new SmoothedMovingAverage { Length = 8 };
var lips = new SmoothedMovingAverage { Length = 5 };
var ao = new AwesomeOscillator { ShortMa = { Length = 5 }, LongMa = { Length = 34 } };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ao, jaw, teeth, lips, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal ao, decimal jaw, decimal teeth, decimal lips)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
_barsFromSignal++;
if (_hasPrev)
{
var aoCrossUp = _prevAo <= 0m && ao > 0m;
var aoCrossDown = _prevAo >= 0m && ao < 0m;
var alligatorBull = lips > teeth && close > jaw;
var alligatorBear = lips < teeth && close < jaw;
if (_barsFromSignal >= SignalCooldownBars && aoCrossUp && alligatorBull && Position <= 0)
{
BuyMarket();
_entryPrice = close;
_barsFromSignal = 0;
}
if (_barsFromSignal >= SignalCooldownBars && aoCrossDown && alligatorBear && Position >= 0)
{
SellMarket();
_entryPrice = close;
_barsFromSignal = 0;
}
}
if (Position > 0 && _entryPrice > 0)
{
var percentStop = _entryPrice * (1m - StopLossPercent);
if (close < percentStop || close < teeth)
{
SellMarket();
}
}
else if (Position < 0 && _entryPrice > 0)
{
var percentStop = _entryPrice * (1m + StopLossPercent);
if (close > percentStop || close > teeth)
{
BuyMarket();
}
}
_prevAo = ao;
_hasPrev = true;
}
}
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 SmoothedMovingAverage, AwesomeOscillator
from StockSharp.Algo.Strategies import Strategy
class momentum_alligator_4h_bitcoin_strategy(Strategy):
"""
Momentum Alligator 4h Bitcoin: AO zero-line cross with Alligator alignment and stop-loss.
"""
def __init__(self):
super(momentum_alligator_4h_bitcoin_strategy, self).__init__()
self._stop_loss_pct = self.Param("StopLossPercent", 0.02).SetDisplay("SL %", "Stop loss percent", "Risk")
self._cooldown_bars = self.Param("SignalCooldownBars", 2).SetDisplay("Cooldown", "Min bars between entries", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))).SetDisplay("Candle Type", "Candles", "General")
self._prev_ao = 0.0
self._has_prev = False
self._entry_price = 0.0
self._bars_from_signal = 2
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(momentum_alligator_4h_bitcoin_strategy, self).OnReseted()
self._prev_ao = 0.0
self._has_prev = False
self._entry_price = 0.0
self._bars_from_signal = self._cooldown_bars.Value
def OnStarted2(self, time):
super(momentum_alligator_4h_bitcoin_strategy, self).OnStarted2(time)
jaw = SmoothedMovingAverage()
jaw.Length = 13
teeth = SmoothedMovingAverage()
teeth.Length = 8
lips = SmoothedMovingAverage()
lips.Length = 5
ao = AwesomeOscillator()
ao.ShortMa.Length = 5
ao.LongMa.Length = 34
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ao, jaw, teeth, lips, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _process_candle(self, candle, ao_val, jaw_val, teeth_val, lips_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
ao = float(ao_val)
jaw = float(jaw_val)
teeth = float(teeth_val)
lips = float(lips_val)
self._bars_from_signal += 1
if self._has_prev:
ao_cross_up = self._prev_ao <= 0.0 and ao > 0.0
ao_cross_down = self._prev_ao >= 0.0 and ao < 0.0
alligator_bull = lips > teeth and close > jaw
alligator_bear = lips < teeth and close < jaw
if self._bars_from_signal >= self._cooldown_bars.Value and ao_cross_up and alligator_bull and self.Position <= 0:
self.BuyMarket()
self._entry_price = close
self._bars_from_signal = 0
if self._bars_from_signal >= self._cooldown_bars.Value and ao_cross_down and alligator_bear and self.Position >= 0:
self.SellMarket()
self._entry_price = close
self._bars_from_signal = 0
sl_pct = float(self._stop_loss_pct.Value)
if self.Position > 0 and self._entry_price > 0:
if close < self._entry_price * (1.0 - sl_pct) or close < teeth:
self.SellMarket()
elif self.Position < 0 and self._entry_price > 0:
if close > self._entry_price * (1.0 + sl_pct) or close > teeth:
self.BuyMarket()
self._prev_ao = ao
self._has_prev = True
def CreateClone(self):
return momentum_alligator_4h_bitcoin_strategy()