マルチタイムフレーム資産のテクニカルレーティング戦略
この戦略は複数の時間軸からテクニカルレーティングを集計します。 1h、4h、日足ロウソク足で価格を移動平均とRSIの閾値と比較します。 統合レーティングがプラスのときロングポジションを、マイナスのときショートポジションを開きます。
詳細
- エントリー: 平均レーティング > 0 で買い;平均レーティング < 0 で売り。
- インジケーター: SMA, RSI。
- 時間軸: 1h, 4h, 1d。
- タイプ: トレンドフォロー。
- ストップ: なし。
- 方向: ロングとショート。
- リスク: 中。
- 複雑さ: 中。
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>
/// Aggregates SMA/RSI technical ratings from 1h, 4h and daily time frames.
/// </summary>
public class TechnicalRatingsOnMultiFramesAssetsStrategy : Strategy
{
private readonly StrategyParam<int> _smaPeriod;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _bullRsi;
private readonly StrategyParam<decimal> _bearRsi;
private readonly StrategyParam<DataType> _hourly;
private readonly StrategyParam<DataType> _fourHourly;
private readonly StrategyParam<DataType> _daily;
private readonly Dictionary<string, decimal> _ratings = [];
public int SmaPeriod { get => _smaPeriod.Value; set => _smaPeriod.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public decimal BullRsiThreshold { get => _bullRsi.Value; set => _bullRsi.Value = value; }
public decimal BearRsiThreshold { get => _bearRsi.Value; set => _bearRsi.Value = value; }
public DataType HourlyCandleType { get => _hourly.Value; set => _hourly.Value = value; }
public DataType FourHourCandleType { get => _fourHourly.Value; set => _fourHourly.Value = value; }
public DataType DailyCandleType { get => _daily.Value; set => _daily.Value = value; }
public TechnicalRatingsOnMultiFramesAssetsStrategy()
{
_smaPeriod = Param(nameof(SmaPeriod), 20).SetGreaterThanZero()
.SetDisplay("SMA Period", "SMA period used by each rating.", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14).SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period used by each rating.", "Indicators");
_bullRsi = Param(nameof(BullRsiThreshold), 55m)
.SetDisplay("Bull RSI", "RSI threshold contributing a bullish vote.", "Indicators");
_bearRsi = Param(nameof(BearRsiThreshold), 45m)
.SetDisplay("Bear RSI", "RSI threshold contributing a bearish vote.", "Indicators");
_hourly = Param(nameof(HourlyCandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("1h", "Primary technical-rating timeframe.", "Timeframes");
_fourHourly = Param(nameof(FourHourCandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("4h", "Confirmation technical-rating timeframe.", "Timeframes");
_daily = Param(nameof(DailyCandleType), TimeSpan.FromDays(1).TimeFrame())
.SetDisplay("1d", "Daily technical-rating timeframe.", "Timeframes");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, HourlyCandleType), (Security, FourHourCandleType), (Security, DailyCandleType)];
protected override void OnReseted()
{
base.OnReseted();
_ratings.Clear();
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
StartRating("1h", HourlyCandleType);
StartRating("4h", FourHourCandleType);
StartRating("1d", DailyCandleType);
}
private void StartRating(string key, DataType candleType)
{
var sma = new SimpleMovingAverage { Length = SmaPeriod };
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(candleType);
subscription.Bind(sma, rsi, (candle, smaValue, rsiValue) =>
{
if (candle.State != CandleStates.Finished || !sma.IsFormed || !rsi.IsFormed)
return;
var maVote = candle.ClosePrice > smaValue ? 1m : candle.ClosePrice < smaValue ? -1m : 0m;
var rsiVote = rsiValue >= BullRsiThreshold ? 1m : rsiValue <= BearRsiThreshold ? -1m : 0m;
_ratings[key] = (maVote + rsiVote) / 2m;
Evaluate();
}).Start();
var area = CreateChartArea();
if (area != null)
DrawCandles(area, subscription);
}
private void Evaluate()
{
if (_ratings.Count < 3)
return;
var average = (_ratings["1h"] + _ratings["4h"] + _ratings["1d"]) / 3m;
if (average > 0m && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (average < 0m && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
}
}
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
from StockSharp.Algo.Indicators import SimpleMovingAverage, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class technical_ratings_on_multi_frames_assets_strategy(Strategy):
def __init__(self):
super(technical_ratings_on_multi_frames_assets_strategy, self).__init__()
self._sma_period = self.Param("SmaPeriod", 20).SetGreaterThanZero()
self._rsi_period = self.Param("RsiPeriod", 14).SetGreaterThanZero()
self._bull_rsi = self.Param("BullRsiThreshold", 55.0)
self._bear_rsi = self.Param("BearRsiThreshold", 45.0)
self._hourly = self.Param("HourlyCandleType", DataType.TimeFrame(TimeSpan.FromHours(1)))
self._four_hourly = self.Param("FourHourCandleType", DataType.TimeFrame(TimeSpan.FromHours(4)))
self._daily = self.Param("DailyCandleType", DataType.TimeFrame(TimeSpan.FromDays(1)))
self._ratings = {}
def GetWorkingSecurities(self):
return [
(self.Security, self._hourly.Value),
(self.Security, self._four_hourly.Value),
(self.Security, self._daily.Value),
]
def OnReseted(self):
super(technical_ratings_on_multi_frames_assets_strategy, self).OnReseted()
self._ratings = {}
def OnStarted2(self, time):
super(technical_ratings_on_multi_frames_assets_strategy, self).OnStarted2(time)
self._start_rating("1h", self._hourly.Value)
self._start_rating("4h", self._four_hourly.Value)
self._start_rating("1d", self._daily.Value)
def _start_rating(self, key, candle_type):
sma = SimpleMovingAverage()
sma.Length = int(self._sma_period.Value)
rsi = RelativeStrengthIndex()
rsi.Length = int(self._rsi_period.Value)
def on_candle(candle, sma_value, rsi_value):
if candle.State != CandleStates.Finished or not sma.IsFormed or not rsi.IsFormed:
return
close = float(candle.ClosePrice)
sma_v = float(sma_value)
rsi_v = float(rsi_value)
ma_vote = 1.0 if close > sma_v else (-1.0 if close < sma_v else 0.0)
bull = float(self._bull_rsi.Value)
bear = float(self._bear_rsi.Value)
rsi_vote = 1.0 if rsi_v >= bull else (-1.0 if rsi_v <= bear else 0.0)
self._ratings[key] = (ma_vote + rsi_vote) / 2.0
self._evaluate()
self.SubscribeCandles(candle_type).Bind(sma, rsi, on_candle).Start()
def _evaluate(self):
if len(self._ratings) < 3:
return
average = (self._ratings["1h"] + self._ratings["4h"] + self._ratings["1d"]) / 3.0
if average > 0 and self.Position <= 0:
self.BuyMarket(self.Volume + Math.Abs(self.Position))
elif average < 0 and self.Position >= 0:
self.SellMarket(self.Volume + Math.Abs(self.Position))
def CreateClone(self):
return technical_ratings_on_multi_frames_assets_strategy()