GitHub で見る
OHLC 確認ストラテジー
概要
OHLC 確認ストラテジーは、前のローソク足の始値・高値・安値・終値の構造を検査するクラシックな MetaTrader エキスパートアドバイザーを再現します。このストラテジーは設定可能な過去のオフセットでローソク足の実体を評価し、その実体の方向に新しいポジションを開き、オプションでシグナルを反転させることができます。オシレーターや移動平均に依存せず、シンプルな価格行動ベースの実行のために設計されています。
トレーディングロジック
- ストラテジーは設定されたローソク足シリーズを購読し、処理前にバーが完成するのを待ちます。
- 完成した各ローソク足について、エンジンは始値と終値を保存し、ユーザー定義のシフト("SignalShift")が古いバーを参照できるようにします。
- 強気の実体(終値が始値を上回る)はロングシグナルを生成し、弱気の実体(終値が始値を下回る)はショートシグナルを生成します。実体がフラットの場合、取引は作成されません。
ReverseSignals フラグは取引方向を反転させ、元のエキスパートアドバイザーのリバーストレードモードを再現できます。
- アクティブなポジションがない場合、現在のスプレッドが許可された
SpreadLimitPips 閾値内であれば、ストラテジーは検出された方向に成行注文を開くことを試みます。スプレッドは板情報フィードを使用して監視されます。
- ポジションがすでに存在する場合、反対のシグナルは完全な反転ではなくポジションのクローズをトリガーし、MQL ロジックに一致します。
- オプションのストップロスとテイクプロフィットの保護は、起動時に pip 距離を使用して開始され、インストゥルメントの価格ステップに変換され、MQL のマネー管理動作を再現します。
パラメーター
| パラメーター |
デフォルト |
説明 |
CandleType |
5分足の時間軸 |
OHLC 評価に使用するデータシリーズ。 |
StopLossPips |
50 |
pip で測定したストップロス距離;0 でストップを無効化。 |
TakeProfitPips |
100 |
pip で測定したテイクプロフィット距離;0 でターゲットを無効化。 |
ReverseSignals |
false |
ロングとショートのシグナルの方向を反転します。 |
SpreadLimitPips |
1 |
新しいポジションを開く際に許可される最大スプレッド(pip 単位)。 |
SignalShift |
1 |
シグナル計算に使用する完了したローソク足の数(1 = 前のローソク足)。 |
OrderVolume |
1 |
各成行注文で送信するボリューム。 |
使用上の注意
- ストラテジーはインストゥルメントのメタデータを使用して pip 値を価格ステップ距離に変換します。小数点以下 3 桁または 5 桁のインストゥルメントは自動的に標準の 10 ポイント pip 調整を受けます。
- スプレッドチェックが正しく機能するには、データフィードで板情報の購読を有効にする必要があります。bid/ask 気配値が利用できない場合、ストラテジーは新規取引の開始をスキップします。
- 保護ストップは
OnStarted 中に一度開始されます。その後にストップパラメーターを変更する場合、新しい保護を適用するにはストラテジーを再起動する必要があります。
- ストラテジーはローソク足の実体にのみ反応するため、高値と安値の値は元の MetaTrader バージョンと同様に無視されます。
デプロイ手順
- ローソク足と板情報の両方を提供するインストゥルメントにストラテジーをアタッチします。
- 希望するトレーディングスタイル(時間軸、pip 距離、ボリューム)に従ってパラメーターを設定します。
- ストラテジーを起動します。次の完成したローソク足を待ってからアクションを実行します。
- スプレッドによる拒否や実行された取引のログを監視し、必要に応じてパラメーターを調整します。
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>
/// OHLC check strategy. Trades based on candle structure (bullish/bearish body).
/// </summary>
public class OhlcCheckStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _confirmBars;
private int _bullCount;
private int _bearCount;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int ConfirmBars
{
get => _confirmBars.Value;
set => _confirmBars.Value = value;
}
public OhlcCheckStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_confirmBars = Param(nameof(ConfirmBars), 3)
.SetGreaterThanZero()
.SetDisplay("Confirm Bars", "Consecutive candles to confirm direction", "Trading");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_bullCount = 0;
_bearCount = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_bullCount = 0;
_bearCount = 0;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (candle.ClosePrice > candle.OpenPrice)
{
_bullCount++;
_bearCount = 0;
}
else if (candle.ClosePrice < candle.OpenPrice)
{
_bearCount++;
_bullCount = 0;
}
// Consecutive bullish candles → buy
if (_bullCount >= ConfirmBars && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
_bullCount = 0;
}
// Consecutive bearish candles → sell
else if (_bearCount >= ConfirmBars && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
_bearCount = 0;
}
}
}
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.Strategies import Strategy
class ohlc_check_strategy(Strategy):
def __init__(self):
super(ohlc_check_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._confirm_bars = self.Param("ConfirmBars", 3) \
.SetDisplay("Confirm Bars", "Consecutive candles to confirm direction", "Trading")
self._bull_count = 0
self._bear_count = 0
@property
def CandleType(self):
return self._candle_type.Value
@property
def ConfirmBars(self):
return self._confirm_bars.Value
def OnReseted(self):
super(ohlc_check_strategy, self).OnReseted()
self._bull_count = 0
self._bear_count = 0
def OnStarted2(self, time):
super(ohlc_check_strategy, self).OnStarted2(time)
self._bull_count = 0
self._bear_count = 0
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _on_process(self, candle):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
open_price = float(candle.OpenPrice)
if close > open_price:
self._bull_count += 1
self._bear_count = 0
elif close < open_price:
self._bear_count += 1
self._bull_count = 0
cb = int(self.ConfirmBars)
# Consecutive bullish candles
if self._bull_count >= cb and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._bull_count = 0
# Consecutive bearish candles
elif self._bear_count >= cb and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._bear_count = 0
def CreateClone(self):
return ohlc_check_strategy()