Стратегия MasterMind 3
Данная стратегия торгует экстремальные развороты, используя четыре индикатора Williams %R с разными периодами. Когда все индикаторы уходят в глубокую зону перепроданности, стратегия открывает длинную позицию. Когда все индикаторы поднимаются в сильную зону перекупленности, стратегия открывает короткую позицию.
Логика торговли
- Подписка на свечи выбранного таймфрейма.
- Расчёт четырёх индикаторов Williams %R с периодами 26, 27, 29 и 30.
- Покупка, если все значения ниже
-99.99. - Продажа, если все значения выше
-0.01. - Обработка сигналов только по завершённым свечам.
Объём сделки берётся из свойства Volume. При наличии противоположной позиции стратегия автоматически закрывает её встречной рыночной сделкой.
Параметры
| Имя | Описание | Значение по умолчанию |
|---|---|---|
WprPeriod1 |
Период первого Williams %R | 26 |
WprPeriod2 |
Период второго Williams %R | 27 |
WprPeriod3 |
Период третьего Williams %R | 29 |
WprPeriod4 |
Период четвёртого Williams %R | 30 |
CandleType |
Тип и таймфрейм свечей | Свечи 1 минута |
Примечания
- Используется высокоуровневый API и метод
Bind. - Стратегия не содержит стоп-лоссов или тейк-профитов и переворачивает позицию при появлении обратного сигнала.
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>
/// Williams %R based extreme reversals.
/// Enters long when all indicators show deep oversold.
/// Enters short when all indicators show strong overbought.
/// </summary>
public class MasterMind3Strategy : Strategy
{
private readonly StrategyParam<int> _rsiPeriod1;
private readonly StrategyParam<int> _rsiPeriod2;
private readonly StrategyParam<int> _rsiPeriod3;
private readonly StrategyParam<int> _rsiPeriod4;
private readonly StrategyParam<DataType> _candleType;
private bool _wasOversold;
private bool _wasOverbought;
/// <summary>
/// Period for the first Williams %R indicator.
/// </summary>
public int RsiPeriod1
{
get => _rsiPeriod1.Value;
set => _rsiPeriod1.Value = value;
}
/// <summary>
/// Period for the second Williams %R indicator.
/// </summary>
public int RsiPeriod2
{
get => _rsiPeriod2.Value;
set => _rsiPeriod2.Value = value;
}
/// <summary>
/// Period for the third Williams %R indicator.
/// </summary>
public int RsiPeriod3
{
get => _rsiPeriod3.Value;
set => _rsiPeriod3.Value = value;
}
/// <summary>
/// Period for the fourth Williams %R indicator.
/// </summary>
public int RsiPeriod4
{
get => _rsiPeriod4.Value;
set => _rsiPeriod4.Value = value;
}
/// <summary>
/// The type of candles to use for calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes strategy parameters.
/// </summary>
public MasterMind3Strategy()
{
_rsiPeriod1 = Param(nameof(RsiPeriod1), 26)
.SetGreaterThanZero()
.SetDisplay("RSI Period 1", "Length of the first RSI indicator", "RSI")
.SetOptimize(10, 50, 5);
_rsiPeriod2 = Param(nameof(RsiPeriod2), 27)
.SetGreaterThanZero()
.SetDisplay("RSI Period 2", "Length of the second RSI indicator", "RSI")
.SetOptimize(10, 50, 5);
_rsiPeriod3 = Param(nameof(RsiPeriod3), 29)
.SetGreaterThanZero()
.SetDisplay("RSI Period 3", "Length of the third RSI indicator", "RSI")
.SetOptimize(10, 50, 5);
_rsiPeriod4 = Param(nameof(RsiPeriod4), 30)
.SetGreaterThanZero()
.SetDisplay("RSI Period 4", "Length of the fourth RSI indicator", "RSI")
.SetOptimize(10, 50, 5);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Candle Type", "Type of candles for the strategy", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_wasOversold = false;
_wasOverbought = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi1 = new RelativeStrengthIndex { Length = RsiPeriod1 };
var rsi2 = new RelativeStrengthIndex { Length = RsiPeriod2 };
var rsi3 = new RelativeStrengthIndex { Length = RsiPeriod3 };
var rsi4 = new RelativeStrengthIndex { Length = RsiPeriod4 };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi1, rsi2, rsi3, rsi4, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, rsi1);
DrawIndicator(area, rsi2);
DrawIndicator(area, rsi3);
DrawIndicator(area, rsi4);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsi1, decimal rsi2, decimal rsi3, decimal rsi4)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var isOversold = rsi1 <= 35m && rsi2 <= 35m && rsi3 <= 35m && rsi4 <= 35m;
var isOverbought = rsi1 >= 65m && rsi2 >= 65m && rsi3 >= 65m && rsi4 >= 65m;
var isBuySignal = isOversold && !_wasOversold;
var isSellSignal = isOverbought && !_wasOverbought;
if (isBuySignal && Position <= 0)
{
BuyMarket(Volume + Math.Abs(Position));
}
else if (isSellSignal && Position >= 0)
{
SellMarket(Volume + Math.Abs(Position));
}
_wasOversold = isOversold;
_wasOverbought = isOverbought;
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class master_mind3_strategy(Strategy):
def __init__(self):
super(master_mind3_strategy, self).__init__()
self._rsi_period1 = self.Param("RsiPeriod1", 26)
self._rsi_period2 = self.Param("RsiPeriod2", 27)
self._rsi_period3 = self.Param("RsiPeriod3", 29)
self._rsi_period4 = self.Param("RsiPeriod4", 30)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15)))
self._was_oversold = False
self._was_overbought = False
@property
def RsiPeriod1(self):
return self._rsi_period1.Value
@RsiPeriod1.setter
def RsiPeriod1(self, value):
self._rsi_period1.Value = value
@property
def RsiPeriod2(self):
return self._rsi_period2.Value
@RsiPeriod2.setter
def RsiPeriod2(self, value):
self._rsi_period2.Value = value
@property
def RsiPeriod3(self):
return self._rsi_period3.Value
@RsiPeriod3.setter
def RsiPeriod3(self, value):
self._rsi_period3.Value = value
@property
def RsiPeriod4(self):
return self._rsi_period4.Value
@RsiPeriod4.setter
def RsiPeriod4(self, value):
self._rsi_period4.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(master_mind3_strategy, self).OnStarted2(time)
self._was_oversold = False
self._was_overbought = False
rsi1 = RelativeStrengthIndex()
rsi1.Length = self.RsiPeriod1
rsi2 = RelativeStrengthIndex()
rsi2.Length = self.RsiPeriod2
rsi3 = RelativeStrengthIndex()
rsi3.Length = self.RsiPeriod3
rsi4 = RelativeStrengthIndex()
rsi4.Length = self.RsiPeriod4
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi1, rsi2, rsi3, rsi4, self.ProcessCandle).Start()
def ProcessCandle(self, candle, rsi1_val, rsi2_val, rsi3_val, rsi4_val):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
r1 = float(rsi1_val)
r2 = float(rsi2_val)
r3 = float(rsi3_val)
r4 = float(rsi4_val)
is_oversold = r1 <= 35.0 and r2 <= 35.0 and r3 <= 35.0 and r4 <= 35.0
is_overbought = r1 >= 65.0 and r2 >= 65.0 and r3 >= 65.0 and r4 >= 65.0
buy_signal = is_oversold and not self._was_oversold
sell_signal = is_overbought and not self._was_overbought
if buy_signal and self.Position <= 0:
self.BuyMarket()
elif sell_signal and self.Position >= 0:
self.SellMarket()
self._was_oversold = is_oversold
self._was_overbought = is_overbought
def OnReseted(self):
super(master_mind3_strategy, self).OnReseted()
self._was_oversold = False
self._was_overbought = False
def CreateClone(self):
return master_mind3_strategy()