The Aroon Horn Sign strategy looks for trend reversals using the Aroon indicator.
It monitors the Aroon Up and Down lines on higher timeframe candles. When the
Aroon Up line crosses above the Aroon Down line and stays above the 50 level,
this signals a potential bullish reversal. The strategy closes any short
position and opens a new long. Conversely, when Aroon Down dominates above 50,
any existing long is closed and a short position is initiated.
The approach uses fixed take-profit and stop-loss levels expressed in price
units. These levels are activated through the built-in risk protection module.
Because the logic relies only on the Aroon values, it works across different
markets and timeframes without additional filters.
Details
Data: Price candles.
Entry Criteria:
Long: Aroon Up > Aroon Down and Aroon Up >= 50.
Short: Aroon Down > Aroon Up and Aroon Down >= 50.
Exit Criteria:
Long positions close when a short entry condition appears.
Short positions close when a long entry condition appears.
Stops: Fixed stop-loss and take-profit using StartProtection.
Default Values:
AroonPeriod = 9
CandleType = 4‑hour candles
TakeProfit = 2000 (price units)
StopLoss = 1000 (price units)
Filters:
Category: Trend reversal
Direction: Long and Short
Indicators: Aroon
Complexity: Simple
Risk level: Medium
using System;
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>
/// Aroon Horn Sign trend reversal strategy.
/// Opens long when Aroon Up crosses above Aroon Down above 50.
/// Opens short when the opposite occurs.
/// </summary>
public class AroonHornSignStrategy : Strategy
{
private readonly StrategyParam<int> _aroonPeriod;
private readonly StrategyParam<DataType> _candleType;
private int _prevTrend;
public int AroonPeriod { get => _aroonPeriod.Value; set => _aroonPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public AroonHornSignStrategy()
{
_aroonPeriod = Param(nameof(AroonPeriod), 9)
.SetDisplay("Aroon Period", "Aroon indicator period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for processing", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevTrend = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevTrend = 0;
var aroon = new Aroon { Length = AroonPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(aroon, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, aroon);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue aroonValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var value = (IAroonValue)aroonValue;
var up = value.Up;
var down = value.Down;
if (up is null || down is null)
return;
var trend = _prevTrend;
if (up > down && up >= 50m)
trend = 1;
else if (down > up && down >= 50m)
trend = -1;
if (_prevTrend <= 0 && trend > 0 && Position <= 0)
BuyMarket();
else if (_prevTrend >= 0 && trend < 0 && Position >= 0)
SellMarket();
_prevTrend = trend;
}
}
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 Aroon
from StockSharp.Algo.Strategies import Strategy
class aroon_horn_sign_strategy(Strategy):
def __init__(self):
super(aroon_horn_sign_strategy, self).__init__()
self._aroon_period = self.Param("AroonPeriod", 9) \
.SetDisplay("Aroon Period", "Aroon indicator period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe for processing", "General")
self._prev_trend = 0
@property
def aroon_period(self):
return self._aroon_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(aroon_horn_sign_strategy, self).OnReseted()
self._prev_trend = 0
def OnStarted2(self, time):
super(aroon_horn_sign_strategy, self).OnStarted2(time)
self._prev_trend = 0
aroon = Aroon()
aroon.Length = self.aroon_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(aroon, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, aroon)
self.DrawOwnTrades(area)
def process_candle(self, candle, aroon_value):
if candle.State != CandleStates.Finished:
return
if not aroon_value.IsFormed:
return
up = aroon_value.Up
down = aroon_value.Down
if up is None or down is None:
return
up = float(up)
down = float(down)
trend = self._prev_trend
if up > down and up >= 50.0:
trend = 1
elif down > up and down >= 50.0:
trend = -1
if self._prev_trend <= 0 and trend > 0 and self.Position <= 0:
self.BuyMarket()
elif self._prev_trend >= 0 and trend < 0 and self.Position >= 0:
self.SellMarket()
self._prev_trend = trend
def CreateClone(self):
return aroon_horn_sign_strategy()