Inicio
/
Ejemplos de estrategias
Ver en GitHub
Compass Line Strategy
This strategy replicates the CompassLine expert by merging two complementary filters:
Follow Line — a Bollinger Bands breakout trail optionally shifted by ATR. When price closes outside the bands the trail is extended in the breakout direction and never retreats while the trend persists.
Compass — a logistic transform of the median price relative to the highest high and lowest low over the moving-average window. The raw signal is double-smoothed (triangular averaging) to produce a stable bullish/bearish state.
A position is opened only when both filters agree on the trend. Optional time filtering and protective stops mirror the MQL logic.
Details
Entry Criteria :
Follow Line must point upward (recent close above the upper band) for longs or downward (recent close below the lower band) for shorts. ATR displacement can be toggled with UseAtrFilter.
Compass state (based on CompassPeriod) must be positive for longs or negative for shorts after the double smoothing phase.
Trading is executed only when the optional session filter (UseTimeFilter with Session in HHmm-HHmm) allows it.
Long/Short : Both directions are supported.
Exit Criteria :
CloseMode = None keeps the position until an opposite entry or protective stop occurs.
CloseMode = BothIndicators closes when both Follow Line and Compass reverse direction simultaneously.
CloseMode = FollowLineOnly exits when Follow Line flips against the position.
CloseMode = CompassOnly exits when Compass changes polarity.
Stops : TakeProfit and StopLoss distances (in security steps) are applied after every entry when greater than zero.
Default Values :
FollowBbPeriod = 21
FollowBbDeviation = 1
FollowAtrPeriod = 5
UseAtrFilter = false
CompassPeriod = 30 (smoothing length = round(CompassPeriod / 3))
CloseMode = None
UseTimeFilter = false
Session = "0000-2400"
TakeProfit = 0
StopLoss = 0
CandleType = TimeSpan.FromMinutes(15)
Filters :
Category: Trend
Direction: Both
Indicators: Bollinger Bands, ATR, Triangular moving average
Stops: Optional
Complexity: Intermediate
Timeframe: Intraday
Seasonality: No
Neural Networks: No
Divergence: No
Risk Level: Medium
Additional Notes
The Compass smoothing uses a triangular window equal to round(CompassPeriod / 3), closely matching the original indicator implementation.
Session strings such as 0930-1600 restrict trading to the specified window while still updating indicator states outside the session.
Protective orders reuse StockSharp's high-level helpers so the logic is compatible with portfolio risk management modules.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Compass Line strategy: BB + RSI trend filter.
/// Buys when close < lower BB and RSI < 45.
/// Sells when close > upper BB and RSI > 55.
/// </summary>
public class CompassLineStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _bbPeriod;
private readonly StrategyParam<int> _rsiPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int BbPeriod
{
get => _bbPeriod.Value;
set => _bbPeriod.Value = value;
}
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
public CompassLineStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_bbPeriod = Param(nameof(BbPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var bb = new BollingerBands { Length = BbPeriod };
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
decimal? prevClose = null;
decimal? prevLower = null;
decimal? prevUpper = null;
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(bb, rsi, (candle, bbVal, rsiVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var bbv = (BollingerBandsValue)bbVal;
if (bbv.UpBand is not decimal upper || bbv.LowBand is not decimal lower)
return;
if (rsiVal.IsEmpty)
return;
var rsiDec = rsiVal.GetValue<decimal>();
var close = candle.ClosePrice;
if (prevClose.HasValue && prevLower.HasValue && prevUpper.HasValue)
{
var crossBelowLower = prevClose.Value > prevLower.Value && close <= lower;
var crossAboveUpper = prevClose.Value < prevUpper.Value && close >= upper;
if (crossBelowLower && rsiDec < 45m && Position <= 0)
BuyMarket();
else if (crossAboveUpper && rsiDec > 55m && Position >= 0)
SellMarket();
}
prevClose = close;
prevLower = lower;
prevUpper = upper;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, bb);
DrawOwnTrades(area);
}
}
}
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 BollingerBands, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class compass_line_strategy(Strategy):
def __init__(self):
super(compass_line_strategy, self).__init__()
self._bb_period = self.Param("BbPeriod", 20) \
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI period", "Indicators")
self._bb = None
self._rsi = None
self._prev_close = None
self._prev_lower = None
self._prev_upper = None
@property
def bb_period(self):
return self._bb_period.Value
@property
def rsi_period(self):
return self._rsi_period.Value
def OnReseted(self):
super(compass_line_strategy, self).OnReseted()
self._bb = None
self._rsi = None
self._prev_close = None
self._prev_lower = None
self._prev_upper = None
def OnStarted2(self, time):
super(compass_line_strategy, self).OnStarted2(time)
self._bb = BollingerBands()
self._bb.Length = self.bb_period
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.rsi_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(30)))
subscription.BindEx(self._bb, self._rsi, self._process_candle)
subscription.Start()
def _process_candle(self, candle, bb_value, rsi_value):
if candle.State != CandleStates.Finished:
return
if not self._bb.IsFormed or not self._rsi.IsFormed:
return
upper = float(bb_value.UpBand)
lower = float(bb_value.LowBand)
rsi = float(rsi_value)
close = float(candle.ClosePrice)
if self._prev_close is not None and self._prev_lower is not None and self._prev_upper is not None:
cross_below_lower = self._prev_close > self._prev_lower and close <= lower
cross_above_upper = self._prev_close < self._prev_upper and close >= upper
if cross_below_lower and rsi < 45.0 and self.Position <= 0:
self.BuyMarket()
elif cross_above_upper and rsi > 55.0 and self.Position >= 0:
self.SellMarket()
self._prev_close = close
self._prev_lower = lower
self._prev_upper = upper
def CreateClone(self):
return compass_line_strategy()