The VR BUCH Moving Average Strategy is a direct port of the MetaTrader expert advisor VR---BUCH. It trades trend reversals using two configurable moving averages and a candle price filter. The StockSharp version keeps the original signal flow: the strategy closes open positions when an opposite setup appears and only opens a new position after the previous exposure is fully closed.
The implementation relies on StockSharp's high-level candle subscriptions, native moving average indicators and real-time order helpers. All indicator values are processed on finished candles and the strategy avoids manual historical buffers except for a small ring buffer that reproduces the MetaTrader shift parameters.
Trading Logic
Indicator calculation
A fast moving average and a slow moving average are computed on the selected candle type.
Each moving average can use a different price source and smoothing method (simple, exponential, smoothed, weighted).
Optional horizontal shifts reproduce the MetaTrader ma_shift parameter by referencing values from past candles.
Signal detection
A buy setup occurs when the shifted fast MA is above the shifted slow MA and the selected confirmation price is above the fast MA.
A sell setup occurs when the shifted fast MA is below the shifted slow MA and the confirmation price is below the fast MA.
Position handling
If a position is already open, an opposite signal triggers a flat close first. New entries are evaluated on subsequent signals only when the net position returns to zero.
When no position exists, the strategy submits a market order with the configured volume in the direction of the active signal.
No stop-loss or take-profit levels are included by default. Users can combine the strategy with StockSharp protective blocks (StartProtection) or external risk managers if required.
Parameters
Parameter
Description
Fast Period
Length of the fast moving average.
Fast Shift
Number of candles used to shift the fast MA value into the past.
Fast Price
Candle price component used for the fast MA (close, open, high, low, median, typical, weighted).
Fast Method
Smoothing method for the fast MA (simple, exponential, smoothed, weighted).
Slow Period
Length of the slow moving average.
Slow Shift
Number of candles used to shift the slow MA value.
Slow Price
Candle price component for the slow MA.
Slow Method
Smoothing method for the slow MA.
Signal Price
Candle price used to confirm the entry (defaults to close).
Candle Type
Timeframe or custom candle type used for calculations.
Volume
Order volume for new trades.
Usage Notes
Signals are evaluated only on finished candles to avoid intra-bar noise.
The strategy expects the trading connector to provide sufficient historical data to warm up both moving averages and their shift buffers.
Weighted price uses the formula ((High + Low + 2 * Close) / 4), matching the MetaTrader PRICE_WEIGHTED option.
The class name and namespace follow the StockSharp project conventions, enabling seamless compilation inside the AlgoTrading solution.
How to Run
Place the strategy into a StockSharp strategy container or sample runner.
Configure the desired security, timeframe (Candle Type) and order volume.
Adjust moving average settings to match the original MetaTrader template if necessary.
Start the strategy. It will subscribe to candles, draw indicators on charts (if available) and place market orders based on the described logic.
For portfolio or multiple-symbol usage, duplicate the strategy instance per instrument and assign dedicated securities.
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()