Waindrops Makit0
Simplified strategy that compares VWAP of two halves of a custom period.
Details
- Entry Criteria: Right-half VWAP vs left-half VWAP.
- Long/Short: Both directions.
- Exit Criteria: Opposite signal.
- Stops: No.
- Default Values:
PeriodMinutes= 60CandleType= TimeSpan.FromMinutes(1)
- Filters:
- Category: Volume
- Direction: Both
- Indicators: VWAP
- Stops: No
- Complexity: Basic
- Timeframe: Intraday (1m)
- Seasonality: No
- Neural Networks: No
- Divergence: No
- Risk Level: Low
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Simplified Waindrops strategy comparing VWAP of two period halves.
/// </summary>
public class WaindropsMakit0Strategy : Strategy
{
private readonly StrategyParam<int> _periodMinutes;
private readonly StrategyParam<DataType> _candleType;
private VolumeWeightedMovingAverage _leftVwap;
private VolumeWeightedMovingAverage _rightVwap;
private int _counter;
private decimal _leftValue;
private decimal _rightValue;
public int PeriodMinutes { get => _periodMinutes.Value; set => _periodMinutes.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public WaindropsMakit0Strategy()
{
_periodMinutes = Param(nameof(PeriodMinutes), 120)
.SetDisplay("Period", "Full period in candles", "General")
.SetOptimize(30, 120, 30);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle type", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_leftVwap = null;
_rightVwap = null;
_counter = 0;
_leftValue = 0m;
_rightValue = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_leftVwap = new VolumeWeightedMovingAverage();
_rightVwap = new VolumeWeightedMovingAverage();
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var half = PeriodMinutes / 2;
if (_counter < half)
{
var res = _leftVwap.Process(candle);
if (res.IsEmpty)
return;
_leftValue = res.ToDecimal();
}
else
{
var res = _rightVwap.Process(candle);
if (res.IsEmpty)
return;
_rightValue = res.ToDecimal();
}
_counter++;
if (_counter == half)
{
_rightVwap.Reset();
}
else if (_counter >= PeriodMinutes)
{
_counter = 0;
_leftVwap.Reset();
_rightVwap.Reset();
if (_rightValue > _leftValue && Position <= 0)
BuyMarket();
else if (_rightValue < _leftValue && Position >= 0)
SellMarket();
}
}
}
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, CandleIndicatorValue
from StockSharp.Algo.Strategies import Strategy
class waindrops_makit0_strategy(Strategy):
def __init__(self):
super(waindrops_makit0_strategy, self).__init__()
self._period_minutes = self.Param("PeriodMinutes", 120) \
.SetDisplay("Period", "Full period in candles", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candle type", "General")
self._left_vwap = None
self._right_vwap = None
self._counter = 0
self._left_value = 0.0
self._right_value = 0.0
@property
def period_minutes(self):
return self._period_minutes.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(waindrops_makit0_strategy, self).OnReseted()
self._left_vwap = None
self._right_vwap = None
self._counter = 0
self._left_value = 0.0
self._right_value = 0.0
def OnStarted2(self, time):
super(waindrops_makit0_strategy, self).OnStarted2(time)
self._left_vwap = VolumeWeightedMovingAverage()
self._right_vwap = VolumeWeightedMovingAverage()
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle):
if candle.State != CandleStates.Finished:
return
half = self.period_minutes / 2
if self._counter < half:
res = self._left_vwap.Process(CandleIndicatorValue(self._left_vwap, candle))
if res.IsEmpty:
return
self._left_value = float(res)
else:
res = self._right_vwap.Process(CandleIndicatorValue(self._right_vwap, candle))
if res.IsEmpty:
return
self._right_value = float(res)
self._counter += 1
if self._counter == half:
self._right_vwap.Reset()
elif self._counter >= self.period_minutes:
self._counter = 0
self._left_vwap.Reset()
self._right_vwap.Reset()
if self._right_value > self._left_value and self.Position <= 0:
self.BuyMarket()
elif self._right_value < self._left_value and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return waindrops_makit0_strategy()