Стратегия воспроизводит логику советника MetaTrader Expert_AMS_ES_MFI, сочетая свечные разворотные модели и подтверждение импульса индикатором Money Flow Index (MFI). На выбранном таймфрейме анализируются трехсвечные фигуры «Morning Star» и «Evening Star», после чего сигнал фильтруется порогами MFI, чтобы подтвердить исчерпанность текущего движения. Пересечения уровней MFI также используются для выхода из позиции.
Логика торговли
Источник данных: закрытые свечи заданного таймфрейма и рассчитанные значения MFI.
Индикаторы:
Money Flow Index (MFI) с настраиваемым периодом (по умолчанию 49).
Правила входа:
Покупка: обнаружить модель «Morning Star» (сильная медвежья свеча, маленькая центральная свеча, сильная бычья свеча, закрывающаяся выше середины тела первой) и убедиться, что значение MFI на предыдущей свече ниже порога подтверждения (по умолчанию 40).
Продажа: обнаружить модель «Evening Star» (сильная бычья свеча, маленькая центральная свеча, сильная медвежья свеча, закрывающаяся ниже середины тела первой) и убедиться, что значение MFI на предыдущей свече выше порога подтверждения (по умолчанию 60).
При смене направления стратегия сначала закрывает противоположную позицию и только затем открывает новую.
Правила выхода:
Выход из лонга: зафиксировать позицию, если MFI пересекает сверху уровень перекупленности (по умолчанию 70) или опускается ниже уровня перепроданности (по умолчанию 30), что сигнализирует о перегреве импульса или срыве разворота.
Выход из шорта: зафиксировать позицию, если MFI пробивает вверх уровень перепроданности (30) либо продолжает рост выше перекупленности (70), что указывает на усиление быков.
Тип заявок: рыночные ордера с объемом, заданным в настройках StockSharp.
Параметры
Название
Описание
Значение по умолчанию
CandleType
Таймфрейм анализируемых свечей.
Свечи 1 часа
MfiPeriod
Период индикатора MFI.
49
BullishMfiThreshold
Порог MFI для подтверждения сигналов Morning Star.
40
BearishMfiThreshold
Порог MFI для подтверждения сигналов Evening Star.
60
UpperExitLevel
Уровень MFI для фиксации перекупленности.
70
LowerExitLevel
Уровень MFI для фиксации перепроданности.
30
Все параметры можно оптимизировать в StockSharp Designer или Optimizer.
Рекомендации по использованию
Подключите стратегию к нужному инструменту и выставьте CandleType, соответствующий таймфрейму исходного MQL-советника.
Настройте риск-параметры (объем, кредитное плечо, ограничения брокера) в интерфейсе StockSharp.
Запустите стратегию — она автоматически подпишется на свечи, рассчитает значения MFI и начнет управление позицией по описанным правилам.
Происхождение
Стратегия является прямой конверсией советника из каталога MQL/323, сохраняет его логику на основе свечных моделей и MFI, но реализована средствами высокоуровневого API StockSharp.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Morning/Evening Star + MFI strategy.
/// Buys on morning star with low MFI, sells on evening star with high MFI.
/// </summary>
public class MorningEveningMfiStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _mfiPeriod;
private readonly StrategyParam<decimal> _mfiLow;
private readonly StrategyParam<decimal> _mfiHigh;
private readonly StrategyParam<int> _signalCooldownCandles;
private ICandleMessage _prevCandle;
private ICandleMessage _prevPrevCandle;
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int MfiPeriod { get => _mfiPeriod.Value; set => _mfiPeriod.Value = value; }
public decimal MfiLow { get => _mfiLow.Value; set => _mfiLow.Value = value; }
public decimal MfiHigh { get => _mfiHigh.Value; set => _mfiHigh.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public MorningEveningMfiStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_mfiPeriod = Param(nameof(MfiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("MFI Period", "MFI period", "Indicators");
_mfiLow = Param(nameof(MfiLow), 40m)
.SetDisplay("MFI Low", "MFI oversold threshold", "Signals");
_mfiHigh = Param(nameof(MfiHigh), 60m)
.SetDisplay("MFI High", "MFI overbought threshold", "Signals");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCandle = null;
_prevPrevCandle = null;
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevCandle = null;
_prevPrevCandle = null;
_candlesSinceTrade = SignalCooldownCandles;
var mfi = new MoneyFlowIndex { Length = MfiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(mfi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal mfiValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
if (_prevCandle != null && _prevPrevCandle != null)
{
var prevBody = Math.Abs(_prevCandle.ClosePrice - _prevCandle.OpenPrice);
var prevRange = _prevCandle.HighPrice - _prevCandle.LowPrice;
var isSmallBody = prevRange > 0 && prevBody < prevRange * 0.3m;
var firstMidpoint = (_prevPrevCandle.OpenPrice + _prevPrevCandle.ClosePrice) / 2m;
var firstBearish = _prevPrevCandle.OpenPrice > _prevPrevCandle.ClosePrice;
var currBullish = candle.ClosePrice > candle.OpenPrice;
var isMorningStar = firstBearish && isSmallBody && currBullish && candle.ClosePrice > firstMidpoint;
var firstBullish = _prevPrevCandle.ClosePrice > _prevPrevCandle.OpenPrice;
var currBearish = candle.OpenPrice > candle.ClosePrice;
var isEveningStar = firstBullish && isSmallBody && currBearish && candle.ClosePrice < firstMidpoint;
if (isMorningStar && mfiValue < MfiLow && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (isEveningStar && mfiValue > MfiHigh && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
_prevPrevCandle = _prevCandle;
_prevCandle = candle;
}
}
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 MoneyFlowIndex
from StockSharp.Algo.Strategies import Strategy
class morning_evening_mfi_strategy(Strategy):
def __init__(self):
super(morning_evening_mfi_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._mfi_period = self.Param("MfiPeriod", 14)
self._mfi_low = self.Param("MfiLow", 40.0)
self._mfi_high = self.Param("MfiHigh", 60.0)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 6)
self._prev_candle = None
self._prev_prev_candle = None
self._candles_since_trade = 6
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def MfiPeriod(self):
return self._mfi_period.Value
@MfiPeriod.setter
def MfiPeriod(self, value):
self._mfi_period.Value = value
@property
def MfiLow(self):
return self._mfi_low.Value
@MfiLow.setter
def MfiLow(self, value):
self._mfi_low.Value = value
@property
def MfiHigh(self):
return self._mfi_high.Value
@MfiHigh.setter
def MfiHigh(self, value):
self._mfi_high.Value = value
@property
def SignalCooldownCandles(self):
return self._signal_cooldown_candles.Value
@SignalCooldownCandles.setter
def SignalCooldownCandles(self, value):
self._signal_cooldown_candles.Value = value
def OnReseted(self):
super(morning_evening_mfi_strategy, self).OnReseted()
self._prev_candle = None
self._prev_prev_candle = None
self._candles_since_trade = self.SignalCooldownCandles
def OnStarted2(self, time):
super(morning_evening_mfi_strategy, self).OnStarted2(time)
self._prev_candle = None
self._prev_prev_candle = None
self._candles_since_trade = self.SignalCooldownCandles
mfi = MoneyFlowIndex()
mfi.Length = self.MfiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(mfi, self._process_candle).Start()
def _process_candle(self, candle, mfi_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
mfi_val = float(mfi_value)
if self._prev_candle is not None and self._prev_prev_candle is not None:
prev_body = abs(float(self._prev_candle.ClosePrice) - float(self._prev_candle.OpenPrice))
prev_range = float(self._prev_candle.HighPrice) - float(self._prev_candle.LowPrice)
is_small_body = prev_range > 0 and prev_body < prev_range * 0.3
first_midpoint = (float(self._prev_prev_candle.OpenPrice) + float(self._prev_prev_candle.ClosePrice)) / 2.0
first_bearish = float(self._prev_prev_candle.OpenPrice) > float(self._prev_prev_candle.ClosePrice)
curr_bullish = float(candle.ClosePrice) > float(candle.OpenPrice)
is_morning_star = first_bearish and is_small_body and curr_bullish and float(candle.ClosePrice) > first_midpoint
first_bullish = float(self._prev_prev_candle.ClosePrice) > float(self._prev_prev_candle.OpenPrice)
curr_bearish = float(candle.OpenPrice) > float(candle.ClosePrice)
is_evening_star = first_bullish and is_small_body and curr_bearish and float(candle.ClosePrice) < first_midpoint
if is_morning_star and mfi_val < self.MfiLow and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif is_evening_star and mfi_val > self.MfiHigh and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
self._prev_prev_candle = self._prev_candle
self._prev_candle = candle
def CreateClone(self):
return morning_evening_mfi_strategy()