Waindrops Makit0
简化策略,对比自定义周期两半的VWAP。
细节
- 入场条件:比较左右两半的VWAP。
- 多空方向:双向。
- 出场条件:相反信号。
- 止损:否。
- 默认值:
PeriodMinutes= 60CandleType= TimeSpan.FromMinutes(1)
- 筛选:
- 分类:成交量
- 方向:双向
- 指标:VWAP
- 止损:否
- 复杂度:基础
- 时间框架:日内(1m)
- 季节性:否
- 神经网络:否
- 背离:否
- 风险等级:低
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()