GitHub で見る
GPF TCPivotLimit 戦略
概要
GPF TCPivotLimit 戦略 は、StockSharp フレームワーク内に MetaTrader 4 エキスパート アドバイザー gpfTCPivotLimit.mq4 を再作成します。このシステムは時間足のローソク足に基づいて取引され、古典的な日次ピボットレベル付近の反転に反応します。新しい取引日ごとに、戦略は前日の高値、安値、終値からピボット、3 つのレジスタンス レベル (R1 ~ R3)、および 3 つのサポート レベル (S1 ~ S3) を計算します。翌日が始まるとすぐに、最後に完了した 2 つの時間足ローソク足を評価して、価格がレジスタンスゾーンまたはサポートゾーンを拒否したかどうかを判断し、反対方向に成行注文を開きます。
取引ロジック
- ピボット計算 – 新しい日次セッションが開始されると、戦略は前日の高値、安値、終値を保存し、次を計算します。
Pivot = (High + Low + Close) / 3
R1 = 2 × Pivot − Low、S1 = 2 × Pivot − High
R2 = Pivot + (High − Low)、S2 = Pivot − (High − Low)
R3 = High + 2 × (Pivot − Low)、S3 = Low − 2 × (High − Pivot)
- エントリの確認 – 新しい日が始まると、最後の 2 つの閉じた時間足ローソク足 (
t-2 と t-1) が検査されます。
- ショートは、ローソク足
t-2 が選択した抵抗値を上回って(そのレベルより上または近い)、その下でオープンし、ローソク足 t-1 がそのレベルの下で閉じた場合にオープンされます。
- ロングは、ローソク足
t-2 が選択したサポートの下に沈み(レベルの下で低いか、そのレベルで近い)、そのサポートの上で開かれ、ローソク足 t-1 がレベルの上で閉じた場合に開かれます。
- ターゲット プリセット – オリジナルのエキスパート アドバイザは 5 つのプロフィット/ストップ レイアウトを公開します。以下の表は、このポートに保存されている正確なマッピングを示しています。
TargetMode |
ロングトリガー |
長い停車時間 |
ロングターゲット |
ショートトリガー |
ショートストップ |
ショートターゲット |
| 1 |
S1 |
S2 |
R1 |
R1 |
R2 |
S1 |
| 2 |
S1 |
S2 |
R2 |
R1 |
R2 |
S2 |
| 3 |
S2 |
S3 |
R1 |
R2 |
R3 |
S1 |
| 4 |
S2 |
S3 |
R2 |
R2 |
R3 |
S2 |
| 5 |
S2 |
S3 |
R3 |
R2 |
R3 |
S3 |
リスク管理 – 完了したすべてのキャンドルに対して保護的なストップロスとテイクプロフィットのチェックが実行されます。オプションのトレーリング ストップ ロジックは MT4 の動作をエミュレートします。未実現利益が設定された距離を超えると、取引に有利にストップが移動します。オプションの一日の終わりの出口は、プラットフォーム時間の 23:00 にポジションを平らにします。
音量調整 – MetaTrader 入力 isFloatLots は、UseDynamicVolume トグルによってミラーされます。有効にすると、DrawdownFactor および RiskPercentage 入力を使用して、連続して負けた取引の後にポジション サイズが減少します。
パラメーター
| 名前 |
説明 |
デフォルト |
BaseVolume |
リスク調整前の各成行注文で提出された基準数量。 |
1 |
UseDynamicVolume |
2 回以上連続して負けた場合、取引サイズが減少します。 |
false |
RiskPercentage |
基本ボリューム (MetaTrader MaxR) をスケールするために使用される取引あたりのリスク比率を参照します。 |
0.02 |
DrawdownFactor |
連敗後にボリュームを縮小するときに適用される除数 (MetaTrader DcF)。 |
3 |
TargetMode |
上記のレジスタンス/サポートの組み合わせを選択します (MetaTrader TgtProfit)。 |
1 |
TrailingPoints |
トレーリングストップ距離は計器点で表されます。無効にするには、0 に設定します。 |
30 |
CloseAtSessionEnd |
true のとき、23:00 のローソク足の終値ですべてのポジションがクローズされます。 |
false |
LogSignals |
ピボット値、エントリ、および終了を戦略ログに出力します。 |
false |
CandleType |
分析に使用されるローソク足のデータ型 (デフォルトは 1 時間足ローソク足)。 |
TimeFrameCandleMessage(1h) |
注意事項
- この戦略は、元の EA と同様に 成行注文を発行し、保留中の注文は出しません。
- すべての StockSharp コネクタとの互換性を維持するために、ストップロスとテイクプロフィットのイベントは市場の出口で実行されます。
- 後続距離は機器
PriceStep に依存します。ステップが欠落している場合、トレーリング機構は自動的に無効になります。
- MT4 バージョンのメール通知フラグは
LogSignals で表され、メールの代わりにログ メッセージが生成されます。
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class GpfTcpPivotLimitStrategy : Strategy
{
private readonly StrategyParam<int> _channelPeriod;
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevClose; private decimal _prevMid; private bool _hasPrev;
private int _cooldown;
public int ChannelPeriod { get => _channelPeriod.Value; set => _channelPeriod.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public GpfTcpPivotLimitStrategy()
{
_channelPeriod = Param(nameof(ChannelPeriod), 20).SetDisplay("Channel Period", "Pivot lookback", "Indicators");
_emaPeriod = Param(nameof(EmaPeriod), 14).SetDisplay("EMA Period", "EMA filter", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = default;
_prevMid = default;
_hasPrev = default;
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var highest = new Highest { Length = ChannelPeriod };
var lowest = new Lowest { Length = ChannelPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(highest, lowest, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal highest, decimal lowest)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) return;
var close = candle.ClosePrice;
var mid = (highest + lowest) / 2;
if (!_hasPrev) { _prevClose = close; _prevMid = mid; _hasPrev = true; return; }
if (_cooldown > 0)
{
_cooldown--;
_prevClose = close; _prevMid = mid;
return;
}
if (_prevClose <= _prevMid && close > mid && Position <= 0)
{
var volume = Volume + Math.Abs(Position);
BuyMarket(volume);
_cooldown = 2;
}
else if (_prevClose >= _prevMid && close < mid && Position >= 0)
{
var volume = Volume + Math.Abs(Position);
SellMarket(volume);
_cooldown = 2;
}
_prevClose = close; _prevMid = mid;
}
}
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 Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class gpf_tcp_pivot_limit_strategy(Strategy):
"""
GPF TCP Pivot Limit: Donchian channel midline crossover.
Buys when close crosses above channel midpoint.
Sells when close crosses below channel midpoint.
"""
def __init__(self):
super(gpf_tcp_pivot_limit_strategy, self).__init__()
self._channel_period = self.Param("ChannelPeriod", 20) \
.SetDisplay("Channel Period", "Pivot lookback", "Indicators")
self._ema_period = self.Param("EmaPeriod", 14) \
.SetDisplay("EMA Period", "EMA filter", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_close = 0.0
self._prev_mid = 0.0
self._has_prev = False
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(gpf_tcp_pivot_limit_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_mid = 0.0
self._has_prev = False
self._cooldown = 0
def OnStarted2(self, time):
super(gpf_tcp_pivot_limit_strategy, self).OnStarted2(time)
highest = Highest()
highest.Length = self._channel_period.Value
lowest = Lowest()
lowest.Length = self._channel_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(highest, lowest, self._process_candle).Start()
def _process_candle(self, candle, highest_val, lowest_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
h = float(highest_val)
l = float(lowest_val)
mid = (h + l) / 2.0
if not self._has_prev:
self._prev_close = close
self._prev_mid = mid
self._has_prev = True
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_close = close
self._prev_mid = mid
return
if self._prev_close <= self._prev_mid and close > mid and self.Position <= 0:
self.BuyMarket()
self._cooldown = 2
elif self._prev_close >= self._prev_mid and close < mid and self.Position >= 0:
self.SellMarket()
self._cooldown = 2
self._prev_close = close
self._prev_mid = mid
def CreateClone(self):
return gpf_tcp_pivot_limit_strategy()