Дневная стратегия по GBP/USD, сочетающая EMA по максимумам свечи, фильтр RSI, подтверждение импульса MACD и управление риском через ATR. Реализация повторяет оригинальный советник MetaTrader с четырьмя частичными фиксингами прибыли и переводом стопа в безубыток.
Основные сведения
Рынок: пара GBP/USD (спот или CFD)
Таймфрейм: дневные свечи (настраивается)
Направление: длинные и короткие позиции
Стиль управления: пакет из четырёх ордеров с общим стопом
Используемые индикаторы: EMA по High, RSI, основная линия MACD, ATR
Настройка индикаторов
EMA по максимумам – период 6, служит линией пробоя.
RSI – период 10, задаёт диапазоны допустимого импульса.
MACD (главная линия) – fast 5, slow 21, signal 14; используется наклон основной линии.
ATR – период 28, вычисляет волатильностные стопы и цели.
Логика входа
Длинные позиции
Предыдущая дневная свеча открылась ниже EMA(High) и закрылась выше – факт пробоя вверх.
RSI находится между 60 и 80, что исключает слабый импульс и перекупленность.
Выполнено одно из условий по MACD:
Значение MACD две свечи назад отрицательное (тренд только что сменился вверх); или
Относительное снижение |MACD| за последние две свечи превышает порог MacdDiffBuy (0.5 по умолчанию).
При выполнении условий стратегия закрывает шорты и выставляет четыре одинаковых рыночных ордера на покупку (по умолчанию 0.1 лота каждый).
Короткие позиции
Свеча открылась выше EMA(High) и закрылась ниже неё.
RSI находится между 25 и 39 – зеркальный фильтр для шортов.
MACD две свечи назад положительный либо относительное изменение |MACD| превышает MacdDiffSell (0.15 по умолчанию).
После подтверждения закрываются лонги и выставляются четыре равных рыночных ордера на продажу.
Управление позицией
Стоп-лосс: общий для пакета, рассчитывается как entry ± ATR * StopLossMultiplier (1.6 по умолчанию, знак зависит от направления).
Частичное закрытие: четыре цели по ATR с коэффициентами 1.0, 1.5, 2.0, 2.5, умноженными на TakeProfitMultiplier (по умолчанию 1). При достижении каждая цель закрывает четверть исходного объёма.
Перевод в безубыток: после каждого тейк-профита стоп переносится на цену сработавшего тейка, что полностью повторяет логику оригинального советника.
Отработка стопа: если максимум/минимум свечи пересекает уровень защиты, остаток позиции закрывается рыночным ордером.
Особенности контроля риска
Стратегия не наращивает позицию сверх четырёх стартовых ордеров; новые сигналы игнорируются, пока сохраняется позиция в том же направлении.
Сигналы появляются только после формирования ATR и MACD (значение ATR должно быть > 0).
Изменение параметров во время работы влияет лишь на будущие сделки; объём каждой доли фиксируется при входе для корректного выхода.
Параметры
Параметр
Описание
Значение по умолчанию
OrderVolume
Объём одной рыночной заявки
0.1
EmaPeriod
Период EMA по максимумам
6
RsiPeriod
Период RSI
10
AtrPeriod
Период ATR
28
StopLossMultiplier
Множитель ATR для стоп-лосса
1.6
TakeProfitMultiplier
Базовый множитель ATR для целей
1.0
MacdFastPeriod
Быстрый период MACD
5
MacdSlowPeriod
Медленный период MACD
21
MacdSignalPeriod
Период сигнальной линии MACD
14
MacdDiffBuyThreshold
Минимальный прирост наклона MACD для лонга
0.5
MacdDiffSellThreshold
Минимальный прирост наклона MACD для шорта
0.15
RsiUpperLimit
Верхняя граница RSI для входа в лонг
80
RsiUpperLevel
Нижняя граница RSI для входа в лонг
60
RsiLowerLevel
Верхняя граница RSI для входа в шорт
39
RsiLowerLimit
Нижняя граница RSI для входа в шорт
25
CandleType
Тип подписываемых свечей
1 Day
Практические рекомендации
Оптимизируйте фильтры RSI и MACD совместно: чрезмерное расширение диапазона RSI без корректировки 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;
/// <summary>
/// Alexav D1 Profit GBPUSD strategy (simplified). Uses EMA crossover with RSI
/// filter for breakout entries with ATR-based stop/take management.
/// </summary>
public class AlexavD1ProfitGbpUsdStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaFastLength;
private readonly StrategyParam<int> _emaSlowLength;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<decimal> _rsiUpperLevel;
private readonly StrategyParam<decimal> _rsiLowerLevel;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int EmaFastLength
{
get => _emaFastLength.Value;
set => _emaFastLength.Value = value;
}
public int EmaSlowLength
{
get => _emaSlowLength.Value;
set => _emaSlowLength.Value = value;
}
public int RsiLength
{
get => _rsiLength.Value;
set => _rsiLength.Value = value;
}
public decimal RsiUpperLevel
{
get => _rsiUpperLevel.Value;
set => _rsiUpperLevel.Value = value;
}
public decimal RsiLowerLevel
{
get => _rsiLowerLevel.Value;
set => _rsiLowerLevel.Value = value;
}
public AlexavD1ProfitGbpUsdStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_emaFastLength = Param(nameof(EmaFastLength), 6)
.SetGreaterThanZero()
.SetDisplay("EMA Fast", "Fast EMA period", "Indicators");
_emaSlowLength = Param(nameof(EmaSlowLength), 21)
.SetGreaterThanZero()
.SetDisplay("EMA Slow", "Slow EMA period", "Indicators");
_rsiLength = Param(nameof(RsiLength), 10)
.SetGreaterThanZero()
.SetDisplay("RSI Length", "RSI period", "Indicators");
_rsiUpperLevel = Param(nameof(RsiUpperLevel), 65m)
.SetDisplay("RSI Upper", "Max RSI for buy", "Filters");
_rsiLowerLevel = Param(nameof(RsiLowerLevel), 35m)
.SetDisplay("RSI Lower", "Min RSI for sell", "Filters");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var emaFast = new ExponentialMovingAverage { Length = EmaFastLength };
var emaSlow = new ExponentialMovingAverage { Length = EmaSlowLength };
decimal prevFast = 0, prevSlow = 0;
var hasPrev = false;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(emaFast, emaSlow, (ICandleMessage candle, decimal fastVal, decimal slowVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!hasPrev)
{
prevFast = fastVal;
prevSlow = slowVal;
hasPrev = true;
return;
}
if (!IsFormedAndOnlineAndAllowTrading())
{
prevFast = fastVal;
prevSlow = slowVal;
return;
}
var close = candle.ClosePrice;
// EMA fast crosses above slow - buy signal
var bullishCross = prevFast <= prevSlow && fastVal > slowVal;
// EMA fast crosses below slow - sell signal
var bearishCross = prevFast >= prevSlow && fastVal < slowVal;
if (bullishCross && Position <= 0)
BuyMarket();
else if (bearishCross && Position >= 0)
SellMarket();
prevFast = fastVal;
prevSlow = slowVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, emaFast);
DrawIndicator(area, emaSlow);
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class alexav_d1_profit_gbp_usd_strategy(Strategy):
def __init__(self):
super(alexav_d1_profit_gbp_usd_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candles", "General")
self._ema_fast_length = self.Param("EmaFastLength", 6) \
.SetDisplay("EMA Fast", "Fast EMA period", "Indicators")
self._ema_slow_length = self.Param("EmaSlowLength", 21) \
.SetDisplay("EMA Slow", "Slow EMA period", "Indicators")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@property
def EmaFastLength(self):
return self._ema_fast_length.Value
@property
def EmaSlowLength(self):
return self._ema_slow_length.Value
def OnReseted(self):
super(alexav_d1_profit_gbp_usd_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(alexav_d1_profit_gbp_usd_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
ema_fast = ExponentialMovingAverage()
ema_fast.Length = self.EmaFastLength
ema_slow = ExponentialMovingAverage()
ema_slow.Length = self.EmaSlowLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema_fast, ema_slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema_fast)
self.DrawIndicator(area, ema_slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if not self._has_prev:
self._prev_fast = fv
self._prev_slow = sv
self._has_prev = True
return
if self._prev_fast <= self._prev_slow and fv > sv and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fv < sv and self.Position >= 0:
self.SellMarket()
self._prev_fast = fv
self._prev_slow = sv
def CreateClone(self):
return alexav_d1_profit_gbp_usd_strategy()