Стратегия VR BUCH — перенос эксперт-советника MetaTrader VR---BUCH в экосистему StockSharp. Алгоритм торгует развороты тренда, используя две настраиваемые скользящие средние и фильтрацию по цене свечи. Поведение сигналов повторяет оригинал: при появлении противоположного условия открытая позиция закрывается, и лишь после обнуления позиции рассматривается новый вход.
Реализация задействует высокоуровневые подписки на свечи, встроенные индикаторы StockSharp и вспомогательные методы для рыночных заявок. Обработка ведётся только по закрытым свечам, а для имитации параметра ma_shift из MetaTrader используется компактный кольцевой буфер, без накопления лишних исторических данных.
Логика торговли
Расчёт индикаторов
Быстрая и медленная скользящие рассчитываются на выбранном типе свечей.
Для каждой средней можно отдельно выбрать источник цены и метод сглаживания (простое, экспоненциальное, сглаженное, взвешенное).
Горизонтальные сдвиги берут значения прошлых свечей, полностью воспроизводя ma_shift.
Формирование сигналов
Сигнал на покупку появляется, когда сдвинутая быстрая средняя выше медленной и выбранная цена подтверждения расположена выше быстрой средней.
Сигнал на продажу появляется, когда сдвинутая быстрая средняя ниже медленной и цена подтверждения находится ниже быстрой средней.
Управление позицией
При наличии открытой позиции противоположный сигнал сначала закрывает текущий объём. Новый ордер возможен только после выхода в ноль.
При отсутствии позиции стратегия выставляет рыночную заявку заданного объёма по направлению активного сигнала.
Встроенные стоп-лосс и тейк-профит отсутствуют. При необходимости можно подключить StartProtection или внешний модуль управления рисками.
Параметры
Параметр
Описание
Fast Period
Период быстрой скользящей средней.
Fast Shift
Количество свечей, на которое сдвигается значение быстрой средней.
Fast Price
Тип цены для расчёта быстрой средней (close, open, high, low, median, typical, weighted).
Fast Method
Метод сглаживания быстрой средней (простая, экспоненциальная, сглаженная, взвешенная).
Slow Period
Период медленной скользящей средней.
Slow Shift
Количество свечей для сдвига медленной средней.
Slow Price
Тип цены для медленной средней.
Slow Method
Метод сглаживания медленной средней.
Signal Price
Цена свечи, используемая для подтверждения входа (по умолчанию — закрытие).
Candle Type
Таймфрейм или пользовательский тип свечей для расчётов.
Volume
Объём рыночного ордера при открытии позиции.
Особенности использования
Сигналы формируются только на завершённых свечах, чтобы избежать шума внутри бара.
Коннектор должен предоставить достаточно истории для прогрева обеих скользящих и их сдвигов.
Взвешенная цена рассчитывается как ((High + Low + 2 * Close) / 4), что соответствует параметру PRICE_WEIGHTED в MetaTrader.
Класс и пространство имён следуют стандартам StockSharp, поэтому стратегия без доработок подключается к решению AlgoTrading.
Запуск
Добавьте стратегию в контейнер или пример StockSharp.
Настройте инструмент, таймфрейм (Candle Type) и торговый объём.
При необходимости подберите параметры скользящих средних под оригинальный шаблон MetaTrader.
Запустите стратегию — она подпишется на свечи, при наличии графика отрисует индикаторы и будет отправлять рыночные приказы согласно описанным правилам.
Для многосимвольной торговли создавайте отдельный экземпляр стратегии на каждый инструмент.
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>
/// VR BUCH strategy. Uses Highest/Lowest channel breakout.
/// </summary>
public class VrBuchStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _period;
private decimal? _prevHigh;
private decimal? _prevLow;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int Period
{
get => _period.Value;
set => _period.Value = value;
}
public VrBuchStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_period = Param(nameof(Period), 14)
.SetGreaterThanZero()
.SetDisplay("Period", "Channel period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevHigh = null;
_prevLow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevHigh = null;
_prevLow = null;
var highest = new Highest { Length = Period };
var lowest = new Lowest { Length = Period };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(highest, lowest, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal high, decimal low)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) { _prevHigh = high; _prevLow = low; return; }
if (_prevHigh == null || _prevLow == null) { _prevHigh = high; _prevLow = low; return; }
var close = candle.ClosePrice;
if (close > _prevHigh.Value && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
else if (close < _prevLow.Value && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
_prevHigh = high; _prevLow = low;
}
}
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 Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class vr_buch_strategy(Strategy):
def __init__(self):
super(vr_buch_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._period = self.Param("Period", 14) \
.SetDisplay("Period", "Channel period", "Indicators")
self._prev_high = None
self._prev_low = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def Period(self):
return self._period.Value
def OnReseted(self):
super(vr_buch_strategy, self).OnReseted()
self._prev_high = None
self._prev_low = None
def OnStarted2(self, time):
super(vr_buch_strategy, self).OnStarted2(time)
self._prev_high = None
self._prev_low = None
highest = Highest()
highest.Length = self.Period
lowest = Lowest()
lowest.Length = self.Period
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(highest, lowest, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _on_process(self, candle, high_value, low_value):
if candle.State != CandleStates.Finished:
return
hv = float(high_value)
lv = float(low_value)
if self._prev_high is None or self._prev_low is None:
self._prev_high = hv
self._prev_low = lv
return
close = float(candle.ClosePrice)
if close > self._prev_high and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif close < self._prev_low and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_high = hv
self._prev_low = lv
def CreateClone(self):
return vr_buch_strategy()