STLMCandle 策略
该策略根据最新完成的K线方向进行交易。 当收盘价高于开盘价时,策略开多并平空; 当收盘价低于开盘价时,策略开空并平多。 策略支持止损和止盈,并可配置K线周期。
参数
CandleType– 用于分析的K线周期。StopLoss– 以价格单位表示的绝对止损。TakeProfit– 以价格单位表示的绝对止盈。
注意
该策略是原始 MQL STLMCandle 专家的简化版本,
通过使用标准K线的开盘价和收盘价来近似原指标。
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Candle color strategy based on open-close comparison.
/// Buys when the close price is above the open price and sells on the opposite condition.
/// </summary>
public class StlmCandleStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _stopLoss;
private readonly StrategyParam<decimal> _takeProfit;
private int _barsSinceSignal;
private int _prevDirection;
/// <summary>
/// Candle type used for analysis.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Stop loss in price units.
/// </summary>
public decimal StopLoss
{
get => _stopLoss.Value;
set => _stopLoss.Value = value;
}
/// <summary>
/// Take profit in price units.
/// </summary>
public decimal TakeProfit
{
get => _takeProfit.Value;
set => _takeProfit.Value = value;
}
/// <summary>
/// Initializes a new instance of <see cref="StlmCandleStrategy"/>.
/// </summary>
public StlmCandleStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
_stopLoss = Param(nameof(StopLoss), 1000m)
.SetGreaterThanZero()
.SetDisplay("Stop Loss", "Stop loss in price units", "Risk");
_takeProfit = Param(nameof(TakeProfit), 2000m)
.SetGreaterThanZero()
.SetDisplay("Take Profit", "Take profit in price units", "Risk");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_barsSinceSignal = 2;
_prevDirection = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_barsSinceSignal = 2;
_prevDirection = 0;
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;
_barsSinceSignal++;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevDirection = GetDirection(candle);
return;
}
var direction = GetDirection(candle);
if (_barsSinceSignal >= 2 && direction == 1 && _prevDirection == 1)
{
if (Position <= 0)
{
BuyMarket();
_barsSinceSignal = 0;
}
}
else if (_barsSinceSignal >= 2 && direction == -1 && _prevDirection == -1)
{
if (Position >= 0)
{
SellMarket();
_barsSinceSignal = 0;
}
}
_prevDirection = direction;
}
private static int GetDirection(ICandleMessage candle)
{
if (candle.ClosePrice > candle.OpenPrice)
return 1;
if (candle.ClosePrice < candle.OpenPrice)
return -1;
return 0;
}
}
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.Strategies import Strategy
class stlm_candle_strategy(Strategy):
def __init__(self):
super(stlm_candle_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._stop_loss = self.Param("StopLoss", 1000.0) \
.SetDisplay("Stop Loss", "Stop loss in price units", "Risk")
self._take_profit = self.Param("TakeProfit", 2000.0) \
.SetDisplay("Take Profit", "Take profit in price units", "Risk")
self._bars_since_signal = 2
self._prev_direction = 0
@property
def candle_type(self):
return self._candle_type.Value
@property
def stop_loss(self):
return self._stop_loss.Value
@property
def take_profit(self):
return self._take_profit.Value
def OnReseted(self):
super(stlm_candle_strategy, self).OnReseted()
self._bars_since_signal = 2
self._prev_direction = 0
def OnStarted2(self, time):
super(stlm_candle_strategy, self).OnStarted2(time)
self._bars_since_signal = 2
self._prev_direction = 0
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
@staticmethod
def _get_direction(candle):
if float(candle.ClosePrice) > float(candle.OpenPrice):
return 1
if float(candle.ClosePrice) < float(candle.OpenPrice):
return -1
return 0
def process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
self._bars_since_signal += 1
direction = self._get_direction(candle)
if self._bars_since_signal >= 2 and direction == 1 and self._prev_direction == 1:
if self.Position <= 0:
self.BuyMarket()
self._bars_since_signal = 0
elif self._bars_since_signal >= 2 and direction == -1 and self._prev_direction == -1:
if self.Position >= 0:
self.SellMarket()
self._bars_since_signal = 0
self._prev_direction = direction
def CreateClone(self):
return stlm_candle_strategy()