Главная
/
Примеры стратегий
Открыть на GitHub
Стратегия Linear Regression Channel (Fibo)
Описание
Стратегия представляет собой перенос советника MetaTrader «linear regression channel» на платформу StockSharp. Для определения направления используются линейно-взвешенные скользящие средние, фильтр по индикатору Momentum на более старшем таймфрейме и месячный MACD. Блок управления капиталом повторяет оригинал: денежные цели по плавающей прибыли, трейлинг накопленного результата, перевод в безубыток и стоп по просадке капитала.
Логика входов
Базовый таймфрейм – настраиваемый тип свечей (по умолчанию 15 минут), на котором рассчитываются все сигналы.
Трендовый фильтр – сравнение быстрой и медленной LWMA, рассчитанных по типичной цене. Для покупок требуется, чтобы быстрая LWMA была выше медленной, для продаж – наоборот.
Подтверждение Momentum – индикатор оценивается на более старшем таймфрейме (M1→M15, M5→M30, M15→H1, M30→H4, H1→D1, H4→W1, D1→MN1). Рассматриваются три последних значения и их отклонение от уровня 100. Если хотя бы одно из значений превышает порог для покупок/продаж, фильтр считается выполненным.
Месячный MACD – сделки на покупку разрешены только при условии, что основная линия MACD(12,26,9) выше сигнальной; продажи – при обратном соотношении.
Открытие позиции – при выполнении всех фильтров стратегия выставляет рыночный ордер. При появлении противоположного сигнала позиция закрывается и может быть развернута.
Управление позицией
Фиксированные стоп и тейк – расстояния в пунктах задаются параметрами и проверяются на каждой закрытой свече.
Трейлинг-стоп – опционально активируется после достижения заданной прибыли и тянет стоп на указанном расстоянии от экстремума.
Перевод в безубыток – после достижения триггера стоп переносится к цене входа с заданным запасом.
Денежный тейк – при превышении целевой плавающей прибыли вся позиция закрывается.
Процентный тейк – цель рассчитывается как доля от стартового капитала стратегии.
Трейлинг по прибыли – после достижения пороговой прибыли фиксируется максимум; если текущая прибыль упала больше чем на заданную величину, позиция закрывается.
Стоп по капиталу – когда плавающий убыток превышает процент от максимальной достигнутой стоимости портфеля, позиция ликвидируется.
Параметры
Параметр
Назначение
Candle Type
Рабочий таймфрейм стратегии.
Fast LWMA / Slow LWMA
Периоды быстрых и медленных LWMA.
Momentum Length
Длина расчета Momentum на старшем таймфрейме.
Momentum Buy Threshold / Momentum Sell Threshold
Минимальное отклонение от уровня 100 для подтверждения покупок/продаж.
Take Profit (points) / Stop Loss (points)
Фиксированные значения тейк-профита и стоп-лосса в пунктах.
Use Trailing, Trailing Activation, Trailing Offset
Параметры трейлинг-стопа.
Use Break-even, Break-even Trigger, Break-even Offset
Настройки перевода в безубыток.
Max Trades
Максимальное количество входов за запуск стратегии.
Order Volume
Базовый объем заявок.
Use Money TP, Money Take Profit
Денежная цель по плавающей прибыли.
Use Percent TP, Percent Take Profit
Цель как процент от стартового капитала.
Enable Money Trailing, Money Trailing Trigger, Money Trailing Stop
Защита накопленной прибыли от отката.
Use Equity Stop, Equity Risk %
Ограничение просадки капитала.
Дополнительно
Стратегия удерживает единственную суммарную позицию и может разворачиваться при смене сигнала.
Метод GetWorkingSecurities() автоматически подписывает необходимые старшие таймфреймы для Momentum и MACD.
Комментарии в коде выполняются только на английском языке, как требует репозиторий.
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;
public class LinearRegressionChannelFibStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public LinearRegressionChannelFibStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_prevFast = fastValue; _prevSlow = slowValue;
}
}
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 linear_regression_channel_fib_strategy(Strategy):
def __init__(self):
super(linear_regression_channel_fib_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 14) \
.SetDisplay("Fast Period", "Fast MA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow MA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def stop_loss_points(self):
return self._stop_loss_points.Value
@property
def take_profit_points(self):
return self._take_profit_points.Value
def OnReseted(self):
super(linear_regression_channel_fib_strategy, self).OnReseted()
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(linear_regression_channel_fib_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = self.fast_period
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._fast, self._slow, self._process_candle)
subscription.Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if not self._fast.IsFormed or not self._slow.IsFormed:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if self.Position > 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close <= self._entry_price - self.stop_loss_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close >= self._entry_price + self.take_profit_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
elif self.Position < 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close >= self._entry_price + self.stop_loss_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close <= self._entry_price - self.take_profit_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return linear_regression_channel_fib_strategy()