GitHub で見る
Suffic369 戦略
概要
Suffic369 戦略は、2 つの短い移動平均と幅の広い Bollinger バンドを組み合わせたトレンド追跡ブレイクアウト システムです。エキスパートアドバイザーは、市場が下限バンドBollinger付近で取引されているときに、終値の高速単純移動平均(SMA)が最近の高値のSMAを上回ったときにロングポジションをエントリーします。価格が上部バンドに迫っているときに、速い SMA が最近の安値の SMA を下回ったときに、ショート ポジションがオープンされます。変換された StockSharp バージョンは、元の MQL ロジックを保持しますが、それを高レベルのローソク足サブスクリプションとインジケーター バインディングで表現します。
インジケーター
- Fast SMA (終値、長さ = 3) – 終値の短期方向を測定します。
- 高値 SMA (高値、長さ = 5) – 最近の高値を平均し、強気の抵抗基準として機能します。
- 安値 SMA (安値、長さ = 5) – 最近の安値を平均し、弱気のサポート基準を提供します。
- Bollinger バンド (長さ = 156、偏差 = 1) – ボラティリティに対する価格の極端な値を特定します。
すべてのインジケーターは完了したローソク足で更新されます。元の MetaTrader プログラムで使用されている 1 小節のシフトを再現するために、以前の値がキャッシュされます。
取引ルール
ロングエントリー
- 前回の最高値 SMA (終値) は、前回の最高値 SMA を下回っています。
- 現在の高値 SMA (終値) は現在の高値 SMA を上回っています。
- ローソク足の終値が Bollinger バンドの下限を下回っています。
ショートエントリー
- 以前の速い値 SMA (終値) は、前の安値 SMA を上回っています。
- 現在の速い値 SMA (終値) は、現在の安値 SMA を下回ります。
- ローソク足の終値は上部 Bollinger バンドを上回っています。
終了ロジック
- 反対のシグナル: 新たなショートエントリーシグナルが現れるとロングポジションはクローズされ、その逆も同様です。
- ストップロス: アクティブ化されたポジションを保護する、オプションの価格ステップベースのストップ。
- テイクプロフィット: 元のテイクプロフィットパラメータをミラーリングする、オプションの価格ステップベースのターゲット。
- トレーリング ストップ: MQL ロジックとまったく同様に、収益性の高い取引の背後で引き締めるオプションのトレーリング ストップ (利益が設定された距離を超えた場合にのみ、現在のクローズを使用してストップを移動します)。
ストラテジーは一度に最大 1 つのポジションを保持します。ストップ、ターゲット、または反対のシグナルによって取引が終了した後は、次のローソク足が終了するまで新しいエントリーは評価されません。
パラメーター
| 名前 |
デフォルト |
説明 |
FastMaLength |
3 |
終値に基づいて構築された高速 SMA の長さ。 |
HighMaLength |
5 |
ローソク足の高値に基づいて計算された SMA の長さ。 |
LowMaLength |
5 |
ローソク足の安値に基づいて計算された SMA の長さ。 |
BollingerLength |
156 |
Bollinger バンドのウィンドウ サイズ。 |
BollingerDeviation |
1 |
バンドの標準偏差乗数。 |
UseStopLoss |
本当の |
ストップロスブロックを有効にします。 |
StopLossPoints |
30 |
商品価格ステップにおけるストップ距離。 |
UseTakeProfit |
本当の |
テイクプロフィットブロックを有効にします。 |
TakeProfitPoints |
60 |
価格ステップでの利益目標距離。 |
UseTrailingStop |
本当の |
トレーリングストップ管理を有効にします。 |
TrailingStopPoints |
30 |
価格ステップの末尾オフセット。 |
CandleType |
15分の時間枠 |
計算に使用されるローソクの種類。 |
すべての数値パラメータは StrategyParam<T> インスタンスとして公開されるため、StockSharp 内で直接最適化できます。
リスク管理
- ストップロス、テイクプロフィット、トレーリングストップは、商品価格ステップ (
Security.PriceStep) を使用してポイント距離を絶対価格に変換します。
- トレーリングストップは、価格が設定された距離よりも進んだ場合にのみ、利益の上がる動きに従い、元の注文変更ロジックを複製します。
StartProtection() は起動時に呼び出され、StockSharp の組み込み保護機能が有効になります。
使用上の注意
- 選択したローソク足タイプをサポートする商品にストラテジーをサブスクライブします。
- 戦略を開始する前に、
Volume プロパティが希望の取引サイズに設定されていることを確認してください。
- この戦略は、完全に形成されたインジケーター値を待ってから注文を発行します。最初のローソク足はインジケーター履歴をシードするために使用されます。
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Suffic369 breakout strategy based on fast/slow SMA crossover.
/// Buy when fast SMA crosses above slow SMA, sell when fast crosses below slow.
/// </summary>
public class Suffic369Strategy : Strategy
{
private readonly StrategyParam<int> _fastMaLength;
private readonly StrategyParam<int> _slowMaLength;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
/// <summary>
/// Fast SMA length.
/// </summary>
public int FastMaLength
{
get => _fastMaLength.Value;
set => _fastMaLength.Value = value;
}
/// <summary>
/// Slow SMA length.
/// </summary>
public int SlowMaLength
{
get => _slowMaLength.Value;
set => _slowMaLength.Value = value;
}
/// <summary>
/// Candle type used for calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="Suffic369Strategy"/> class.
/// </summary>
public Suffic369Strategy()
{
_fastMaLength = Param(nameof(FastMaLength), 3)
.SetDisplay("Fast SMA Length", "Fast moving average period", "Indicators");
_slowMaLength = Param(nameof(SlowMaLength), 6)
.SetDisplay("Slow SMA Length", "Slow moving average period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Primary candle source", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0m;
_prevSlow = 0m;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fastSma = new SimpleMovingAverage { Length = FastMaLength };
var slowSma = new SimpleMovingAverage { Length = SlowMaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastSma, slowSma, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev)
{
_prevFast = fast;
_prevSlow = slow;
_hasPrev = true;
return;
}
// Buy signal: fast SMA crosses above slow SMA
var longSignal = _prevFast <= _prevSlow && fast > slow;
// Sell signal: fast SMA crosses below slow SMA
var shortSignal = _prevFast >= _prevSlow && fast < slow;
if (Position > 0 && shortSignal)
{
SellMarket();
}
else if (Position < 0 && longSignal)
{
BuyMarket();
}
else if (Position == 0)
{
if (longSignal)
BuyMarket();
else if (shortSignal)
SellMarket();
}
_prevFast = fast;
_prevSlow = slow;
}
}
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
from indicator_extensions import *
class suffic369_strategy(Strategy):
"""Fast/slow SMA crossover (3/6)."""
def __init__(self):
super(suffic369_strategy, self).__init__()
self._fast_ma_length = self.Param("FastMaLength", 3).SetDisplay("Fast SMA Length", "Fast moving average period", "Indicators")
self._slow_ma_length = self.Param("SlowMaLength", 6).SetDisplay("Slow SMA Length", "Slow moving average period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))).SetDisplay("Candle Type", "Primary candle source", "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(suffic369_strategy, self).OnReseted()
self._prev_fast = 0
self._prev_slow = 0
self._has_prev = False
def OnStarted2(self, time):
super(suffic369_strategy, self).OnStarted2(time)
self._prev_fast = 0
self._prev_slow = 0
self._has_prev = False
fast_sma = SimpleMovingAverage()
fast_sma.Length = self._fast_ma_length.Value
slow_sma = SimpleMovingAverage()
slow_sma.Length = self._slow_ma_length.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(fast_sma, slow_sma, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, fast_sma)
self.DrawIndicator(area, slow_sma)
self.DrawOwnTrades(area)
def OnProcess(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
if not self._has_prev:
self._prev_fast = fast
self._prev_slow = slow
self._has_prev = True
return
long_signal = self._prev_fast <= self._prev_slow and fast > slow
short_signal = self._prev_fast >= self._prev_slow and fast < slow
if self.Position > 0 and short_signal:
self.SellMarket()
elif self.Position < 0 and long_signal:
self.BuyMarket()
elif self.Position == 0:
if long_signal:
self.BuyMarket()
elif short_signal:
self.SellMarket()
self._prev_fast = fast
self._prev_slow = slow
def CreateClone(self):
return suffic369_strategy()