Distance to Demand Vector 策略
该策略基于 Distance to Demand Vector 指标。它比较多空需求向量的距离,并在其交叉时交易。
细节
- 入场条件:
- 多头:到多头向量的距离 > 到空头向量的距离
- 空头:到多头向量的距离 < 到空头向量的距离
- 方向:多空双向
- 出场条件:
- 相反信号
- 止损:无
- 默认值:
Length= 100CandleType= TimeSpan.FromMinutes(1).TimeFrame()
- 筛选:
- 类型:趋势
- 方向:双向
- 指标:Highest, Lowest
- 止损:否
- 复杂度:基础
- 时间框架:短期
- 季节性:无
- 神经网络:无
- 背离:无
- 风险等级:中
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>
/// Distance to demand vector strategy.
/// The long vector is the lowest low and the short vector the highest high of the last Length candles.
/// When the distance from the close to the long vector rises above the distance to the short vector the strategy goes long,
/// and when it falls below it goes short, reversing an opposite position.
/// </summary>
public class DistanceToDemandVectorStrategy : Strategy
{
private readonly StrategyParam<int> _length;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevDiff;
/// <summary>
/// Candles that define the demand vectors.
/// </summary>
public int Length
{
get => _length.Value;
set => _length.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public DistanceToDemandVectorStrategy()
{
_length = Param(nameof(Length), 100)
.SetGreaterThanZero()
.SetDisplay("Length", "Candles that define the demand vectors", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevDiff = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevDiff = null;
var highest = new Highest { Length = Length };
var lowest = new Lowest { Length = Length };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(highest, lowest, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, highest);
DrawIndicator(area, lowest);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue highestValue, IIndicatorValue lowestValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!highestValue.IsFormed || !lowestValue.IsFormed)
return;
var close = candle.ClosePrice;
var distanceToLong = close - lowestValue.GetValue<decimal>();
var distanceToShort = highestValue.GetValue<decimal>() - close;
var diff = distanceToLong - distanceToShort;
var prev = _prevDiff;
_prevDiff = diff;
if (prev is not decimal prevDiff)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (prevDiff <= 0m && diff > 0m && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (prevDiff >= 0m && diff < 0m && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class distance_to_demand_vector_strategy(Strategy):
"""
Distance to demand vector strategy.
The long vector is the lowest low and the short vector the highest high of the last Length candles.
When the distance from the close to the long vector rises above the distance to the short vector the strategy goes long,
and when it falls below it goes short, reversing an opposite position.
"""
def __init__(self):
super(distance_to_demand_vector_strategy, self).__init__()
self._length = self.Param("Length", 100) \
.SetGreaterThanZero() \
.SetDisplay("Length", "Candles that define the demand vectors", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_diff = None
@property
def candle_type(self):
return self._candle_type.Value
def GetWorkingSecurities(self):
return [(self.Security, self.candle_type)]
def OnReseted(self):
super(distance_to_demand_vector_strategy, self).OnReseted()
self._prev_diff = None
def OnStarted2(self, time):
super(distance_to_demand_vector_strategy, self).OnStarted2(time)
self._prev_diff = None
highest = Highest()
highest.Length = self._length.Value
lowest = Lowest()
lowest.Length = self._length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(highest, lowest, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, highest)
self.DrawIndicator(area, lowest)
self.DrawOwnTrades(area)
def _process_candle(self, candle, highest_value, lowest_value):
if candle.State != CandleStates.Finished:
return
if not highest_value.IsFormed or not lowest_value.IsFormed:
return
close = candle.ClosePrice
distance_to_long = close - lowest_value.GetValue[Decimal](None)
distance_to_short = highest_value.GetValue[Decimal](None) - close
diff = distance_to_long - distance_to_short
prev = self._prev_diff
self._prev_diff = diff
if prev is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
zero = Decimal(0)
if prev <= zero and diff > zero and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif prev >= zero and diff < zero and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
def CreateClone(self):
return distance_to_demand_vector_strategy()