Vela Volume Weighted MA
Esta estrategia construye medias móviles ponderadas por volumen (VWMA) para los precios de apertura y cierre de las velas. La posición relativa de estas VWMA define un "color" de vela.
Lógica de Trading
- Una vela es alcista cuando VWMA(apertura) está por debajo de VWMA(cierre).
- Una vela es bajista cuando VWMA(apertura) está por encima de VWMA(cierre).
- Cuando la vela anterior es alcista y la actual se vuelve neutral o bajista, la estrategia abre una posición larga y cierra cualquier posición corta.
- Cuando la vela anterior es bajista y la actual se vuelve neutral o alcista, la estrategia abre una posición corta y cierra cualquier posición larga.
Parámetros
VWMA Period– longitud utilizada para calcular ambas medias móviles ponderadas por volumen.Candle Type– marco temporal de las velas utilizadas para los cálculos.
Un bloque de protección está habilitado por defecto: take‑profit del 2% y stop‑loss del 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()