Grim Slash
Grim Slash is a simple price action strategy that buys when the current candle's low tests the previous close and exits when the high reaches the previous high. Risk is managed with fixed percentage take profit and stop loss.
Details
- Data: Price candles.
- Entry Criteria:
- Long: Current low touches or dips below the previous close.
- Exit Criteria: Current high touches or exceeds the previous high.
- Stops: 15% take profit, 5% stop loss.
- Default Values:
TakeProfitPercent= 15StopLossPercent= 5
- Filters:
- Category: Reversal
- Direction: Long
- Indicators: None
- Complexity: Low
- Risk level: Medium
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Grim Slash strategy.
/// Buys when the candle's low touches or dips below the previous close and exits when the high reaches the previous high.
/// A percent take profit and stop loss manage the risk.
/// </summary>
public class GrimSlashStrategy : Strategy
{
private readonly StrategyParam<decimal> _takeProfitPercent;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevClose;
private decimal? _prevHigh;
/// <summary>
/// Take profit percent from the entry price.
/// </summary>
public decimal TakeProfitPercent
{
get => _takeProfitPercent.Value;
set => _takeProfitPercent.Value = value;
}
/// <summary>
/// Stop loss percent from the entry price.
/// </summary>
public decimal StopLossPercent
{
get => _stopLossPercent.Value;
set => _stopLossPercent.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public GrimSlashStrategy()
{
_takeProfitPercent = Param(nameof(TakeProfitPercent), 15m)
.SetNotNegative()
.SetDisplay("Take Profit %", "Take profit percent from the entry price", "Risk");
_stopLossPercent = Param(nameof(StopLossPercent), 5m)
.SetNotNegative()
.SetDisplay("Stop Loss %", "Stop loss percent from the entry price", "Risk");
_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();
_prevClose = null;
_prevHigh = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = null;
_prevHigh = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
StartProtection(
TakeProfitPercent > 0 ? new Unit(TakeProfitPercent, UnitTypes.Percent) : new Unit(),
StopLossPercent > 0 ? new Unit(StopLossPercent, UnitTypes.Percent) : new Unit(),
useMarketOrders: true);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var prevClose = _prevClose;
var prevHigh = _prevHigh;
_prevClose = candle.ClosePrice;
_prevHigh = candle.HighPrice;
if (prevClose is not decimal lastClose || prevHigh is not decimal lastHigh)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (Position > 0)
{
if (candle.HighPrice >= lastHigh)
SellMarket(Position);
}
else if (Position == 0 && candle.LowPrice <= lastClose)
{
BuyMarket(Volume);
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Strategies import Strategy
class grim_slash_strategy(Strategy):
"""
Grim Slash strategy.
Buys when the candle's low touches or dips below the previous close and exits when the high reaches the previous high.
A percent take profit and stop loss manage the risk.
"""
def __init__(self):
super(grim_slash_strategy, self).__init__()
self._take_profit_percent = self.Param("TakeProfitPercent", 15.0).SetNotNegative().SetDisplay("Take Profit %", "Take profit percent from the entry price", "Risk")
self._stop_loss_percent = self.Param("StopLossPercent", 5.0).SetNotNegative().SetDisplay("Stop Loss %", "Stop loss percent from the entry price", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_close = None
self._prev_high = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(grim_slash_strategy, self).OnReseted()
self._prev_close = None
self._prev_high = None
def OnStarted2(self, time):
super(grim_slash_strategy, self).OnStarted2(time)
self._prev_close = None
self._prev_high = None
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._process_candle).Start()
tp = float(self._take_profit_percent.Value)
sl = float(self._stop_loss_percent.Value)
self.StartProtection(
Unit(Decimal(tp), UnitTypes.Percent) if tp > 0 else Unit(),
Unit(Decimal(sl), UnitTypes.Percent) if sl > 0 else Unit(),
useMarketOrders=True)
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
prev_close = self._prev_close
prev_high = self._prev_high
self._prev_close = candle.ClosePrice
self._prev_high = candle.HighPrice
if prev_close is None or prev_high is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
if self.Position > 0:
if candle.HighPrice >= prev_high:
self.SellMarket(self.Position)
elif self.Position == 0 and candle.LowPrice <= prev_close:
self.BuyMarket(self.Volume)
def CreateClone(self):
return grim_slash_strategy()