GitHub で見る
会議のライン Stochastic 戦略
概要
ミーティングライン Stochastic 戦略 は、MetaTrader のエキスパート Expert_AML_Stoch の StockSharp の実装です。これは、強気/弱気ミーティングラインのローソク足反転パターンと、Stochastic オシレーターの %D 信号ラインからの確認を組み合わせたものです。この戦略は、追加のモメンタム確認を伴うパターン認識へのルールベースのアプローチを必要とする裁量トレーダー向けに設計されています。高レベルの StockSharp API を使用することで、コードは簡潔かつテスト可能であり、ポートフォリオ管理やさらなる自動化のために簡単に拡張できます。
取引ロジック
ローソク足パターン フィルター
- この戦略は、最後の 2 つの完了したキャンドルを継続的に評価して、ミーティング ラインのフォーメーションを検出します。
- 強気のセットアップには、終値が前の終値の 10% 以内にある長い黒のローソク足に続いて長い白のローソク足が必要です。
- 弱気のセットアップには、同じ10%に近い位置にある長い白いローソク足に続いて長い黒いローソク足が必要です。
- ローソク足の平均実体サイズは、弱い実体を除外するために、構成可能な単純な移動平均を使用して計算されます。
Stochastic 確認
- Stochastic オシレーターの %D 信号ラインはローソク足信号を確認する必要があります。
- 強気のエントリーでは、%D が設定可能な売られすぎしきい値 (デフォルトは 30) を下回っていることが要求されます。
- 弱気のエントリーでは、%D が設定可能な買われすぎしきい値 (デフォルト 70) を超える必要があります。
退出ルール
- %D が下側出口レベル (デフォルト 20) または上側出口レベル (デフォルト 80) のいずれかを上方に通過すると、ショート ポジションがクローズされます。
- %D が同じレベルを下方にクロスすると、ロング ポジションがクローズされます。
- 反転注文は、既存のエクスポージャーを自動的にクローズし、反対方向に新しいポジションをオープンします。
ボリュームの処理
- この戦略は、それが正の場合は基本の
Volume プロパティを使用します。それ以外の場合は、MetaTrader の固定ロットの動作との互換性を保つために、デフォルトで単一ロットになります。
パラメーター
| 名前 |
説明 |
デフォルト |
注意事項 |
CandleType |
分析に使用される主なローソク足シリーズ。 |
15分の時間枠 |
StockSharp でサポートされているあらゆる DataType を受け入れます。 |
StochasticLength |
生の %K 計算のルックバック期間。 |
3 |
MetaTrader %K period をミラーリングします。 |
StochasticSmoothing |
%K (MetaTrader slowing) に適用される平滑化。 |
25 |
オシレーターの内部スムージングの長さを設定します。 |
StochasticSignal |
%D 信号線の平滑化期間。 |
36 |
MetaTrader %D period をミラーリングします。 |
BodyAveragePeriod |
キャンドル本体のサイズを平均するために使用されるキャンドルの数。 |
3 |
会議のラインを発見するときにマイナーボディを除外します。 |
LongEntryLevel |
強気のエントリーを可能にする最大 %D 値。 |
30 |
売られ過ぎのしきい値に相当します。 |
ShortEntryLevel |
弱気エントリーに必要な最小 %D 値。 |
70 |
買われすぎのしきい値に相当します。 |
ExitLowerLevel |
上向きクロスでエグジットをトリガーする下限境界。 |
20 |
長期および短期の両方の終了決定に使用されます。 |
ExitUpperLevel |
下向きのクロスでエグジットをトリガーする上限。 |
80 |
長期および短期の両方の終了決定に使用されます。 |
すべてのパラメータは StrategyParam<T> を通じて公開され、StockSharp デザイナーで直接、またはプログラムで最適化できます。
信号の生成
- ロングエントリー: 強気のミーティングライン + %D が
LongEntryLevel を下回っており、既存のロングエクスポージャーはありません (ショートは反転されています)。
- ショートエントリー: 弱気のミーティングライン + %D が
ShortEntryLevel を上回っており、既存のショートエクスポージャーはありません (ロングは反転されています)。
- ロングイグジット: %D は
ExitUpperLevel または ExitLowerLevel を下回ります。
- ショート終了: %D が
ExitLowerLevel または ExitUpperLevel を超えています。
実装メモ
- インジケーター データは
BindEx を介して処理され、手動によるインジケーター収集管理を回避します。
- ローソク足の実体の平均化では、
DecimalIndicatorValue を通じて絶対実体サイズが供給された SimpleMovingAverage を使用し、MetaTrader ヘルパー AvgBody と一致します。
- コード内のすべてのコメントは英語で書かれており、インデントはプロジェクト ガイドラインに従ってタブ文字に依存しています。
- この戦略は、チャート領域が利用可能なときにローソク足と確率オシレーターを自動的に描画し、ライブ監視を簡素化します。
使用のヒント
- 最適化: 公開されたパラメータをウォークフォワード テストに使用して、取引商品に合わせてしきい値を調整します。
- リスク管理: StockSharp に組み込まれた
StartProtection または運用環境の導入のための外部のポートフォリオ レベルのリスク制御を使用して戦略を階層化します。
- データ品質: ミーティング ライン パターンは、正確な始値/終値の影響を受けます。フィードの調整と非流動性セッションのフィルタリングを保証します。
- タイムフレーム: デフォルトは 15 分ですが、
CandleType を変更することで日中または日次データを使用できます。
この戦略は、ローソク足のフォーメーションに依存しているが誤検知を減らすためにオシレーターの確認を必要とするトレーダーに規律あるアプローチを提供します。
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Meeting Lines + Stochastic strategy.
/// Buys on bullish meeting lines with low stochastic, sells on bearish meeting lines with high stochastic.
/// </summary>
public class MeetingLinesStochasticStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _stochPeriod;
private readonly StrategyParam<decimal> _stochLow;
private readonly StrategyParam<decimal> _stochHigh;
private ICandleMessage _prevCandle;
private ICandleMessage _prevPrevCandle;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int StochPeriod { get => _stochPeriod.Value; set => _stochPeriod.Value = value; }
public decimal StochLow { get => _stochLow.Value; set => _stochLow.Value = value; }
public decimal StochHigh { get => _stochHigh.Value; set => _stochHigh.Value = value; }
public MeetingLinesStochasticStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_stochPeriod = Param(nameof(StochPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Stochastic Period", "Stochastic K period", "Indicators");
_stochLow = Param(nameof(StochLow), 30m)
.SetDisplay("Stoch Low", "Stochastic oversold level", "Signals");
_stochHigh = Param(nameof(StochHigh), 70m)
.SetDisplay("Stoch High", "Stochastic overbought level", "Signals");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCandle = null;
_prevPrevCandle = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevCandle = null;
_prevPrevCandle = null;
var stoch = new StochasticOscillator { K = { Length = StochPeriod }, D = { Length = 3 } };
var subscription = SubscribeCandles(CandleType);
subscription.BindEx(stoch, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue stochValue)
{
if (candle.State != CandleStates.Finished) return;
var stochTyped = stochValue as StochasticOscillatorValue;
if (stochTyped?.K is not decimal kValue) { UpdateState(candle); return; }
if (_prevCandle != null && _prevPrevCandle != null)
{
var avgBody = (Math.Abs(_prevCandle.ClosePrice - _prevCandle.OpenPrice) +
Math.Abs(_prevPrevCandle.ClosePrice - _prevPrevCandle.OpenPrice)) / 2m;
if (avgBody > 0)
{
// Bullish meeting lines: prev bearish, current bullish, closes near
var prevBearish = _prevCandle.OpenPrice > _prevCandle.ClosePrice &&
(_prevCandle.OpenPrice - _prevCandle.ClosePrice) > avgBody * 0.5m;
var currBullish = candle.ClosePrice > candle.OpenPrice &&
(candle.ClosePrice - candle.OpenPrice) > avgBody * 0.5m;
var closesNear = Math.Abs(candle.ClosePrice - _prevCandle.ClosePrice) < avgBody * 0.3m;
if (prevBearish && currBullish && closesNear && kValue < StochLow && Position <= 0)
BuyMarket();
// Bearish meeting lines: prev bullish, current bearish, closes near
var prevBullish = _prevCandle.ClosePrice > _prevCandle.OpenPrice &&
(_prevCandle.ClosePrice - _prevCandle.OpenPrice) > avgBody * 0.5m;
var currBearish = candle.OpenPrice > candle.ClosePrice &&
(candle.OpenPrice - candle.ClosePrice) > avgBody * 0.5m;
var closesNear2 = Math.Abs(candle.ClosePrice - _prevCandle.ClosePrice) < avgBody * 0.3m;
if (prevBullish && currBearish && closesNear2 && kValue > StochHigh && Position >= 0)
SellMarket();
}
}
UpdateState(candle);
}
private void UpdateState(ICandleMessage candle)
{
_prevPrevCandle = _prevCandle;
_prevCandle = candle;
}
}
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 StochasticOscillator
from StockSharp.Algo.Strategies import Strategy
class meeting_lines_stochastic_strategy(Strategy):
def __init__(self):
super(meeting_lines_stochastic_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._stoch_period = self.Param("StochPeriod", 14)
self._stoch_low = self.Param("StochLow", 30.0)
self._stoch_high = self.Param("StochHigh", 70.0)
self._prev_candle = None
self._prev_prev_candle = None
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def StochPeriod(self):
return self._stoch_period.Value
@StochPeriod.setter
def StochPeriod(self, value):
self._stoch_period.Value = value
@property
def StochLow(self):
return self._stoch_low.Value
@StochLow.setter
def StochLow(self, value):
self._stoch_low.Value = value
@property
def StochHigh(self):
return self._stoch_high.Value
@StochHigh.setter
def StochHigh(self, value):
self._stoch_high.Value = value
def OnReseted(self):
super(meeting_lines_stochastic_strategy, self).OnReseted()
self._prev_candle = None
self._prev_prev_candle = None
def OnStarted2(self, time):
super(meeting_lines_stochastic_strategy, self).OnStarted2(time)
self._prev_candle = None
self._prev_prev_candle = None
stoch = StochasticOscillator()
stoch.K.Length = self.StochPeriod
stoch.D.Length = 3
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(stoch, self._process_candle).Start()
def _process_candle(self, candle, stoch_value):
if candle.State != CandleStates.Finished:
return
k_val = stoch_value.K
if k_val is None:
self._update_state(candle)
return
k_value = float(k_val)
if self._prev_candle is not None and self._prev_prev_candle is not None:
avg_body = (abs(float(self._prev_candle.ClosePrice) - float(self._prev_candle.OpenPrice))
+ abs(float(self._prev_prev_candle.ClosePrice) - float(self._prev_prev_candle.OpenPrice))) / 2.0
if avg_body > 0:
# Bullish meeting lines
prev_bearish = (float(self._prev_candle.OpenPrice) > float(self._prev_candle.ClosePrice)
and (float(self._prev_candle.OpenPrice) - float(self._prev_candle.ClosePrice)) > avg_body * 0.5)
curr_bullish = (float(candle.ClosePrice) > float(candle.OpenPrice)
and (float(candle.ClosePrice) - float(candle.OpenPrice)) > avg_body * 0.5)
closes_near = abs(float(candle.ClosePrice) - float(self._prev_candle.ClosePrice)) < avg_body * 0.3
if prev_bearish and curr_bullish and closes_near and k_value < self.StochLow and self.Position <= 0:
self.BuyMarket()
# Bearish meeting lines
prev_bullish = (float(self._prev_candle.ClosePrice) > float(self._prev_candle.OpenPrice)
and (float(self._prev_candle.ClosePrice) - float(self._prev_candle.OpenPrice)) > avg_body * 0.5)
curr_bearish = (float(candle.OpenPrice) > float(candle.ClosePrice)
and (float(candle.OpenPrice) - float(candle.ClosePrice)) > avg_body * 0.5)
closes_near2 = abs(float(candle.ClosePrice) - float(self._prev_candle.ClosePrice)) < avg_body * 0.3
if prev_bullish and curr_bearish and closes_near2 and k_value > self.StochHigh and self.Position >= 0:
self.SellMarket()
self._update_state(candle)
def _update_state(self, candle):
self._prev_prev_candle = self._prev_candle
self._prev_candle = candle
def CreateClone(self):
return meeting_lines_stochastic_strategy()