需要ベクトルへの距離戦略
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()