Grid Tendence V1 Strategy
Grid trading strategy that reopens or reverses positions based on profit percentage steps.
It starts long and when profit reaches the specified percent it closes and reopens in the same direction. When loss reaches the percent it closes and opens in the opposite direction.
Details
- Entry Criteria: Always in market, starting long. Reopen or reverse when profit or loss reaches
Percent. - Long/Short: Both directions.
- Exit Criteria: Profit or loss threshold.
- Stops: No.
- Default Values:
Percent= 1.0CandleType= TimeSpan.FromMinutes(1)
- Filters:
- Category: Grid
- Direction: Both
- Indicators: None
- Stops: No
- Complexity: Basic
- Timeframe: Intraday (1m)
- Seasonality: No
- Neural Networks: No
- Divergence: No
- 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>
/// Grid Tendence V1 strategy.
/// Always in the market, starting long. When the open position gains Percent percent from its entry price it is closed and
/// reopened in the same direction; when it loses Percent percent it is closed and a position in the opposite direction is opened.
/// </summary>
public class GridTendenceV1Strategy : Strategy
{
private readonly StrategyParam<decimal> _percent;
private readonly StrategyParam<DataType> _candleType;
private decimal _entryPrice;
/// <summary>
/// Profit or loss percent that triggers a reopen or a reversal.
/// </summary>
public decimal Percent
{
get => _percent.Value;
set => _percent.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public GridTendenceV1Strategy()
{
_percent = Param(nameof(Percent), 1.0m)
.SetGreaterThanZero()
.SetDisplay("Percent", "Profit or loss percent that reopens or reverses the position", "Trading");
_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();
_entryPrice = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_entryPrice = 0m;
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;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
if (Position == 0)
{
// The first entry is always long.
BuyMarket(Volume);
_entryPrice = close;
return;
}
if (_entryPrice <= 0m)
{
_entryPrice = close;
return;
}
var change = (close - _entryPrice) / _entryPrice * 100m;
var profit = Position > 0 ? change : -change;
if (profit >= Percent)
{
if (Position > 0)
{
SellMarket(Position);
BuyMarket(Volume);
}
else
{
BuyMarket(-Position);
SellMarket(Volume);
}
_entryPrice = close;
}
else if (profit <= -Percent)
{
if (Position > 0)
SellMarket(Volume + Math.Abs(Position));
else
BuyMarket(Volume + Math.Abs(Position));
_entryPrice = close;
}
}
}
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
from StockSharp.Algo.Strategies import Strategy
class grid_tendence_v1_strategy(Strategy):
"""
Grid Tendence V1 strategy.
Always in the market, starting long. When the open position gains Percent percent from its entry price it is closed and
reopened in the same direction; when it loses Percent percent it is closed and a position in the opposite direction is opened.
"""
def __init__(self):
super(grid_tendence_v1_strategy, self).__init__()
self._percent = self.Param("Percent", 1.0).SetGreaterThanZero().SetDisplay("Percent", "Profit or loss percent that reopens or reverses the position", "Trading")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._entry_price = 0.0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(grid_tendence_v1_strategy, self).OnReseted()
self._entry_price = 0.0
def OnStarted2(self, time):
super(grid_tendence_v1_strategy, self).OnStarted2(time)
self._entry_price = 0.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)
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
close = float(candle.ClosePrice)
if self.Position == 0:
# The first entry is always long.
self.BuyMarket(self.Volume)
self._entry_price = close
return
if self._entry_price <= 0.0:
self._entry_price = close
return
change = (close - self._entry_price) / self._entry_price * 100.0
profit = change if self.Position > 0 else -change
percent = float(self._percent.Value)
if profit >= percent:
if self.Position > 0:
self.SellMarket(self.Position)
self.BuyMarket(self.Volume)
else:
self.BuyMarket(-self.Position)
self.SellMarket(self.Volume)
self._entry_price = close
elif profit <= -percent:
if self.Position > 0:
self.SellMarket(self.Volume + abs(self.Position))
else:
self.BuyMarket(self.Volume + abs(self.Position))
self._entry_price = close
def CreateClone(self):
return grid_tendence_v1_strategy()