Главная
/
Примеры стратегий
Открыть на GitHub
Compass Line Strategy
Стратегия воспроизводит советник CompassLine, объединяя два фильтра:
Follow Line — трейлинг на основе пробоя полос Боллинджера с опциональным смещением ATR. При выходе цены за пределы полос линия продолжает расти (или снижаться) и не откатывается, пока сохраняется тренд.
Compass — логистическое преобразование медианной цены относительно максимума и минимума за период скользящей средней. Сырый сигнал дважды сглаживается треугольным окном для получения устойчивого состояния «бык/медведь».
Сделка открывается только при совпадении направления обоих фильтров. Дополнительно доступны временной фильтр и защитные стопы, как в оригинальной реализации.
Детали
Вход :
Follow Line должен указывать вверх (закрытие выше верхней полосы) для покупок или вниз (закрытие ниже нижней полосы) для продаж. Смещение ATR включается параметром UseAtrFilter.
Состояние Compass (период задаётся CompassPeriod) должно быть положительным для покупок и отрицательным для продаж после двойного сглаживания.
Торговля выполняется только в рамках сессии, заданной UseTimeFilter и строкой Session (формат HHmm-HHmm).
Длинные/Короткие : Оба направления поддерживаются.
Выход :
CloseMode = None удерживает позицию до появления противоположного сигнала или срабатывания стопов.
CloseMode = BothIndicators закрывает позицию, когда Follow Line и Compass одновременно меняют направление.
CloseMode = FollowLineOnly закрывает позицию при смене направления Follow Line.
CloseMode = CompassOnly закрывает позицию при смене полярности Compass.
Стопы : TakeProfit и StopLoss (в шагах цены) устанавливаются после каждого входа, если заданы больше нуля.
Значения по умолчанию :
FollowBbPeriod = 21
FollowBbDeviation = 1
FollowAtrPeriod = 5
UseAtrFilter = false
CompassPeriod = 30 (длина сглаживания = round(CompassPeriod / 3))
CloseMode = None
UseTimeFilter = false
Session = "0000-2400"
TakeProfit = 0
StopLoss = 0
CandleType = TimeSpan.FromMinutes(15)
Фильтры :
Категория: Trend
Направление: Both
Индикаторы: Bollinger Bands, ATR, Triangular moving average
Стопы: Опционально
Сложность: Intermediate
Таймфрейм: Intraday
Сезонность: Нет
Нейросети: Нет
Дивергенции: Нет
Уровень риска: Medium
Дополнительно
Длина сглаживания Compass равна round(CompassPeriod / 3), что повторяет оригинальный индикатор.
Строки сессии вроде 0930-1600 ограничивают торговлю указанным окном, при этом индикаторы продолжают обновляться за его пределами.
Защитные заявки используют высокоуровневые методы StockSharp и совместимы с управлением рисками портфеля.
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()