DeMarker Sign 策略
该策略使用 DeMarker 振荡指标来捕捉可能的趋势反转。默认情况下在每根完成的 4 小时蜡烛上计算 DeMarker 值,并与可配置的上限和下限比较。当指标上穿下限(默认 0.3)时,策略开多并平掉空单;当指标下穿上限(默认 0.7)时,策略开空并平掉多单。仓位将保持到出现相反信号为止。
细节
- 入场条件:
- 多头:DeMarker 从下向上穿越下限。
- 空头:DeMarker 从上向下穿越上限。
- 多空方向:双向。
- 出场条件:出现相反信号。
- 止损:默认无。
- 过滤器:无。
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>
/// Strategy based on DeMarker oscillator crossing predefined levels.
/// </summary>
public class DeMarkerSignStrategy : Strategy
{
private readonly StrategyParam<int> _deMarkerPeriod;
private readonly StrategyParam<decimal> _upLevel;
private readonly StrategyParam<decimal> _downLevel;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevDeMarker;
public int DeMarkerPeriod { get => _deMarkerPeriod.Value; set => _deMarkerPeriod.Value = value; }
public decimal UpLevel { get => _upLevel.Value; set => _upLevel.Value = value; }
public decimal DownLevel { get => _downLevel.Value; set => _downLevel.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public DeMarkerSignStrategy()
{
_deMarkerPeriod = Param(nameof(DeMarkerPeriod), 14)
.SetDisplay("DeMarker Period", "Indicator period", "General");
_upLevel = Param(nameof(UpLevel), 0.7m)
.SetDisplay("Upper Level", "Sell when DeMarker falls below", "General");
_downLevel = Param(nameof(DownLevel), 0.3m)
.SetDisplay("Lower Level", "Buy when DeMarker rises above", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevDeMarker = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevDeMarker = null;
var deMarker = new DeMarker { Length = DeMarkerPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(deMarker, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, deMarker);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal deMarker)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_prevDeMarker is null)
{
_prevDeMarker = deMarker;
return;
}
// DeMarker crosses above lower level -> buy
if (deMarker > DownLevel && _prevDeMarker <= DownLevel && Position <= 0)
BuyMarket();
// DeMarker crosses below upper level -> sell
else if (deMarker < UpLevel && _prevDeMarker >= UpLevel && Position >= 0)
SellMarket();
_prevDeMarker = deMarker;
}
}
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 DeMarker
from StockSharp.Algo.Strategies import Strategy
class de_marker_sign_strategy(Strategy):
def __init__(self):
super(de_marker_sign_strategy, self).__init__()
self._de_marker_period = self.Param("DeMarkerPeriod", 14) \
.SetDisplay("DeMarker Period", "Indicator period", "General")
self._up_level = self.Param("UpLevel", 0.7) \
.SetDisplay("Upper Level", "Sell when DeMarker falls below", "General")
self._down_level = self.Param("DownLevel", 0.3) \
.SetDisplay("Lower Level", "Buy when DeMarker rises above", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe for candles", "General")
self._prev_de_marker = None
@property
def de_marker_period(self):
return self._de_marker_period.Value
@property
def up_level(self):
return self._up_level.Value
@property
def down_level(self):
return self._down_level.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(de_marker_sign_strategy, self).OnReseted()
self._prev_de_marker = None
def OnStarted2(self, time):
super(de_marker_sign_strategy, self).OnStarted2(time)
self._prev_de_marker = None
de_marker = DeMarker()
de_marker.Length = self.de_marker_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(de_marker, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, de_marker)
self.DrawOwnTrades(area)
def process_candle(self, candle, de_marker):
if candle.State != CandleStates.Finished:
return
de_marker = float(de_marker)
if self._prev_de_marker is None:
self._prev_de_marker = de_marker
return
down_lvl = float(self.down_level)
up_lvl = float(self.up_level)
if de_marker > down_lvl and self._prev_de_marker <= down_lvl and self.Position <= 0:
self.BuyMarket()
elif de_marker < up_lvl and self._prev_de_marker >= up_lvl and self.Position >= 0:
self.SellMarket()
self._prev_de_marker = de_marker
def CreateClone(self):
return de_marker_sign_strategy()