Стратегия Combo EA4 FSF R Updated 5
Общее описание
Эта стратегия представляет собой перенос MetaTrader-советника «Combo_EA4FSFrUpdated5» на платформу StockSharp. Решение объединяет пять модулей технического анализа — скользящие средние, RSI, стохастик, параболик SAR и нулевое запаздывание MACD. Сделка открывается только тогда, когда все включённые модули подтверждают одно и то же направление, что полностью воспроизводит консенсусную фильтрацию оригинального советника. Дополнительно сохранены опциональный трейлинг-стоп, автоматическое закрытие по сигналам и возможность мгновенного переворота после закрытия позиции.
Набор индикаторов
- Скользящие средние — три настраиваемых средних (MA1, MA2, MA3) с ATR-буферами, уменьшающими число ложных пересечений. Поддерживаются все пять режимов
MA_MODE из исходного кода.
- RSI — четыре режима подтверждения: зоны перекупленности/перепроданности, анализ наклона, комбинированный вариант и проверка зон.
- Стохастический осциллятор — параметры %K/%D и замедление, при желании накладываются пороги
StochasticHigh/StochasticLow.
- Параболик SAR — сравнивает значение SAR с закрытием предыдущей свечи.
- Zero-lag MACD — реализован через нулевые экспоненциальные средние, что повторяет индикатор
ZeroLag_MACD.mq4; доступны режимы «тренд», «пересечение нуля» и комбинированный.
- ATR — рассчитывает стопы и тейки, а также служит буфером для пересечения скользящих средних.
Логика торговли
Вход в позицию
- Стратегия дожидается формирования всех требуемых индикаторов.
- Для каждого активного модуля вычисляется направление в соответствии с выбранным режимом:
- MA — сравнение MA1/MA2/MA3 с учётом ATR-буфера.
- RSI — пороговая логика, анализ наклона, комбинированный режим или зоны.
- Стохастик — пересечение %K/%D с дополнительными фильтрами по уровням.
- Parabolic SAR — цена должна находиться выше/ниже SAR предыдущей свечи.
- Zero-lag MACD — проверка структуры гистограммы или пересечения сигнальной линии около нулевой оси.
- Если все модули выдают сигнал «Buy», открывается длинная позиция; если все выдают «Sell», открывается короткая позиция. В остальных случаях сделка не совершается.
Выход из позиции
- Закрытие по сигналам — при
AutoClose = true выполняется аналогичный консенсусный анализ с использованием параметров блока «Closing». Длинная позиция закрывается, когда все выбранные выходные модули показывают «Sell», короткая — при общем сигнале «Buy». Если OpenOppositeAfterClose = true, заявка на противоположную позицию ставится сразу после исполнения закрывающего ордера.
- Стоп-уровни — начальные стоп-лосс и тейк-профит рассчитываются как
ATR × AtrMultiplier с поправкой на минимальный шаг цены (имитация Point*MyPoint). Для длинных позиций стоп = ATR × мультипликатор − буфер, тейк = ATR × мультипликатор + буфер (для коротких зеркально).
- Трейлинг-стоп — при включенном
UseTrailingStop цена стоп-лосса обновляется на каждом завершённом баре согласно параметру TrailingStop (в пунктах).
- Жёсткие выходы — срабатывание стопа или тейка приводит к немедленному закрытию позиции без последующего переворота.
Управление объёмом
- Фиксированный объём — при
UseStaticVolume = true используется значение StaticVolume.
- Динамический объём — в противном случае объём оценивается по текущей стоимости портфеля и параметру
RiskPercent. Если данные недоступны, применяется базовый Volume стратегии.
Параметры
| Группа |
Параметр |
Назначение |
| Entries |
UseMa |
Включить подтверждение скользящими средними. |
| Entries |
MaMode |
Режим комбинирования MA (быстрая/средняя, средняя/медленная, комбинированные варианты). |
| Indicators |
Ma1Period, Ma2Period, Ma3Period |
Периоды трёх средних. |
| Indicators |
Ma1BufferPeriod, Ma2BufferPeriod |
Периоды ATR для буферов пересечения. |
| Indicators |
Ma1Method, Ma2Method, Ma3Method |
Типы скользящих (SMA, EMA, SMMA, LWMA). |
| Indicators |
Ma1Price, Ma2Price, Ma3Price |
Используемый тип цены. |
| Entries |
UseRsi |
Включить подтверждение RSI. |
| Indicators |
RsiPeriod |
Период RSI. |
| Entries |
RsiMode |
Режим анализа RSI. |
| Entries |
RsiBuyLevel, RsiSellLevel |
Пороговые уровни для зоны перепроданности/перекупленности. |
| Entries |
RsiBuyZone, RsiSellZone |
Границы зон для режима 4. |
| Entries |
UseStochastic |
Включить стохастик. |
| Indicators |
StochasticK, StochasticD, StochasticSlowing |
Параметры стохастика. |
| Entries |
UseStochasticHighLow |
Требовать выхода за уровни StochasticHigh/Low. |
| Entries |
StochasticHigh, StochasticLow |
Верхний и нижний пороги стохастика. |
| Entries |
UseSar |
Включить Parabolic SAR. |
| Indicators |
SarStep, SarMax |
Настройки ускорения SAR. |
| Entries |
UseMacd |
Включить нулевой MACD. |
| Indicators |
MacdFast, MacdSlow, MacdSignal |
Параметры MACD. |
| Indicators |
MacdPrice |
Тип цены для MACD. |
| Entries |
MacdMode |
Режим сигналов MACD. |
| Risk |
UseTrailingStop, TrailingStop |
Включить трейлинг и задать расстояние (в пунктах). |
| Risk |
UseStaticVolume, StaticVolume, RiskPercent |
Управление объёмом. |
| Risk |
AtrPeriod, AtrMultiplier |
Настройки ATR для управления рисками. |
| Exits |
AutoClose |
Включить автоматическое закрытие по сигналам. |
| Exits |
OpenOppositeAfterClose |
Переворачиваться после сигналового выхода. |
| Exits |
UseMaClosing, MaModeClosing |
Настройки выхода по MA. |
| Exits |
UseMacdClosing, MacdModeClosing |
Настройки выхода по MACD. |
| Exits |
UseRsiClosing, RsiModeClosing |
Настройки выхода по RSI. |
| Exits |
UseStochasticClosing |
Включить стохастик для выхода. |
| Exits |
UseSarClosing |
Включить SAR для выхода. |
| General |
CandleType |
Основной таймфрейм (по умолчанию 5-минутные свечи). |
Дополнительные замечания
- Стратегия ведёт только одну совокупную позицию, что упрощает управление и повторяет ограничение «Max_same_orders» оригинального советника.
- Переворот выполняется только после закрытия по сигналу; если позиция закрыта стопом или тейком, новая сделка не инициируется автоматически.
- Из-за различий в брокерских требованиях к марже динамическое вычисление объёма носит приблизительный характер — перед использованием на реальном счёте проверьте фактический размер заявки.
- Как и в MetaTrader-версии, для корректной работы нулевого MACD и ATR необходим достаточный прогрев историческими данными.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Combo EA: Triple EMA confirmation with RSI filter and ATR stops.
/// </summary>
public class ComboEa4FsfrUpdated5Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastEmaLength;
private readonly StrategyParam<int> _slowEmaLength;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<int> _atrLength;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
public ComboEa4FsfrUpdated5Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_fastEmaLength = Param(nameof(FastEmaLength), 8)
.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators");
_slowEmaLength = Param(nameof(SlowEmaLength), 21)
.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators");
_rsiLength = Param(nameof(RsiLength), 14)
.SetDisplay("RSI Length", "RSI period.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastEmaLength
{
get => _fastEmaLength.Value;
set => _fastEmaLength.Value = value;
}
public int SlowEmaLength
{
get => _slowEmaLength.Value;
set => _slowEmaLength.Value = value;
}
public int RsiLength
{
get => _rsiLength.Value;
set => _rsiLength.Value = value;
}
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = 0;
_prevSlow = 0;
_entryPrice = 0;
var fastEma = new ExponentialMovingAverage { Length = FastEmaLength };
var slowEma = new ExponentialMovingAverage { Length = SlowEmaLength };
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastEma, slowEma, rsi, atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastEma);
DrawIndicator(area, slowEma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal, decimal rsiVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevFast == 0 || _prevSlow == 0 || atrVal <= 0)
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
var close = candle.ClosePrice;
if (Position > 0)
{
if (fastVal < slowVal && _prevFast >= _prevSlow)
{
SellMarket();
_entryPrice = 0;
}
else if (close <= _entryPrice - atrVal * 2m)
{
SellMarket();
_entryPrice = 0;
}
}
else if (Position < 0)
{
if (fastVal > slowVal && _prevFast <= _prevSlow)
{
BuyMarket();
_entryPrice = 0;
}
else if (close >= _entryPrice + atrVal * 2m)
{
BuyMarket();
_entryPrice = 0;
}
}
if (Position == 0)
{
if (fastVal > slowVal && _prevFast <= _prevSlow && rsiVal > 50)
{
_entryPrice = close;
BuyMarket();
}
else if (fastVal < slowVal && _prevFast >= _prevSlow && rsiVal < 50)
{
_entryPrice = close;
SellMarket();
}
}
_prevFast = fastVal;
_prevSlow = slowVal;
}
}
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, RelativeStrengthIndex, AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class combo_ea4_fsfr_updated5_strategy(Strategy):
"""
Combo EA: Triple EMA confirmation with RSI filter and ATR stops.
"""
def __init__(self):
super(combo_ea4_fsfr_updated5_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._fast_ema_length = self.Param("FastEmaLength", 8) \
.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators")
self._slow_ema_length = self.Param("SlowEmaLength", 21) \
.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators")
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "RSI period.", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period.", "Indicators")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(combo_ea4_fsfr_updated5_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
def OnStarted2(self, time):
super(combo_ea4_fsfr_updated5_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self._fast_ema_length.Value
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self._slow_ema_length.Value
rsi = RelativeStrengthIndex()
rsi.Length = self._rsi_length.Value
atr = AverageTrueRange()
atr.Length = self._atr_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast_ema, slow_ema, rsi, atr, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ema)
self.DrawIndicator(area, slow_ema)
self.DrawOwnTrades(area)
def on_process(self, candle, fast_val, slow_val, rsi_val, atr_val):
if candle.State != CandleStates.Finished:
return
if self._prev_fast == 0.0 or self._prev_slow == 0.0 or atr_val <= 0:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
if self.Position > 0:
if (fast_val < slow_val and self._prev_fast >= self._prev_slow) or close <= self._entry_price - atr_val * 2:
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0:
if (fast_val > slow_val and self._prev_fast <= self._prev_slow) or close >= self._entry_price + atr_val * 2:
self.BuyMarket()
self._entry_price = 0.0
if self.Position == 0:
if fast_val > slow_val and self._prev_fast <= self._prev_slow and rsi_val > 50:
self._entry_price = close
self.BuyMarket()
elif fast_val < slow_val and self._prev_fast >= self._prev_slow and rsi_val < 50:
self._entry_price = close
self.SellMarket()
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return combo_ea4_fsfr_updated5_strategy()