Candle Volume Weighted MA
Esta estratégia constrói médias móvies ponderadas por volume (VWMA) para os preços de abertura e fechamento dos candles. A posição relativa dessas VWMAs define uma "cor" do candle.
Lógica de Negociação
- Um candle é altista quando VWMA(abertura) está abaixo de VWMA(fechamento).
- Um candle é baixista quando VWMA(abertura) está acima de VWMA(fechamento).
- Quando o candle anterior é altista e o atual se torna neutro ou baixista, a estratégia abre uma posição comprada e fecha qualquer posição vendida.
- Quando o candle anterior é baixista e o atual se torna neutro ou altista, a estratégia abre uma posição vendida e fecha qualquer posição comprada.
Parâmetros
VWMA Period– comprimento utilizado para calcular ambas as médias móvies ponderadas por volume.Candle Type– período dos candles utilizados para os cálculos.
Um bloco de proteção está habilitado por padrão: take‑profit de 2% e stop‑loss de 1%.
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;
/// <summary>
/// Volume Weighted MA Candle strategy.
/// Uses VWMA slope direction combined with candle direction for signals.
/// Buys when VWMA turns up and candle is bullish, sells on opposite.
/// </summary>
public class VolumeWeightedMaCandleStrategy : Strategy
{
private readonly StrategyParam<int> _vwmaPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevVwma;
private decimal? _prevColor;
public int VwmaPeriod
{
get => _vwmaPeriod.Value;
set => _vwmaPeriod.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public VolumeWeightedMaCandleStrategy()
{
_vwmaPeriod = Param(nameof(VwmaPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("VWMA Period", "Period for volume weighted moving average", "Parameters")
.SetOptimize(5, 30, 5);
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles for calculations", "Parameters");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevVwma = null;
_prevColor = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevVwma = null;
_prevColor = null;
var vwma = new VolumeWeightedMovingAverage { Length = VwmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(vwma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, vwma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal vwmaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
// Color: 2 = bullish (price above VWMA rising), 0 = bearish, 1 = neutral
var priceAbove = candle.ClosePrice > vwmaValue;
var priceBelow = candle.ClosePrice < vwmaValue;
var rising = _prevVwma != null && vwmaValue > _prevVwma.Value;
var falling = _prevVwma != null && vwmaValue < _prevVwma.Value;
decimal currentColor;
if (priceAbove && rising)
currentColor = 2m;
else if (priceBelow && falling)
currentColor = 0m;
else
currentColor = 1m;
if (_prevColor is decimal prevColor)
{
// Transition from bullish to not-bullish -> sell
if (prevColor == 2m && currentColor < 2m && Position >= 0)
SellMarket();
// Transition from bearish to not-bearish -> buy
else if (prevColor == 0m && currentColor > 0m && Position <= 0)
BuyMarket();
}
_prevColor = currentColor;
_prevVwma = vwmaValue;
}
}
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 VolumeWeightedMovingAverage
from StockSharp.Algo.Strategies import Strategy
class volume_weighted_ma_candle_strategy(Strategy):
def __init__(self):
super(volume_weighted_ma_candle_strategy, self).__init__()
self._vwma_period = self.Param("VwmaPeriod", 12) \
.SetDisplay("VWMA Period", "Period for volume weighted moving average", "Parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles for calculations", "Parameters")
self._prev_vwma = None
self._prev_color = None
@property
def vwma_period(self):
return self._vwma_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(volume_weighted_ma_candle_strategy, self).OnReseted()
self._prev_vwma = None
self._prev_color = None
def OnStarted2(self, time):
super(volume_weighted_ma_candle_strategy, self).OnStarted2(time)
self._prev_vwma = None
self._prev_color = None
vwma = VolumeWeightedMovingAverage()
vwma.Length = self.vwma_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(vwma, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, vwma)
self.DrawOwnTrades(area)
def process_candle(self, candle, vwma_value):
if candle.State != CandleStates.Finished:
return
vwma_value = float(vwma_value)
close_price = float(candle.ClosePrice)
price_above = close_price > vwma_value
price_below = close_price < vwma_value
rising = self._prev_vwma is not None and vwma_value > self._prev_vwma
falling = self._prev_vwma is not None and vwma_value < self._prev_vwma
if price_above and rising:
current_color = 2
elif price_below and falling:
current_color = 0
else:
current_color = 1
if self._prev_color is not None:
if self._prev_color == 2 and current_color < 2 and self.Position >= 0:
self.SellMarket()
elif self._prev_color == 0 and current_color > 0 and self.Position <= 0:
self.BuyMarket()
self._prev_color = current_color
self._prev_vwma = vwma_value
def CreateClone(self):
return volume_weighted_ma_candle_strategy()