20/200 Expert AutoLot Strategy
This strategy opens at most one position per day at a user-defined hour. It compares the open price of two past bars (T1 and T2). If the earlier bar is higher than the later one by DeltaShort pips, it opens a short position. If the later bar is higher by DeltaLong pips, it opens a long position.
Position volume can be fixed or calculated automatically from account balance. When the balance decreases compared to the previous trade, the lot is multiplied by BigLotSize.
Each trade uses its own take-profit and stop-loss in pips. Additionally, a maximum holding time (MaxOpenTime) closes the trade after the specified number of hours.
Parameters
CandleType– timeframe of processed candles (default 1 hour).TradeHour– hour of the day when entry conditions are checked.T1,T2– bar shifts for comparing open prices.DeltaLong,DeltaShort– minimal open price difference in pips.TakeProfitLong,StopLossLong– protection for long trades in pips.TakeProfitShort,StopLossShort– protection for short trades in pips.Lot– base trading volume.AutoLot– enable automatic lot calculation.BigLotSize– multiplier applied after loss.MaxOpenTime– maximum time in hours to keep a position.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// "20/200 expert v4.2 AntS" strategy.
/// Opens trades based on the difference between two past open prices.
/// Closes positions by stop-loss, take-profit or time.
/// </summary>
public class Twenty200ExpertAutoLotStrategy : Strategy
{
private readonly StrategyParam<int> _takeProfitLong;
private readonly StrategyParam<int> _stopLossLong;
private readonly StrategyParam<int> _takeProfitShort;
private readonly StrategyParam<int> _stopLossShort;
private readonly StrategyParam<int> _t1;
private readonly StrategyParam<int> _t2;
private readonly StrategyParam<int> _deltaLong;
private readonly StrategyParam<int> _deltaShort;
private readonly StrategyParam<DataType> _candleType;
private readonly List<decimal> _opens = new();
private decimal _stopPrice;
private decimal _takePrice;
private DateTimeOffset _entryTime;
private bool _isLong;
public int TakeProfitLong { get => _takeProfitLong.Value; set => _takeProfitLong.Value = value; }
public int StopLossLong { get => _stopLossLong.Value; set => _stopLossLong.Value = value; }
public int TakeProfitShort { get => _takeProfitShort.Value; set => _takeProfitShort.Value = value; }
public int StopLossShort { get => _stopLossShort.Value; set => _stopLossShort.Value = value; }
public int T1 { get => _t1.Value; set => _t1.Value = value; }
public int T2 { get => _t2.Value; set => _t2.Value = value; }
public int DeltaLong { get => _deltaLong.Value; set => _deltaLong.Value = value; }
public int DeltaShort { get => _deltaShort.Value; set => _deltaShort.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public Twenty200ExpertAutoLotStrategy()
{
_takeProfitLong = Param(nameof(TakeProfitLong), 39)
.SetDisplay("TP Long (pips)", "Take profit for long", "Risk");
_stopLossLong = Param(nameof(StopLossLong), 147)
.SetDisplay("SL Long (pips)", "Stop loss for long", "Risk");
_takeProfitShort = Param(nameof(TakeProfitShort), 32)
.SetDisplay("TP Short (pips)", "Take profit for short", "Risk");
_stopLossShort = Param(nameof(StopLossShort), 267)
.SetDisplay("SL Short (pips)", "Stop loss for short", "Risk");
_t1 = Param(nameof(T1), 6)
.SetDisplay("T1", "First bar shift", "Logic");
_t2 = Param(nameof(T2), 2)
.SetDisplay("T2", "Second bar shift", "Logic");
_deltaLong = Param(nameof(DeltaLong), 1)
.SetDisplay("Delta Long", "Min rise in pips", "Logic");
_deltaShort = Param(nameof(DeltaShort), 1)
.SetDisplay("Delta Short", "Min fall in pips", "Logic");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Time frame", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_opens.Clear();
_stopPrice = 0m;
_takePrice = 0m;
_entryTime = default;
_isLong = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_opens.Clear();
_stopPrice = 0m;
_takePrice = 0m;
_entryTime = default;
_isLong = false;
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;
_opens.Add(candle.OpenPrice);
var maxShift = Math.Max(T1, T2);
if (_opens.Count <= maxShift)
return;
var pip = Security?.PriceStep ?? 1m;
var openT1 = _opens[_opens.Count - 1 - T1];
var openT2 = _opens[_opens.Count - 1 - T2];
// Position management: check SL/TP
if (Position != 0)
{
if (_isLong)
{
if (candle.LowPrice <= _stopPrice || candle.HighPrice >= _takePrice)
{
SellMarket();
return;
}
}
else
{
if (candle.HighPrice >= _stopPrice || candle.LowPrice <= _takePrice)
{
BuyMarket();
return;
}
}
return;
}
// Entry logic
var diffShort = openT1 - openT2;
var diffLong = openT2 - openT1;
if (diffShort > DeltaShort * pip && Position >= 0)
{
SellMarket();
_isLong = false;
_entryTime = candle.OpenTime;
_stopPrice = candle.OpenPrice + StopLossShort * pip;
_takePrice = candle.OpenPrice - TakeProfitShort * pip;
}
else if (diffLong > DeltaLong * pip && Position <= 0)
{
BuyMarket();
_isLong = true;
_entryTime = candle.OpenTime;
_stopPrice = candle.OpenPrice - StopLossLong * pip;
_takePrice = candle.OpenPrice + TakeProfitLong * pip;
}
}
}
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 twenty_200_expert_auto_lot_strategy(Strategy):
"""Open price difference between two bar offsets with SL/TP management."""
def __init__(self):
super(twenty_200_expert_auto_lot_strategy, self).__init__()
self._tp_long = self.Param("TakeProfitLong", 39).SetDisplay("TP Long", "TP for long", "Risk")
self._sl_long = self.Param("StopLossLong", 147).SetDisplay("SL Long", "SL for long", "Risk")
self._tp_short = self.Param("TakeProfitShort", 32).SetDisplay("TP Short", "TP for short", "Risk")
self._sl_short = self.Param("StopLossShort", 267).SetDisplay("SL Short", "SL for short", "Risk")
self._t1 = self.Param("T1", 6).SetDisplay("T1", "First bar shift", "Logic")
self._t2 = self.Param("T2", 2).SetDisplay("T2", "Second bar shift", "Logic")
self._delta_long = self.Param("DeltaLong", 1).SetDisplay("Delta Long", "Min rise", "Logic")
self._delta_short = self.Param("DeltaShort", 1).SetDisplay("Delta Short", "Min fall", "Logic")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).SetDisplay("Candle Type", "Timeframe", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(twenty_200_expert_auto_lot_strategy, self).OnReseted()
self._opens = []
self._stop_price = 0
self._take_price = 0
self._is_long = False
def OnStarted2(self, time):
super(twenty_200_expert_auto_lot_strategy, self).OnStarted2(time)
self._opens = []
self._stop_price = 0
self._take_price = 0
self._is_long = False
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawOwnTrades(area)
def OnProcess(self, candle):
if candle.State != CandleStates.Finished:
return
self._opens.append(float(candle.OpenPrice))
close = float(candle.ClosePrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
pip = 1.0
max_shift = max(self._t1.Value, self._t2.Value)
if len(self._opens) <= max_shift:
return
# SL/TP check
if self.Position != 0:
if self._is_long:
if low <= self._stop_price or high >= self._take_price:
self.SellMarket()
self._stop_price = 0
self._take_price = 0
return
else:
if high >= self._stop_price or low <= self._take_price:
self.BuyMarket()
self._stop_price = 0
self._take_price = 0
return
return
open_t1 = self._opens[len(self._opens) - 1 - self._t1.Value]
open_t2 = self._opens[len(self._opens) - 1 - self._t2.Value]
diff_short = open_t1 - open_t2
diff_long = open_t2 - open_t1
if diff_short > self._delta_short.Value * pip and self.Position >= 0:
self.SellMarket()
self._is_long = False
self._stop_price = float(candle.OpenPrice) + self._sl_short.Value * pip
self._take_price = float(candle.OpenPrice) - self._tp_short.Value * pip
elif diff_long > self._delta_long.Value * pip and self.Position <= 0:
self.BuyMarket()
self._is_long = True
self._stop_price = float(candle.OpenPrice) - self._sl_long.Value * pip
self._take_price = float(candle.OpenPrice) + self._tp_long.Value * pip
def CreateClone(self):
return twenty_200_expert_auto_lot_strategy()