Combo Right Strategy
Implementation of strategy converted from MQL script combo_right.mq5.
The system combines a basic CCI signal with three simple perceptrons working on price differences.
Logic
- Basic Signal – Commodity Channel Index (CCI) value. Positive values favour long trades, negative values favour short trades.
- Perceptrons – Each perceptron looks at a set of shifted closing prices and applies linear weights. The mode parameter
Passselects which perceptrons are active:1: only basic CCI signal.2: sale perceptron can override CCI and open short positions.3: buy perceptron can override CCI and open long positions.4: general perceptron supervises both buy and sale perceptrons.
If an active perceptron issues a signal, it replaces the basic CCI output. Otherwise the CCI value is used.
Parameters
TakeProfit1,StopLoss1– profit and loss targets for the basic CCI signal (in ticks).CciPeriod– lookback period of the CCI indicator.- Weights and periods for each perceptron (
x12,x22, …,p4). Pass– operation mode.Shift– bar index used for price data (0 current, 1 previous).Volume– trade volume.CandleType– candle type for calculations.
Indicators
- CCI.
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>
/// Implementation of strategy converted from MQL "Combo_Right".
/// Uses CCI indicator and three simple perceptrons to generate trade signals.
/// </summary>
public class ComboRightStrategy : Strategy
{
private readonly StrategyParam<decimal> _tp1;
private readonly StrategyParam<decimal> _sl1;
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<int> _x12;
private readonly StrategyParam<int> _x22;
private readonly StrategyParam<int> _x32;
private readonly StrategyParam<int> _x42;
private readonly StrategyParam<decimal> _tp2;
private readonly StrategyParam<decimal> _sl2;
private readonly StrategyParam<int> _p2;
private readonly StrategyParam<int> _x13;
private readonly StrategyParam<int> _x23;
private readonly StrategyParam<int> _x33;
private readonly StrategyParam<int> _x43;
private readonly StrategyParam<decimal> _tp3;
private readonly StrategyParam<decimal> _sl3;
private readonly StrategyParam<int> _p3;
private readonly StrategyParam<int> _x14;
private readonly StrategyParam<int> _x24;
private readonly StrategyParam<int> _x34;
private readonly StrategyParam<int> _x44;
private readonly StrategyParam<int> _p4;
private readonly StrategyParam<int> _pass;
private readonly StrategyParam<int> _shift;
private readonly StrategyParam<decimal> _volume;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _minCciSignal;
private readonly StrategyParam<int> _cooldownBars;
private decimal[] _closeBuffer = [];
private int _barIndex;
private int _cooldownRemaining;
private decimal _w11;
private decimal _w12;
private decimal _w13;
private decimal _w14;
private decimal _w21;
private decimal _w22;
private decimal _w23;
private decimal _w24;
private decimal _w31;
private decimal _w32;
private decimal _w33;
private decimal _w34;
private int _sh11;
private int _sh12;
private int _sh13;
private int _sh14;
private int _sh15;
private int _sh21;
private int _sh22;
private int _sh23;
private int _sh24;
private int _sh25;
private int _sh31;
private int _sh32;
private int _sh33;
private int _sh34;
private int _sh35;
private int _previousSignal;
public decimal TakeProfit1 { get => _tp1.Value; set => _tp1.Value = value; }
public decimal StopLoss1 { get => _sl1.Value; set => _sl1.Value = value; }
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public int X12 { get => _x12.Value; set => _x12.Value = value; }
public int X22 { get => _x22.Value; set => _x22.Value = value; }
public int X32 { get => _x32.Value; set => _x32.Value = value; }
public int X42 { get => _x42.Value; set => _x42.Value = value; }
public decimal TakeProfit2 { get => _tp2.Value; set => _tp2.Value = value; }
public decimal StopLoss2 { get => _sl2.Value; set => _sl2.Value = value; }
public int P2 { get => _p2.Value; set => _p2.Value = value; }
public int X13 { get => _x13.Value; set => _x13.Value = value; }
public int X23 { get => _x23.Value; set => _x23.Value = value; }
public int X33 { get => _x33.Value; set => _x33.Value = value; }
public int X43 { get => _x43.Value; set => _x43.Value = value; }
public decimal TakeProfit3 { get => _tp3.Value; set => _tp3.Value = value; }
public decimal StopLoss3 { get => _sl3.Value; set => _sl3.Value = value; }
public int P3 { get => _p3.Value; set => _p3.Value = value; }
public int X14 { get => _x14.Value; set => _x14.Value = value; }
public int X24 { get => _x24.Value; set => _x24.Value = value; }
public int X34 { get => _x34.Value; set => _x34.Value = value; }
public int X44 { get => _x44.Value; set => _x44.Value = value; }
public int P4 { get => _p4.Value; set => _p4.Value = value; }
public int Pass { get => _pass.Value; set => _pass.Value = value; }
public int Shift { get => _shift.Value; set => _shift.Value = value; }
public decimal TradeVolume { get => _volume.Value; set => _volume.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public decimal MinCciSignal { get => _minCciSignal.Value; set => _minCciSignal.Value = value; }
public int CooldownBars { get => _cooldownBars.Value; set => _cooldownBars.Value = value; }
public ComboRightStrategy()
{
_tp1 = Param(nameof(TakeProfit1), 500m).SetDisplay("TP1", "Take profit for basic signal", "General");
_sl1 = Param(nameof(StopLoss1), 500m).SetDisplay("SL1", "Stop loss for basic signal", "General");
_cciPeriod = Param(nameof(CciPeriod), 10).SetDisplay("CCI Period", "Period of CCI", "General");
_x12 = Param(nameof(X12), 100).SetDisplay("X12", "Sale perceptron weight", "Perceptron");
_x22 = Param(nameof(X22), 100).SetDisplay("X22", "Sale perceptron weight", "Perceptron");
_x32 = Param(nameof(X32), 100).SetDisplay("X32", "Sale perceptron weight", "Perceptron");
_x42 = Param(nameof(X42), 100).SetDisplay("X42", "Sale perceptron weight", "Perceptron");
_tp2 = Param(nameof(TakeProfit2), 500m).SetDisplay("TP2", "Take profit for sale perceptron", "Perceptron");
_sl2 = Param(nameof(StopLoss2), 500m).SetDisplay("SL2", "Stop loss for sale perceptron", "Perceptron");
_p2 = Param(nameof(P2), 20).SetDisplay("P2", "Sale perceptron period", "Perceptron");
_x13 = Param(nameof(X13), 100).SetDisplay("X13", "Buy perceptron weight", "Perceptron");
_x23 = Param(nameof(X23), 100).SetDisplay("X23", "Buy perceptron weight", "Perceptron");
_x33 = Param(nameof(X33), 100).SetDisplay("X33", "Buy perceptron weight", "Perceptron");
_x43 = Param(nameof(X43), 100).SetDisplay("X43", "Buy perceptron weight", "Perceptron");
_tp3 = Param(nameof(TakeProfit3), 500m).SetDisplay("TP3", "Take profit for buy perceptron", "Perceptron");
_sl3 = Param(nameof(StopLoss3), 500m).SetDisplay("SL3", "Stop loss for buy perceptron", "Perceptron");
_p3 = Param(nameof(P3), 20).SetDisplay("P3", "Buy perceptron period", "Perceptron");
_x14 = Param(nameof(X14), 100).SetDisplay("X14", "General perceptron weight", "Perceptron");
_x24 = Param(nameof(X24), 100).SetDisplay("X24", "General perceptron weight", "Perceptron");
_x34 = Param(nameof(X34), 100).SetDisplay("X34", "General perceptron weight", "Perceptron");
_x44 = Param(nameof(X44), 100).SetDisplay("X44", "General perceptron weight", "Perceptron");
_p4 = Param(nameof(P4), 20).SetDisplay("P4", "General perceptron period", "Perceptron");
_pass = Param(nameof(Pass), 1).SetDisplay("Pass", "Mode of operation", "General");
_shift = Param(nameof(Shift), 1).SetDisplay("Shift", "Bar shift", "General");
_volume = Param(nameof(TradeVolume), 0.1m).SetDisplay("Volume", "Trading volume", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Type of candles", "General");
_minCciSignal = Param(nameof(MinCciSignal), 50m).SetDisplay("Minimum CCI", "Minimum absolute CCI value for entries", "Filters");
_cooldownBars = Param(nameof(CooldownBars), 10).SetDisplay("Cooldown Bars", "Completed candles to wait after a position change", "Trading");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_closeBuffer = [];
_barIndex = 0;
_cooldownRemaining = 0;
_previousSignal = 0;
_w11 = 0;
_w12 = 0;
_w13 = 0;
_w14 = 0;
_w21 = 0;
_w22 = 0;
_w23 = 0;
_w24 = 0;
_w31 = 0;
_w32 = 0;
_w33 = 0;
_w34 = 0;
_sh11 = 0;
_sh12 = 0;
_sh13 = 0;
_sh14 = 0;
_sh15 = 0;
_sh21 = 0;
_sh22 = 0;
_sh23 = 0;
_sh24 = 0;
_sh25 = 0;
_sh31 = 0;
_sh32 = 0;
_sh33 = 0;
_sh34 = 0;
_sh35 = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_w11 = X12 - 100;
_w12 = X22 - 100;
_w13 = X32 - 100;
_w14 = X42 - 100;
_w21 = X13 - 100;
_w22 = X23 - 100;
_w23 = X33 - 100;
_w24 = X43 - 100;
_w31 = X14 - 100;
_w32 = X24 - 100;
_w33 = X34 - 100;
_w34 = X44 - 100;
_sh11 = Shift;
_sh12 = Shift + P2;
_sh13 = Shift + P2 * 2;
_sh14 = Shift + P2 * 3;
_sh15 = Shift + P2 * 4;
_sh21 = Shift;
_sh22 = Shift + P3;
_sh23 = Shift + P3 * 2;
_sh24 = Shift + P3 * 3;
_sh25 = Shift + P3 * 4;
_sh31 = Shift;
_sh32 = Shift + P4;
_sh33 = Shift + P4 * 2;
_sh34 = Shift + P4 * 3;
_sh35 = Shift + P4 * 4;
var maxShift = Math.Max(Math.Max(_sh15, _sh25), _sh35) + 1;
_closeBuffer = new decimal[maxShift];
_barIndex = 0;
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(cci, ProcessCandle).Start();
StartProtection(new Unit(TakeProfit1, UnitTypes.Absolute), new Unit(StopLoss1, UnitTypes.Absolute));
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, cci);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal cciValue)
{
if (candle.State != CandleStates.Finished)
return;
if (_cooldownRemaining > 0)
_cooldownRemaining--;
var len = _closeBuffer.Length;
_closeBuffer[_barIndex % len] = candle.ClosePrice;
_barIndex++;
if (_barIndex <= len)
return;
var rawSignal = Supervisor(cciValue);
var signal = 0;
if (rawSignal > 0m && cciValue >= MinCciSignal)
signal = 1;
else if (rawSignal < 0m && cciValue <= -MinCciSignal)
signal = -1;
if (_cooldownRemaining == 0)
{
if (signal > 0 && _previousSignal <= 0 && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
_cooldownRemaining = CooldownBars;
}
else if (signal < 0 && _previousSignal >= 0 && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
_cooldownRemaining = CooldownBars;
}
}
if (signal != 0)
_previousSignal = signal;
}
private decimal Supervisor(decimal basicSignal)
{
if (Pass == 4)
{
if (!Perceptron(out var output1, _sh11, _sh12, _sh13, _sh14, _sh15, _w11, _w12, _w13, _w14) ||
!Perceptron(out var output2, _sh21, _sh22, _sh23, _sh24, _sh25, _w21, _w22, _w23, _w24) ||
!Perceptron(out var output3, _sh31, _sh32, _sh33, _sh34, _sh35, _w31, _w32, _w33, _w34))
return 0m;
if (output3 > 0m)
return output2 > 0m ? 1m : basicSignal;
return output1 < 0m ? -1m : basicSignal;
}
if (Pass == 3)
{
if (!Perceptron(out var output2, _sh21, _sh22, _sh23, _sh24, _sh25, _w21, _w22, _w23, _w24))
return 0m;
return output2 > 0m ? 1m : basicSignal;
}
if (Pass == 2)
{
if (!Perceptron(out var output1, _sh11, _sh12, _sh13, _sh14, _sh15, _w11, _w12, _w13, _w14))
return 0m;
return output1 < 0m ? -1m : basicSignal;
}
return basicSignal;
}
private bool Perceptron(out decimal output, int sh1, int sh2, int sh3, int sh4, int sh5,
decimal w1, decimal w2, decimal w3, decimal w4)
{
output = 0m;
if (_barIndex <= sh5)
return false;
var csh1 = GetClose(sh1);
var osh2 = GetClose(sh2);
var osh3 = GetClose(sh3);
var osh4 = GetClose(sh4);
var osh5 = GetClose(sh5);
var a1 = csh1 - osh2;
var a2 = osh2 - osh3;
var a3 = osh3 - osh4;
var a4 = osh4 - osh5;
output = w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4;
return true;
}
private decimal GetClose(int shift)
{
var len = _closeBuffer.Length;
var index = (_barIndex - 1 - shift) % len;
if (index < 0)
index += len;
return _closeBuffer[index];
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class combo_right_strategy(Strategy):
"""
CCI + three perceptrons strategy. Uses close price differences
at various shifts as perceptron inputs to filter CCI signals.
"""
def __init__(self):
super(combo_right_strategy, self).__init__()
self._tp1 = self.Param("TakeProfit1", 500.0) \
.SetDisplay("TP1", "Take profit for basic signal", "General")
self._sl1 = self.Param("StopLoss1", 500.0) \
.SetDisplay("SL1", "Stop loss for basic signal", "General")
self._cci_period = self.Param("CciPeriod", 10) \
.SetDisplay("CCI Period", "Period of CCI", "General")
self._x12 = self.Param("X12", 100) \
.SetDisplay("X12", "Sale perceptron weight", "Perceptron")
self._x22 = self.Param("X22", 100) \
.SetDisplay("X22", "Sale perceptron weight", "Perceptron")
self._x32 = self.Param("X32", 100) \
.SetDisplay("X32", "Sale perceptron weight", "Perceptron")
self._x42 = self.Param("X42", 100) \
.SetDisplay("X42", "Sale perceptron weight", "Perceptron")
self._tp2 = self.Param("TakeProfit2", 500.0) \
.SetDisplay("TP2", "Take profit for sale perceptron", "Perceptron")
self._sl2 = self.Param("StopLoss2", 500.0) \
.SetDisplay("SL2", "Stop loss for sale perceptron", "Perceptron")
self._p2 = self.Param("P2", 20) \
.SetDisplay("P2", "Sale perceptron period", "Perceptron")
self._x13 = self.Param("X13", 100) \
.SetDisplay("X13", "Buy perceptron weight", "Perceptron")
self._x23 = self.Param("X23", 100) \
.SetDisplay("X23", "Buy perceptron weight", "Perceptron")
self._x33 = self.Param("X33", 100) \
.SetDisplay("X33", "Buy perceptron weight", "Perceptron")
self._x43 = self.Param("X43", 100) \
.SetDisplay("X43", "Buy perceptron weight", "Perceptron")
self._tp3 = self.Param("TakeProfit3", 500.0) \
.SetDisplay("TP3", "Take profit for buy perceptron", "Perceptron")
self._sl3 = self.Param("StopLoss3", 500.0) \
.SetDisplay("SL3", "Stop loss for buy perceptron", "Perceptron")
self._p3 = self.Param("P3", 20) \
.SetDisplay("P3", "Buy perceptron period", "Perceptron")
self._x14 = self.Param("X14", 100) \
.SetDisplay("X14", "General perceptron weight", "Perceptron")
self._x24 = self.Param("X24", 100) \
.SetDisplay("X24", "General perceptron weight", "Perceptron")
self._x34 = self.Param("X34", 100) \
.SetDisplay("X34", "General perceptron weight", "Perceptron")
self._x44 = self.Param("X44", 100) \
.SetDisplay("X44", "General perceptron weight", "Perceptron")
self._p4 = self.Param("P4", 20) \
.SetDisplay("P4", "General perceptron period", "Perceptron")
self._pass_mode = self.Param("Pass", 1) \
.SetDisplay("Pass", "Mode of operation", "General")
self._shift = self.Param("Shift", 1) \
.SetDisplay("Shift", "Bar shift", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._min_cci_signal = self.Param("MinCciSignal", 50.0) \
.SetDisplay("Minimum CCI", "Minimum absolute CCI value for entries", "Filters")
self._cooldown_bars = self.Param("CooldownBars", 4) \
.SetDisplay("Cooldown Bars", "Completed candles to wait after a position change", "Trading")
self._close_buffer = []
self._bar_index = 0
self._cooldown_remaining = 0
self._previous_signal = 0
self._w11 = 0.0
self._w12 = 0.0
self._w13 = 0.0
self._w14 = 0.0
self._w21 = 0.0
self._w22 = 0.0
self._w23 = 0.0
self._w24 = 0.0
self._w31 = 0.0
self._w32 = 0.0
self._w33 = 0.0
self._w34 = 0.0
self._sh11 = 0
self._sh12 = 0
self._sh13 = 0
self._sh14 = 0
self._sh15 = 0
self._sh21 = 0
self._sh22 = 0
self._sh23 = 0
self._sh24 = 0
self._sh25 = 0
self._sh31 = 0
self._sh32 = 0
self._sh33 = 0
self._sh34 = 0
self._sh35 = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(combo_right_strategy, self).OnReseted()
self._close_buffer = []
self._bar_index = 0
self._cooldown_remaining = 0
self._previous_signal = 0
def OnStarted2(self, time):
super(combo_right_strategy, self).OnStarted2(time)
shift = self._shift.Value
p2 = self._p2.Value
p3 = self._p3.Value
p4 = self._p4.Value
self._w11 = float(self._x12.Value - 100)
self._w12 = float(self._x22.Value - 100)
self._w13 = float(self._x32.Value - 100)
self._w14 = float(self._x42.Value - 100)
self._w21 = float(self._x13.Value - 100)
self._w22 = float(self._x23.Value - 100)
self._w23 = float(self._x33.Value - 100)
self._w24 = float(self._x43.Value - 100)
self._w31 = float(self._x14.Value - 100)
self._w32 = float(self._x24.Value - 100)
self._w33 = float(self._x34.Value - 100)
self._w34 = float(self._x44.Value - 100)
self._sh11 = shift
self._sh12 = shift + p2
self._sh13 = shift + p2 * 2
self._sh14 = shift + p2 * 3
self._sh15 = shift + p2 * 4
self._sh21 = shift
self._sh22 = shift + p3
self._sh23 = shift + p3 * 2
self._sh24 = shift + p3 * 3
self._sh25 = shift + p3 * 4
self._sh31 = shift
self._sh32 = shift + p4
self._sh33 = shift + p4 * 2
self._sh34 = shift + p4 * 3
self._sh35 = shift + p4 * 4
max_shift = max(self._sh15, self._sh25, self._sh35) + 1
self._close_buffer = [0.0] * max_shift
self._bar_index = 0
cci = CommodityChannelIndex()
cci.Length = self._cci_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(cci, self.on_process).Start()
self.StartProtection(
Unit(float(self._tp1.Value), UnitTypes.Absolute),
Unit(float(self._sl1.Value), UnitTypes.Absolute)
)
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, cci)
self.DrawOwnTrades(area)
def on_process(self, candle, cci_val):
if candle.State != CandleStates.Finished:
return
if self._cooldown_remaining > 0:
self._cooldown_remaining -= 1
buf_len = len(self._close_buffer)
self._close_buffer[self._bar_index % buf_len] = float(candle.ClosePrice)
self._bar_index += 1
if self._bar_index <= buf_len:
return
raw_signal = self._supervisor(float(cci_val))
signal = 0
min_cci = float(self._min_cci_signal.Value)
if raw_signal > 0 and float(cci_val) >= min_cci:
signal = 1
elif raw_signal < 0 and float(cci_val) <= -min_cci:
signal = -1
if self._cooldown_remaining == 0:
if signal > 0 and self._previous_signal <= 0 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._cooldown_remaining = self._cooldown_bars.Value
elif signal < 0 and self._previous_signal >= 0 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._cooldown_remaining = self._cooldown_bars.Value
if signal != 0:
self._previous_signal = signal
def _supervisor(self, basic_signal):
pass_mode = self._pass_mode.Value
if pass_mode == 4:
ok1, out1 = self._perceptron(self._sh11, self._sh12, self._sh13, self._sh14, self._sh15,
self._w11, self._w12, self._w13, self._w14)
ok2, out2 = self._perceptron(self._sh21, self._sh22, self._sh23, self._sh24, self._sh25,
self._w21, self._w22, self._w23, self._w24)
ok3, out3 = self._perceptron(self._sh31, self._sh32, self._sh33, self._sh34, self._sh35,
self._w31, self._w32, self._w33, self._w34)
if not ok1 or not ok2 or not ok3:
return 0.0
if out3 > 0:
return 1.0 if out2 > 0 else basic_signal
return -1.0 if out1 < 0 else basic_signal
if pass_mode == 3:
ok2, out2 = self._perceptron(self._sh21, self._sh22, self._sh23, self._sh24, self._sh25,
self._w21, self._w22, self._w23, self._w24)
if not ok2:
return 0.0
return 1.0 if out2 > 0 else basic_signal
if pass_mode == 2:
ok1, out1 = self._perceptron(self._sh11, self._sh12, self._sh13, self._sh14, self._sh15,
self._w11, self._w12, self._w13, self._w14)
if not ok1:
return 0.0
return -1.0 if out1 < 0 else basic_signal
return basic_signal
def _perceptron(self, sh1, sh2, sh3, sh4, sh5, w1, w2, w3, w4):
if self._bar_index <= sh5:
return False, 0.0
csh1 = self._get_close(sh1)
osh2 = self._get_close(sh2)
osh3 = self._get_close(sh3)
osh4 = self._get_close(sh4)
osh5 = self._get_close(sh5)
a1 = csh1 - osh2
a2 = osh2 - osh3
a3 = osh3 - osh4
a4 = osh4 - osh5
output = w1 * a1 + w2 * a2 + w3 * a3 + w4 * a4
return True, output
def _get_close(self, shift):
buf_len = len(self._close_buffer)
index = (self._bar_index - 1 - shift) % buf_len
if index < 0:
index += buf_len
return self._close_buffer[index]
def CreateClone(self):
return combo_right_strategy()