Smart Forex System — это порт советника MetaTrader на платформу StockSharp. Стратегия сочетает фильтр моментума на основе последней свечи и усредняющую сетку с увеличением объёмов. Первый ордер открывается, когда предыдущая свеча закрылась в направлении тренда и текущее закрытие достаточно отклоняется от опорной цены. Дополнительные сделки добавляются через фиксированный шаг в пунктах против текущей позиции, при этом объём умножается на заданный коэффициент. Выход осуществляется по усреднённым целям take-profit и страховочному stop-loss относительно последнего ордера сетки.
Логика работы
Генерация сигналов
Анализируется последняя завершённая свеча на выбранном таймфрейме.
Если предыдущая свеча медвежья и импульс ниже отрицательного порога, разрешается запуск длинной сетки.
Если предыдущая свеча бычья и импульс превышает положительный порог, запускается короткая сетка.
Параметр «Режим торговли» позволяет ограничить работу только лонгами, только шортами, обоими направлениями либо полностью отключить торговлю.
Расширение сетки
При наличии открытой сетки новый ордер добавляется, когда цена проходит против позиции минимум Grid Step пунктов от цены последнего ордера.
Объём каждого следующего ордера умножается на Lot Multiplier, но ограничивается биржевыми лимитами и параметром Max Volume.
Сетка перестаёт расширяться при достижении Max Trades ордеров в одном направлении.
Управление выходами
Жёсткий стоп-лосс рассчитывается от цены последнего ордера на расстояние Stop Loss пунктов. Пробой уровня закрывает всю сетку.
Цель take-profit зависит от размера сетки:
Для единственного ордера используется First Take Profit пунктов от средневзвешенной цены входа.
Для нескольких ордеров применяется Grid Take Profit пунктов от той же средней цены.
Все проверки выполняются на завершённых свечах, что обеспечивает стабильность расчётов.
Замечания по рискам
Мартингейл-подход быстро увеличивает объём позиции в затяжных трендах. Используйте консервативные множители и ограничивайте размер сетки на волатильных инструментах.
Базовый стоп-лосс (400 пунктов) повторяет настройки оригинального советника и достаточно широк. При необходимости уменьшения просадки адаптируйте его под волатильность инструмента.
Сеточная торговля требует значительного маржинального обеспечения. Проверьте соответствие параметров Start Volume, кредитного плеча и спецификаций брокера.
Параметры
Название
Описание
Значение по умолчанию
Trading Mode
Разрешённое направление торговли (лонг, шорт, оба, выключено).
Long & Short
Momentum Threshold
Минимальный импульс в условных пунктах для открытия сетки.
1
Start Volume
Объём первого ордера в новой сетке.
0.01
Max Volume
Максимальный объём одной заявки.
2
Lot Multiplier
Множитель объёмов для последующих ордеров.
1.5
Grid Step
Минимальный шаг цены в пунктах между усреднениями.
26
Max Trades
Максимальное число ордеров в одном направлении.
12
First Take Profit
Расстояние до цели, если открыт один ордер.
30
Grid Take Profit
Расстояние до цели при нескольких ордерах.
7
Stop Loss
Расстояние стоп-лосса от последнего ордера.
400
Candle Type
Таймфрейм расчёта сигналов.
Свечи 1 час
Рекомендации по применению
Подключайте стратегию к ликвидной валютной паре с предсказуемым спредом.
Настройте Candle Type под желаемый торговый горизонт (по умолчанию H1, как в оригинале).
Перед реальной торговлей оптимизируйте шаг сетки, множитель объёмов и фильтр моментума на исторических данных.
Контролируйте загрузку маржи: сетка может быстро нарастить позицию, поэтому полезно использовать дополнительные механизмы защиты капитала.
Избегайте одновременного запуска нескольких сеточных стратегий на одном инструменте, чтобы не суммировать просадки.
Отличия от версии MetaTrader
В портированной версии расчёты выполняются на завершённых свечах, что снижает шум и делает результаты воспроизводимыми.
Объёмы заявок приводятся к ограничениям инструмента через свойства StockSharp (минимальный/максимальный объём и шаг лота).
Управление стопами и целями реализовано внутри стратегии, без постоянной модификации заявок для каждой ступени сетки.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Smart Forex System strategy: Triple EMA alignment.
/// Enters when fast > mid > slow (buy) or fast < mid < slow (sell).
/// </summary>
public class SmartForexSystemStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _midPeriod;
private readonly StrategyParam<int> _slowPeriod;
private bool _wasBullishAlignment;
private bool _hasPrevAlignment;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int MidPeriod { get => _midPeriod.Value; set => _midPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public SmartForexSystemStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_midPeriod = Param(nameof(MidPeriod), 25)
.SetGreaterThanZero()
.SetDisplay("Mid EMA", "Mid EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_wasBullishAlignment = false;
_hasPrevAlignment = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_wasBullishAlignment = false;
_hasPrevAlignment = false;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var mid = new ExponentialMovingAverage { Length = MidPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, mid, slow, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal midValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
var bullishAlignment = fastValue > midValue && midValue > slowValue;
var bearishAlignment = fastValue < midValue && midValue < slowValue;
var crossedUp = bullishAlignment && (!_hasPrevAlignment || !_wasBullishAlignment);
var crossedDown = bearishAlignment && (!_hasPrevAlignment || _wasBullishAlignment);
if (crossedUp && Position <= 0)
BuyMarket();
else if (crossedDown && Position >= 0)
SellMarket();
if (bullishAlignment || bearishAlignment)
{
_wasBullishAlignment = bullishAlignment;
_hasPrevAlignment = true;
}
}
}
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 smart_forex_system_strategy(Strategy):
def __init__(self):
super(smart_forex_system_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._fast_period = self.Param("FastPeriod", 10)
self._mid_period = self.Param("MidPeriod", 25)
self._slow_period = self.Param("SlowPeriod", 50)
self._was_bullish_alignment = False
self._has_prev_alignment = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def FastPeriod(self):
return self._fast_period.Value
@FastPeriod.setter
def FastPeriod(self, value):
self._fast_period.Value = value
@property
def MidPeriod(self):
return self._mid_period.Value
@MidPeriod.setter
def MidPeriod(self, value):
self._mid_period.Value = value
@property
def SlowPeriod(self):
return self._slow_period.Value
@SlowPeriod.setter
def SlowPeriod(self, value):
self._slow_period.Value = value
def OnReseted(self):
super(smart_forex_system_strategy, self).OnReseted()
self._was_bullish_alignment = False
self._has_prev_alignment = False
def OnStarted2(self, time):
super(smart_forex_system_strategy, self).OnStarted2(time)
self._was_bullish_alignment = False
self._has_prev_alignment = False
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
mid = ExponentialMovingAverage()
mid.Length = self.MidPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, mid, slow, self._process_candle).Start()
def _process_candle(self, candle, fast_value, mid_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
mid_val = float(mid_value)
slow_val = float(slow_value)
bullish_alignment = fast_val > mid_val and mid_val > slow_val
bearish_alignment = fast_val < mid_val and mid_val < slow_val
crossed_up = bullish_alignment and (not self._has_prev_alignment or not self._was_bullish_alignment)
crossed_down = bearish_alignment and (not self._has_prev_alignment or self._was_bullish_alignment)
if crossed_up and self.Position <= 0:
self.BuyMarket()
elif crossed_down and self.Position >= 0:
self.SellMarket()
if bullish_alignment or bearish_alignment:
self._was_bullish_alignment = bullish_alignment
self._has_prev_alignment = True
def CreateClone(self):
return smart_forex_system_strategy()