Fibonacci Auto Trend Scouter Strategy
This strategy uses two rolling extremes based on Fibonacci numbers to scout emerging trends. The short window (8) tracks recent highs and lows while the long window (21) provides context. A long position is opened when the short-term high exceeds the long-term high. A short position opens when the short-term low falls below the long-term low.
Details
- Entry Criteria:
- Long: short-term high > long-term high.
- Short: short-term low < long-term low.
- Long/Short: Both.
- Exit Criteria:
- Position is reversed on opposite signal.
- Stops: No.
- Default Values:
Short period= 8Long period= 21
- Filters:
- Category: Trend following
- Direction: Both
- Indicators: Multiple
- Stops: No
- Complexity: Simple
- Timeframe: Medium-term
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Trend detection using Fibonacci period moving averages.
/// </summary>
public class FibonacciAutoTrendScouterStrategy : Strategy
{
private readonly StrategyParam<int> _smallPeriod;
private readonly StrategyParam<int> _mediumPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevSmall;
private decimal _prevMedium;
private bool _isReady;
public int SmallPeriod { get => _smallPeriod.Value; set => _smallPeriod.Value = value; }
public int MediumPeriod { get => _mediumPeriod.Value; set => _mediumPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public FibonacciAutoTrendScouterStrategy()
{
_smallPeriod = Param(nameof(SmallPeriod), 8)
.SetGreaterThanZero()
.SetDisplay("Small Period", "Small EMA period", "General");
_mediumPeriod = Param(nameof(MediumPeriod), 21)
.SetGreaterThanZero()
.SetDisplay("Medium Period", "Medium EMA period", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle Type", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevSmall = 0;
_prevMedium = 0;
_isReady = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var emaSmall = new ExponentialMovingAverage { Length = SmallPeriod };
var emaMedium = new ExponentialMovingAverage { Length = MediumPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(emaSmall, emaMedium, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, emaSmall);
DrawIndicator(area, emaMedium);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal small, decimal medium)
{
if (candle.State != CandleStates.Finished)
return;
if (!_isReady)
{
_prevSmall = small;
_prevMedium = medium;
_isReady = true;
return;
}
// Crossover detection
var crossUp = _prevSmall <= _prevMedium && small > medium;
var crossDown = _prevSmall >= _prevMedium && small < medium;
if (crossUp && Position <= 0)
BuyMarket();
else if (crossDown && Position >= 0)
SellMarket();
_prevSmall = small;
_prevMedium = medium;
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class fibonacci_auto_trend_scouter_strategy(Strategy):
def __init__(self):
super(fibonacci_auto_trend_scouter_strategy, self).__init__()
self._small_period = self.Param("SmallPeriod", 8) \
.SetDisplay("Small Period", "Small EMA period", "General")
self._medium_period = self.Param("MediumPeriod", 21) \
.SetDisplay("Medium Period", "Medium EMA period", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle Type", "General")
self._prev_small = 0.0
self._prev_medium = 0.0
self._is_ready = False
@property
def small_period(self):
return self._small_period.Value
@property
def medium_period(self):
return self._medium_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(fibonacci_auto_trend_scouter_strategy, self).OnReseted()
self._prev_small = 0.0
self._prev_medium = 0.0
self._is_ready = False
def OnStarted2(self, time):
super(fibonacci_auto_trend_scouter_strategy, self).OnStarted2(time)
ema_small = ExponentialMovingAverage()
ema_small.Length = self.small_period
ema_medium = ExponentialMovingAverage()
ema_medium.Length = self.medium_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema_small, ema_medium, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema_small)
self.DrawIndicator(area, ema_medium)
self.DrawOwnTrades(area)
def on_process(self, candle, small, medium):
if candle.State != CandleStates.Finished:
return
if not self._is_ready:
self._prev_small = small
self._prev_medium = medium
self._is_ready = True
return
# Crossover detection
cross_up = self._prev_small <= self._prev_medium and small > medium
cross_down = self._prev_small >= self._prev_medium and small < medium
if cross_up and self.Position <= 0:
self.BuyMarket()
elif cross_down and self.Position >= 0:
self.SellMarket()
self._prev_small = small
self._prev_medium = medium
def CreateClone(self):
return fibonacci_auto_trend_scouter_strategy()