RoBoost戦略
この戦略はオリジナルのMQL4エキスパートアドバイザー RoBoostj のC#適応版です。 RSIベースのシグナルと単純な価格モメンタム検出を組み合わせて、単一の銘柄で取引します。 選択したローソク足タイプで動作します(デフォルト:1時間足)。
ロジック
- 前回の終値が現在の終値より高く、RSI値が RSI Down 閾値を下回ると、 戦略はショートポジションを開きます。
- 前回の終値が現在の終値以下で、RSI値が RSI Up 閾値を上回ると、 戦略はロングポジションを開きます。
- アクティブなポジションは以下のリスクツールで管理されます:
- 価格単位で測定された固定の Take Profit と Stop Loss レベル。
- オプションのトレーリングストップ。取引が Trail Start 距離分の利益に達すると 有効化されます。有効化後、ストップ価格は Trail Step 距離分離れて価格を追います。
パラメーター
| 名前 | 説明 |
|---|---|
CandleType |
計算に使用するローソク足シリーズ。 |
RsiPeriod |
RSIインジケーターの期間長。 |
RsiUp |
ロングエントリーに使用するRSI閾値。 |
RsiDown |
ショートエントリーに使用するRSI閾値。 |
TakeProfit |
エントリー価格からのテイクプロフィット距離(ポイント)。 |
StopLoss |
エントリー価格からのストップロス距離(ポイント)。 |
UseTrailing |
トレーリングストップロジックを有効化。 |
TrailStart |
トレーリングストップが有効になるポイント距離。 |
TrailStep |
トレーリングストップが有効な場合に現在価格から |
| 維持されるポイント距離。 |
すべての距離は絶対価格単位で表され、銘柄のティックサイズに応じて調整が必要な場合があります。
使用方法
- プロジェクトに戦略を追加するか、StockSharp Designerで開きます。
- トレードの好みに応じてパラメーターを設定します。
- 戦略を開始します。選択したローソク足シリーズを自動的に購読し、 RSI値とローソク足の終値に基づいて取引を管理します。
この戦略は教育目的で作成されており、ライブ市場で使用する前に 履歴データでテストする必要があります。
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>
/// RSI based strategy converted from the original RoBoostj MQL4 robot.
/// Opens long or short positions depending on price momentum and RSI values.
/// Includes optional trailing stop management.
/// </summary>
public class RoBoostStrategy : Strategy
{
private readonly StrategyParam<decimal> _takeProfit;
private readonly StrategyParam<decimal> _stopLoss;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _rsiUp;
private readonly StrategyParam<int> _rsiDown;
private readonly StrategyParam<bool> _useTrailing;
private readonly StrategyParam<decimal> _trailStart;
private readonly StrategyParam<decimal> _trailStep;
private readonly StrategyParam<DataType> _candleType;
private decimal _entryPrice;
private bool _isLong;
private decimal _trailingStopPrice;
private decimal _previousClose;
private bool _isFirst = true;
/// <summary>
/// Take profit distance from entry price.
/// </summary>
public decimal TakeProfit
{
get => _takeProfit.Value;
set => _takeProfit.Value = value;
}
/// <summary>
/// Stop loss distance from entry price.
/// </summary>
public decimal StopLoss
{
get => _stopLoss.Value;
set => _stopLoss.Value = value;
}
/// <summary>
/// RSI indicator period length.
/// </summary>
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
/// <summary>
/// RSI threshold for long entries.
/// </summary>
public int RsiUp
{
get => _rsiUp.Value;
set => _rsiUp.Value = value;
}
/// <summary>
/// RSI threshold for short entries.
/// </summary>
public int RsiDown
{
get => _rsiDown.Value;
set => _rsiDown.Value = value;
}
/// <summary>
/// Enables trailing stop logic.
/// </summary>
public bool UseTrailing
{
get => _useTrailing.Value;
set => _useTrailing.Value = value;
}
/// <summary>
/// Distance at which trailing stop becomes active.
/// </summary>
public decimal TrailStart
{
get => _trailStart.Value;
set => _trailStart.Value = value;
}
/// <summary>
/// Distance maintained from current price when trailing stop is active.
/// </summary>
public decimal TrailStep
{
get => _trailStep.Value;
set => _trailStep.Value = value;
}
/// <summary>
/// Type of candles used for calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of <see cref="RoBoostStrategy"/>.
/// </summary>
public RoBoostStrategy()
{
_takeProfit = Param(nameof(TakeProfit), 500m)
.SetGreaterThanZero()
.SetDisplay("Take Profit", "Take profit distance in points", "Risk Management");
_stopLoss = Param(nameof(StopLoss), 1000m)
.SetGreaterThanZero()
.SetDisplay("Stop Loss", "Stop loss distance in points", "Risk Management");
_rsiPeriod = Param(nameof(RsiPeriod), 7)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI calculation length", "Indicator")
.SetOptimize(5, 20, 1);
_rsiUp = Param(nameof(RsiUp), 50)
.SetDisplay("RSI Up", "RSI threshold for longs", "Indicator")
.SetOptimize(45, 70, 5);
_rsiDown = Param(nameof(RsiDown), 50)
.SetDisplay("RSI Down", "RSI threshold for shorts", "Indicator")
.SetOptimize(30, 55, 5);
_useTrailing = Param(nameof(UseTrailing), false)
.SetDisplay("Use Trailing", "Enable trailing stop", "Risk Management");
_trailStart = Param(nameof(TrailStart), 5m)
.SetGreaterThanZero()
.SetDisplay("Trail Start", "Profit distance to activate trailing", "Risk Management");
_trailStep = Param(nameof(TrailStep), 2m)
.SetGreaterThanZero()
.SetDisplay("Trail Step", "Distance between price and trailing stop", "Risk Management");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles used", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0m;
_isLong = false;
_trailingStopPrice = 0m;
_previousClose = 0m;
_isFirst = true;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, rsi);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var currentClose = candle.ClosePrice;
if (_isFirst)
{
_previousClose = currentClose;
_isFirst = false;
return;
}
if (Position == 0)
{
if (_previousClose > currentClose && rsiValue < RsiDown)
{
SellMarket();
_entryPrice = currentClose;
_isLong = false;
_trailingStopPrice = 0m;
}
else if (_previousClose <= currentClose && rsiValue >= RsiUp)
{
BuyMarket();
_entryPrice = currentClose;
_isLong = true;
_trailingStopPrice = 0m;
}
}
else
{
ManagePosition(currentClose);
}
_previousClose = currentClose;
}
private void ManagePosition(decimal currentPrice)
{
if (_entryPrice == 0m)
return;
if (_isLong)
{
var profit = currentPrice - _entryPrice;
if (profit >= TakeProfit || -profit >= StopLoss)
{
SellMarket();
return;
}
if (UseTrailing)
{
if (profit >= TrailStart)
{
var newStop = currentPrice - TrailStep;
if (_trailingStopPrice < newStop)
_trailingStopPrice = newStop;
}
if (_trailingStopPrice != 0m && currentPrice <= _trailingStopPrice)
SellMarket();
}
}
else
{
var profit = _entryPrice - currentPrice;
if (profit >= TakeProfit || -profit >= StopLoss)
{
BuyMarket();
return;
}
if (UseTrailing)
{
if (profit >= TrailStart)
{
var newStop = currentPrice + TrailStep;
if (_trailingStopPrice == 0m || _trailingStopPrice > newStop)
_trailingStopPrice = newStop;
}
if (_trailingStopPrice != 0m && currentPrice >= _trailingStopPrice)
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 StockSharp.Algo.Indicators import RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class ro_boost_strategy(Strategy):
def __init__(self):
super(ro_boost_strategy, self).__init__()
self._tp = self.Param("TakeProfit", 500.0).SetGreaterThanZero().SetDisplay("Take Profit", "TP distance in points", "Risk")
self._sl = self.Param("StopLoss", 1000.0).SetGreaterThanZero().SetDisplay("Stop Loss", "SL distance in points", "Risk")
self._rsi_period = self.Param("RsiPeriod", 7).SetGreaterThanZero().SetDisplay("RSI Period", "RSI length", "Indicator")
self._rsi_up = self.Param("RsiUp", 50).SetDisplay("RSI Up", "RSI threshold for longs", "Indicator")
self._rsi_down = self.Param("RsiDown", 50).SetDisplay("RSI Down", "RSI threshold for shorts", "Indicator")
self._use_trailing = self.Param("UseTrailing", False).SetDisplay("Use Trailing", "Enable trailing stop", "Risk")
self._trail_start = self.Param("TrailStart", 5.0).SetGreaterThanZero().SetDisplay("Trail Start", "Profit to activate trailing", "Risk")
self._trail_step = self.Param("TrailStep", 2.0).SetGreaterThanZero().SetDisplay("Trail Step", "Trailing distance from price", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).SetDisplay("Candle Type", "Candle 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(ro_boost_strategy, self).OnReseted()
self._entry_price = 0
self._is_long = False
self._trailing_stop = 0
self._prev_close = 0
self._is_first = True
def OnStarted2(self, time):
super(ro_boost_strategy, self).OnStarted2(time)
self._entry_price = 0
self._is_long = False
self._trailing_stop = 0
self._prev_close = 0
self._is_first = True
rsi = RelativeStrengthIndex()
rsi.Length = self._rsi_period.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(rsi, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, rsi)
self.DrawOwnTrades(area)
def OnProcess(self, candle, rsi_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
if self._is_first:
self._prev_close = close
self._is_first = False
return
if self.Position == 0:
if self._prev_close > close and rsi_val < self._rsi_down.Value:
self.SellMarket()
self._entry_price = close
self._is_long = False
self._trailing_stop = 0
elif self._prev_close <= close and rsi_val >= self._rsi_up.Value:
self.BuyMarket()
self._entry_price = close
self._is_long = True
self._trailing_stop = 0
else:
self._manage_position(close)
self._prev_close = close
def _manage_position(self, price):
if self._entry_price == 0:
return
if self._is_long:
profit = price - self._entry_price
if profit >= self._tp.Value or -profit >= self._sl.Value:
self.SellMarket()
return
if self._use_trailing.Value:
if profit >= self._trail_start.Value:
new_stop = price - self._trail_step.Value
if self._trailing_stop < new_stop:
self._trailing_stop = new_stop
if self._trailing_stop != 0 and price <= self._trailing_stop:
self.SellMarket()
else:
profit = self._entry_price - price
if profit >= self._tp.Value or -profit >= self._sl.Value:
self.BuyMarket()
return
if self._use_trailing.Value:
if profit >= self._trail_start.Value:
new_stop = price + self._trail_step.Value
if self._trailing_stop == 0 or self._trailing_stop > new_stop:
self._trailing_stop = new_stop
if self._trailing_stop != 0 and price >= self._trailing_stop:
self.BuyMarket()
def CreateClone(self):
return ro_boost_strategy()