RGT EA RSI戦略
この戦略は相対力指数(RSI)とボリンジャーバンドを組み合わせて、極端な価格動向を特定し潜在的なリバーサルを取引します。RSIが売られすぎや買われすぎのゾーンに入り、価格がボリンジャーバンドをクロスするとポジションが建てられます。ストップロスとトレーリングストップがリスクを管理し利益を確保します。
仕組み
- 受信したローソク足に対してRSIとボリンジャーバンドを計算します。
- RSIが売られすぎレベルを下回り、終値が下部バンドを下回るときに買います。
- RSIが買われすぎレベルを上回り、終値が上部バンドを上回るときに売ります。
- エントリー後、固定ストップロスが置かれます。ポジションが最小利益に達すると、ストップロスが価格を追いかけます。
パラメーター
| 名前 | 説明 |
|---|---|
Volume |
注文量。 |
RsiPeriod |
RSI計算期間。 |
RsiHigh |
RSI買われすぎしきい値。 |
RsiLow |
RSI売られすぎしきい値。 |
StopLoss |
価格単位での初期ストップロス距離。 |
TrailingStop |
価格単位でのトレーリングストップ距離。 |
MinProfit |
トレーリングが有効になる前の最小利益。 |
CandleType |
計算に使用するローソク足の種類。 |
注意事項
- StockSharpがサポートするあらゆる銘柄と時間軸で動作します。
- エントリーとエグジットに成行注文を使用します。
- トレーリングストップは完成したローソク足ごとに更新されます。
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>
/// RSI and Bollinger Bands breakout with trailing stop.
/// </summary>
public class RgtEaRsiStrategy : Strategy
{
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _rsiHigh;
private readonly StrategyParam<int> _rsiLow;
private readonly StrategyParam<decimal> _stopLoss;
private readonly StrategyParam<decimal> _trailingStop;
private readonly StrategyParam<decimal> _minProfit;
private readonly StrategyParam<DataType> _candleType;
private decimal _entryPrice;
private decimal _stopPrice;
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int RsiHigh { get => _rsiHigh.Value; set => _rsiHigh.Value = value; }
public int RsiLow { get => _rsiLow.Value; set => _rsiLow.Value = value; }
public decimal StopLoss { get => _stopLoss.Value; set => _stopLoss.Value = value; }
public decimal TrailingStop { get => _trailingStop.Value; set => _trailingStop.Value = value; }
public decimal MinProfit { get => _minProfit.Value; set => _minProfit.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public RgtEaRsiStrategy()
{
_rsiPeriod = Param(nameof(RsiPeriod), 8)
.SetDisplay("RSI Period", "RSI calculation period", "Indicator");
_rsiHigh = Param(nameof(RsiHigh), 55)
.SetDisplay("RSI High", "Overbought threshold", "Indicator");
_rsiLow = Param(nameof(RsiLow), 45)
.SetDisplay("RSI Low", "Oversold threshold", "Indicator");
_stopLoss = Param(nameof(StopLoss), 500m)
.SetGreaterThanZero()
.SetDisplay("Stop Loss", "Stop loss size in price units", "Risk");
_trailingStop = Param(nameof(TrailingStop), 300m)
.SetGreaterThanZero()
.SetDisplay("Trailing Stop", "Trailing stop distance", "Risk");
_minProfit = Param(nameof(MinProfit), 200m)
.SetGreaterThanZero()
.SetDisplay("Min Profit", "Minimum profit before trailing", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0;
_stopPrice = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var bb = new BollingerBands { Length = 20, Width = 2m };
var subscription = SubscribeCandles(CandleType);
subscription.BindEx(new IIndicator[] { rsi, bb }, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue[] values)
{
if (candle.State != CandleStates.Finished)
return;
if (values[0].IsEmpty || values[1].IsEmpty)
return;
var rsiVal = values[0].GetValue<decimal>();
var bbVal = (BollingerBandsValue)values[1];
if (bbVal.UpBand is not decimal upper ||
bbVal.LowBand is not decimal lower)
return;
if (Position == 0)
{
if (rsiVal < RsiLow && candle.ClosePrice < lower)
{
BuyMarket();
_entryPrice = candle.ClosePrice;
_stopPrice = _entryPrice - StopLoss;
return;
}
if (rsiVal > RsiHigh && candle.ClosePrice > upper)
{
SellMarket();
_entryPrice = candle.ClosePrice;
_stopPrice = _entryPrice + StopLoss;
return;
}
}
if (Position > 0)
{
var profit = candle.ClosePrice - _entryPrice;
var newStop = candle.ClosePrice - TrailingStop;
if (profit > MinProfit && newStop > _stopPrice)
_stopPrice = newStop;
if (candle.ClosePrice <= _stopPrice)
SellMarket();
}
else if (Position < 0)
{
var profit = _entryPrice - candle.ClosePrice;
var newStop = candle.ClosePrice + TrailingStop;
if (profit > MinProfit && newStop < _stopPrice)
_stopPrice = newStop;
if (candle.ClosePrice >= _stopPrice)
BuyMarket();
}
}
}
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 System import Array
from StockSharp.Algo.Indicators import BollingerBands, RelativeStrengthIndex, IIndicator, IndicatorHelper
from StockSharp.Algo.Strategies import Strategy
class rgt_ea_rsi_strategy(Strategy):
def __init__(self):
super(rgt_ea_rsi_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 8) \
.SetDisplay("RSI Period", "RSI calculation period", "Indicator")
self._rsi_high = self.Param("RsiHigh", 55) \
.SetDisplay("RSI High", "Overbought threshold", "Indicator")
self._rsi_low = self.Param("RsiLow", 45) \
.SetDisplay("RSI Low", "Oversold threshold", "Indicator")
self._stop_loss = self.Param("StopLoss", 500.0) \
.SetDisplay("Stop Loss", "Stop loss size in price units", "Risk")
self._trailing_stop = self.Param("TrailingStop", 300.0) \
.SetDisplay("Trailing Stop", "Trailing stop distance", "Risk")
self._min_profit = self.Param("MinProfit", 200.0) \
.SetDisplay("Min Profit", "Minimum profit before trailing", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._entry_price = 0.0
self._stop_price = 0.0
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def rsi_high(self):
return self._rsi_high.Value
@property
def rsi_low(self):
return self._rsi_low.Value
@property
def stop_loss(self):
return self._stop_loss.Value
@property
def trailing_stop(self):
return self._trailing_stop.Value
@property
def min_profit(self):
return self._min_profit.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(rgt_ea_rsi_strategy, self).OnReseted()
self._entry_price = 0.0
self._stop_price = 0.0
def OnStarted2(self, time):
super(rgt_ea_rsi_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.rsi_period
bb = BollingerBands()
bb.Length = 20
bb.Width = 2.0
indicators = Array[IIndicator]([rsi, bb])
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(indicators, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, bb)
self.DrawOwnTrades(area)
def on_process(self, candle, values):
if candle.State != CandleStates.Finished:
return
if values[0].IsEmpty or values[1].IsEmpty:
return
rsi_val = IndicatorHelper.ToDecimal(values[0])
bb_val = values[1]
up = bb_val.UpBand
lo = bb_val.LowBand
if up is None or lo is None:
return
close = candle.ClosePrice
if self.Position == 0:
if rsi_val < self.rsi_low and close < lo:
self.BuyMarket()
self._entry_price = close
self._stop_price = self._entry_price - self.stop_loss
return
if rsi_val > self.rsi_high and close > up:
self.SellMarket()
self._entry_price = close
self._stop_price = self._entry_price + self.stop_loss
return
if self.Position > 0:
profit = close - self._entry_price
new_stop = close - self.trailing_stop
if profit > self.min_profit and new_stop > self._stop_price:
self._stop_price = new_stop
if close <= self._stop_price:
self.SellMarket()
elif self.Position < 0:
profit = self._entry_price - close
new_stop = close + self.trailing_stop
if profit > self.min_profit and new_stop < self._stop_price:
self._stop_price = new_stop
if close >= self._stop_price:
self.BuyMarket()
def CreateClone(self):
return rgt_ea_rsi_strategy()