Эта стратегия повторяет эксперта MetaTrader 5 XIT_THREE_MA_CROSS.mq5 на платформе StockSharp. Алгоритм синхронизирует три скользящих средних, проверяет расхождение линий MACD и рассчитывает объём сделки на основе ATR. Получается трендовая методика с подтверждением импульса, рассчитанная на среднесрочные движения ликвидных валютных пар или индексов.
Общие сведения
Тип рынка: Наиболее эффективна на инструментах, которые формируют устойчивые движения в рамках выбранного таймфрейма.
Используемые индикаторы:
Медленная, промежуточная и быстрая скользящие средние (тип выбирается пользователем) на основном таймфрейме.
MACD (на EMA) для оценки направления импульса и разницы между линией и сигналом.
Два индикатора ATR одинаковой длины на независимых таймфреймах для вычисления стоп-лосса и тейк-профита.
Направление торгов: Двусторонняя торговля, возможны длинные и короткие позиции.
Размер позиции: Рассчитывается из заданного процента риска и дистанции стопа по ATR. Если у инструмента нет полной информации о тиках, стратегия возвращается к стандартному значению Volume.
Логика торговли
Вход в покупку
Длинная позиция открывается на закрытой свече, когда одновременно выполняются условия:
Значение MACD растёт относительно предыдущей свечи (MACD[t] > MACD[t-1]).
Сигнальная линия MACD также растёт.
Разница между MACD и сигналом превышает MacdTriggerPoints * PriceStep.
Промежуточная скользящая средняя увеличилась по сравнению с прошлым значением.
Быстрая скользящая средняя увеличилась.
Промежуточная средняя находится выше медленной.
Быстрая средняя выше промежуточной.
Оба значения ATR доступны для расчёта стопа и цели.
Вход в продажу
Короткий вход является зеркальным отражением длинного сценария:
Линия MACD уменьшается относительно прошлой свечи.
Сигнальная линия MACD уменьшается.
Сигнальная линия превышает MACD минимум на MacdTriggerPoints * PriceStep.
Промежуточная средняя снижается относительно предыдущего значения.
Быстрая средняя снижается.
Промежуточная средняя ниже медленной.
Быстрая средняя ниже промежуточной.
ATR на обоих таймфреймах сформированы.
Выход
Длинная позиция закрывается при пересечении: быстрая средняя уходит ниже промежуточной, либо цена достигает ATR-стопа/тейк-профита.
Короткая позиция закрывается, когда быстрая средняя поднимается выше промежуточной, либо при касании ценой уровней ATR.
После фиксации позиции стратегия дожидается следующей свечи, что повторяет поведение исходного советника.
Управление рисками
Стоп-лосс: Дистанция равна значению ATR с таймфрейма AtrStopCandleType. Для покупок стоп = Entry - ATR, для продаж = Entry + ATR.
Тейк-профит: Расстояние равно ATR с таймфрейма AtrTakeCandleType, уровни зеркально расположены относительно цены входа.
Процент риска: Денежная потеря на единицу позиции оценивается по расстоянию до стопа. Если заданы PriceStep и PriceStepCost, используется стоимость тика. Иначе применяется чистая ценовая дистанция. Размер позиции = RiskPercent% от текущей стоимости портфеля, делённые на риск на единицу и округлённые вниз до шага объёма.
Параметры
Параметр
Описание
Значение по умолчанию
CandleType
Таймфрейм, на котором рассчитываются скользящие средние и MACD.
Типы средних (Simple, Exponential, Smoothed, Weighted).
Simple
MacdFastLength, MacdSlowLength, MacdSignalLength
Быстрый, медленный и сигнальный периоды MACD.
12 / 26 / 9
MacdTriggerPoints
Минимальная дистанция между MACD и сигналом в пунктах инструмента. Конвертируется через PriceStep.
7
AtrLength
Период обоих ATR.
14
AtrTakeCandleType / AtrStopCandleType
Таймфреймы ATR для тейк-профита и стоп-лосса.
Свечи 4 часа
RiskPercent
Доля портфеля, которую допускается потерять в одной сделке.
10%
Рекомендации по использованию
Подключайте стратегию к инструментам с корректными параметрами PriceStep, PriceStepCost и VolumeStep, чтобы позиционирование рассчитывалось точно.
Загрузите историю для всех таймфреймов подписки (CandleType, AtrTakeCandleType, AtrStopCandleType). При отсутствии ATR входы откладываются.
Алгоритм работает по закрытым свечам и игнорирует внутрисвечные колебания, аналогично исходному советнику, который считывает текущие и предыдущие буферы индикаторов.
При необходимости адаптируйте типы скользящих средних под специфику торгуемого рынка.
Файлы
CS/XitThreeMaCrossStrategy.cs – C#-реализация на высокоуровневом API StockSharp с подписками ATR и управлением риском.
README.md – английская версия описания.
README_zh.md – китайский перевод документации.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Triple MA alignment strategy.
/// </summary>
public class XitThreeMaCrossStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _midPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevFast;
private decimal? _prevMid;
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 XitThreeMaCrossStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 5)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast MA period", "Indicators");
_midPeriod = Param(nameof(MidPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Mid Period", "Medium MA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow MA (trend filter)", "Indicators");
Volume = 0.1m;
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevMid = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null;
_prevMid = null;
var fast = new SimpleMovingAverage { Length = FastPeriod };
var mid = new SimpleMovingAverage { Length = MidPeriod };
var slow = new SimpleMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, mid, slow, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, mid);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal midVal, decimal slowVal)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevFast == null || _prevMid == null)
{
_prevFast = fastVal;
_prevMid = midVal;
return;
}
var buySignal = fastVal > midVal && midVal > slowVal;
var sellSignal = fastVal < midVal && midVal < slowVal;
if (buySignal && Position <= 0)
{
if (Position < 0)
BuyMarket(Math.Abs(Position));
BuyMarket(Volume);
}
else if (sellSignal && Position >= 0)
{
if (Position > 0)
SellMarket(Position);
SellMarket(Volume);
}
_prevFast = fastVal;
_prevMid = midVal;
}
}
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class xit_three_ma_cross_strategy(Strategy):
def __init__(self):
super(xit_three_ma_cross_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 5) \
.SetDisplay("Fast Period", "Fast MA period", "Indicators")
self._mid_period = self.Param("MidPeriod", 20) \
.SetDisplay("Mid Period", "Medium MA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow MA (trend filter)", "Indicators")
self._prev_fast = None
self._prev_mid = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def MidPeriod(self):
return self._mid_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(xit_three_ma_cross_strategy, self).OnReseted()
self._prev_fast = None
self._prev_mid = None
def OnStarted2(self, time):
super(xit_three_ma_cross_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_mid = None
fast = SimpleMovingAverage()
fast.Length = self.FastPeriod
mid = SimpleMovingAverage()
mid.Length = self.MidPeriod
slow = SimpleMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, mid, slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, mid)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, mid_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
mv = float(mid_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_mid is None:
self._prev_fast = fv
self._prev_mid = mv
return
buy_signal = fv > mv and mv > sv
sell_signal = fv < mv and mv < sv
if buy_signal and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif sell_signal and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_fast = fv
self._prev_mid = mv
def CreateClone(self):
return xit_three_ma_cross_strategy()