Стратегия MACD Volume XAUUSD
Стратегия для XAUUSD на 15‑минутных свечах сочетает пересечение MACD через нулевую линию с фильтром по объёмам и фиксированными уровнями риска.
Подробности
- Критерии входа: MACD пересекает ноль при положительном осцилляторе объёмов и сравнении объёма.
- Длинные/Короткие: Оба направления.
- Критерии выхода: Уровни стоп-лосса или тейк-профита.
- Стопы: Фиксированный стоп-лосс и множитель тейк-профита.
- Значения по умолчанию:
ShortLength= 5LongLength= 8FastLength= 16SlowLength= 26SignalLength= 9Leverage= 1.0StopLoss= 10100TakeProfitMultiplier= 1.1CandleType= TimeSpan.FromMinutes(15)
- Фильтры:
- Категория: Trend Following
- Направление: Оба
- Индикаторы: MACD, EMA, Объём
- Стопы: Да
- Сложность: Базовая
- Таймфрейм: Внутридневной (15м)
- Сезонность: Нет
- Нейросети: Нет
- Дивергенция: Нет
- Уровень риска: Средний
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class MacdVolumeXauusdStrategy : Strategy
{
private readonly StrategyParam<int> _shortLength;
private readonly StrategyParam<int> _longLength;
private readonly StrategyParam<int> _cooldownBars;
private readonly StrategyParam<DataType> _candleType;
private ExponentialMovingAverage _shortVolumeEma;
private ExponentialMovingAverage _longVolumeEma;
private MovingAverageConvergenceDivergence _macd;
private decimal _prevMacd;
private bool _prevMacdSet;
private int _barsFromSignal;
public int ShortLength { get => _shortLength.Value; set => _shortLength.Value = value; }
public int LongLength { get => _longLength.Value; set => _longLength.Value = value; }
public int CooldownBars { get => _cooldownBars.Value; set => _cooldownBars.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MacdVolumeXauusdStrategy()
{
_shortLength = Param(nameof(ShortLength), 5);
_longLength = Param(nameof(LongLength), 10);
_cooldownBars = Param(nameof(CooldownBars), 2);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame());
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_shortVolumeEma = null;
_longVolumeEma = null;
_macd = null;
_prevMacd = 0m;
_prevMacdSet = false;
_barsFromSignal = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_shortVolumeEma = new ExponentialMovingAverage { Length = ShortLength };
_longVolumeEma = new ExponentialMovingAverage { Length = LongLength };
_macd = new MovingAverageConvergenceDivergence();
_prevMacd = 0;
_prevMacdSet = false;
_barsFromSignal = 0;
var dummyEma1 = new ExponentialMovingAverage { Length = 10 };
var dummyEma2 = new ExponentialMovingAverage { Length = 20 };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(dummyEma1, dummyEma2, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal d1, decimal d2)
{
if (candle.State != CandleStates.Finished)
return;
var t = candle.ServerTime;
_shortVolumeEma.Process(new DecimalIndicatorValue(_shortVolumeEma, candle.TotalVolume, t));
_longVolumeEma.Process(new DecimalIndicatorValue(_longVolumeEma, candle.TotalVolume, t));
var macdResult = _macd.Process(new CandleIndicatorValue(_macd, candle));
if (!_macd.IsFormed)
return;
var macd = macdResult.IsEmpty ? 0m : macdResult.GetValue<decimal>();
if (!_prevMacdSet)
{
_prevMacd = macd;
_prevMacdSet = true;
return;
}
// MACD cross above zero = buy
var longSignal = _prevMacd <= 0 && macd > 0;
// MACD cross below zero = sell
var shortSignal = _prevMacd >= 0 && macd < 0;
if (_barsFromSignal < 10000) _barsFromSignal++;
var canSignal = _barsFromSignal >= CooldownBars;
if (canSignal && longSignal && Position <= 0)
{
BuyMarket();
_barsFromSignal = 0;
}
else if (canSignal && shortSignal && Position >= 0)
{
SellMarket();
_barsFromSignal = 0;
}
_prevMacd = macd;
}
}
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, MovingAverageConvergenceDivergence,
CandleIndicatorValue,
)
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class macd_volume_xauusd_strategy(Strategy):
def __init__(self):
super(macd_volume_xauusd_strategy, self).__init__()
self._short_length = self.Param("ShortLength", 5)
self._long_length = self.Param("LongLength", 10)
self._cooldown_bars = self.Param("CooldownBars", 2)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._prev_macd = 0.0
self._prev_macd_set = False
self._bars_from_signal = 0
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(macd_volume_xauusd_strategy, self).OnReseted()
self._prev_macd = 0.0
self._prev_macd_set = False
self._bars_from_signal = 0
def OnStarted2(self, time):
super(macd_volume_xauusd_strategy, self).OnStarted2(time)
self._short_vol_ema = ExponentialMovingAverage()
self._short_vol_ema.Length = self._short_length.Value
self._long_vol_ema = ExponentialMovingAverage()
self._long_vol_ema.Length = self._long_length.Value
self._macd = MovingAverageConvergenceDivergence()
self._prev_macd = 0.0
self._prev_macd_set = False
self._bars_from_signal = 0
dummy1 = ExponentialMovingAverage()
dummy1.Length = 10
dummy2 = ExponentialMovingAverage()
dummy2.Length = 20
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(dummy1, dummy2, self._process_candle).Start()
def _process_candle(self, candle, d1, d2):
if candle.State != CandleStates.Finished:
return
t = candle.ServerTime
process_float(self._short_vol_ema, candle.TotalVolume, t, True)
process_float(self._long_vol_ema, candle.TotalVolume, t, True)
macd_result = self._macd.Process(CandleIndicatorValue(self._macd, candle))
if not self._macd.IsFormed:
return
macd_val = 0.0 if macd_result.IsEmpty else float(macd_result)
if not self._prev_macd_set:
self._prev_macd = macd_val
self._prev_macd_set = True
return
long_signal = self._prev_macd <= 0 and macd_val > 0
short_signal = self._prev_macd >= 0 and macd_val < 0
if self._bars_from_signal < 10000:
self._bars_from_signal += 1
can_signal = self._bars_from_signal >= self._cooldown_bars.Value
if can_signal and long_signal and self.Position <= 0:
self.BuyMarket()
self._bars_from_signal = 0
elif can_signal and short_signal and self.Position >= 0:
self.SellMarket()
self._bars_from_signal = 0
self._prev_macd = macd_val
def CreateClone(self):
return macd_volume_xauusd_strategy()