GitHub で見る
Gターミナル戦略
概要
G Terminal 戦略は、MetaTrader 4 Expert Advisor GTerminal_V5a の C# ポートです。オリジナルスクリプト許可マニュアル
チャート上に水平線を引くことでエントリーとエグジットを制御します。このポートは内部で同じ行駆動の動作を再現します。
各仮想回線を構成可能なパラメータとして公開することで、StockSharp フレームワークを構築します。選択した銘柄の終値が確定するたびに、
ローソク足シリーズがこれらの仮想ラインの 1 つを横切ると、戦略は MQL4 と同じ方法でポジションをオープン、クローズ、または反転します。
バージョン。オプションの自動保護レベルは、元のツールの「tpinit」および「slinit」ヘルパー ラインをエミュレートします。
戦略ロジック
価格サンプリング
- この戦略は、ユーザー定義の時間枠 (
CandleType) の終了したローソク足に対して機能します。
StartShift は、基準終値として使用されるローソク足を制御します。 0 の値は現在のローソク足の終値を使用し、1 は
前のローソク足など。シフトは比較ローソク足にも影響するため、スクリプトは常に次のように 2 つの連続する終値を評価します。
MetaTrader の実装。
CrossMethod は MQL4 入力をミラーリングします。
0 – 厳密なクロス: 前回の終値はレベルを下回る (長いトリガーの場合) か、上にある (短いトリガーの場合) 必要があります。
現在のクローズはレベルの反対側で終了する必要があります。
1 – 即時トリガー: 現在の終値がそのレベルより上または下にあることのみが必要です。ポートは引き続き前回のクローズをチェックします。
同じバーでの複数のトリガーを防止し、行を削除することで MetaTrader で得られた「一度タッチ」動作を再現します。
点火した後。
エントリールール
- ストップラインの買い – 終値が下から
BuyStopLevel の上に移動すると、戦略は買います。ショートポジションがオープンしている場合、
注文サイズには、ショートを平坦化するために必要な量と、新しい長時間露光用に設定された Volume が含まれます。
- 買い指値ライン – 終値が
BuyLimitLevel を下回ると、同じボリュームロジックを使用してロングポジションがオープンされます。
- 売りストップライン – 終値が上から
SellStopLevel の下に移動すると、戦略は売りになります。既存のロングは次のようにクローズされます
注文数量の一部。
- 売りリミットライン – 終値が
SellLimitLevel を通過すると、ショートポジションがオープンします。
Volume が 0 であるか、PauseTrading が有効な場合、エントリは無視されます。
終了ルール
- 方向性出口 –
LongStopLevel と LongTakeProfitLevel は、終値がそれぞれの終値を横切ったときに長辺を閉じます。
ライン。 ShortStopLevel と ShortTakeProfitLevel は短時間露出でも同じことを行います。
- グローバル イグジット –
AllLongStopLevel / AllLongTakeProfitLevel は、オープン方法に関係なく、すべてのロング ポジションを清算します。
AllShortStopLevel / AllShortTakeProfitLevel はショートのロジックをミラーリングします。
- 初期保護 –
UseInitialProtection を true に設定すると、InitialLongStopLevel、InitialLongTakeProfitLevel、
新しいポジションが埋まった直後の InitialShortStopLevel、および InitialShortTakeProfitLevel。これらのレベルは次のように動作します。
元のスクリプトの「slinit」/「tpinit」ヘルパー行は、ポジションがクローズされるかレベルが更新されるまでアクティブのままです。
- ローソクごとに 1 つの終了アクションのみが送信されます。終了条件が満たされると、ストラテジーは決済注文を送信し、決済注文をスキップします。
行が起動された後に MQL4 バージョンが停止したのと同じように、そのバーの残りのチェックが行われます。
一時停止制御
PauseTrading は、MetaTrader の「PAUSE」行の機能を再現します。有効にすると、開始ロジックまたは終了ロジックは評価されません。
状態は、戦略を再ロードせずに手動で切り替えることができます。
パラメーター
- ボリューム – 新規エントリーの注文ボリューム。最終的な注文サイズには、必要な反対側の露出が自動的に含まれます。
反転中にクローズ。
- クロスメソッド – クロスアルゴリズム (
0 厳密、1 インスタント) を選択します。
- Start Shift – クロスの計算に使用されるローソク足のオフセット。
- 取引を一時停止 –
trueの間、すべての取引アクションを無効にします。
- 初期保護を使用 – 各約定後の初期ストップ/テイクプロフィットレベルの自動適用を有効にします。
- 買いストップレベル/買い指値レベル – ロングエントリーをトリガーする価格レベル。
- 売りストップレベル/売り指値レベル – ショートエントリーをトリガーする価格レベル。
- ロングストップレベル/ロングテイクプロフィット – アクティブなロングポジションのエグジットライン。
- ショートストップレベル/ショートテイクプロフィット – アクティブなショートポジションのエグジットライン。
- オール ロング ストップ / オール ロング テイク プロフィット – すべてのロング ポジションをクローズするグローバル イグジット ライン。
- オールショートストップ/オールショートテイクプロフィット – すべてのショートポジションをクローズするグローバルイグジットライン。
- 初期ロングストップ / 初期ロングテイクプロフィット – 初期保護が設定されている場合、各ロングエントリー後に保護レベルが有効になります。
有効になりました。
- 初期ショートストップ/初期ショートテイクプロフィット – 初期保護が設定されている場合、各ショートエントリー後に保護レベルが有効になります。
有効になりました。
- ローソク タイプ – 比較に使用される終値を提供する時間枠。
実装メモ
- ポートはラインベースのワークフローを維持しますが、チャート オブジェクトに依存するのではなく、各ラインをパラメーターとして公開します。ユーザーは次のことができます
MetaTrader チャート上で線が移動する方法を模倣して、パラメータ グリッドを通じてレベルをその場で更新します。
- 元のスクリプトからのインジケーター ウィンドウ トリガー (RSI、CCI、Momentum など) は、このバージョンでは使用できません。すべてのトリガー
終値のみを使用してください。インジケーター主導の動作であれば、パラメーター セットを他の StockSharp コンポーネントと組み合わせることができます。
が必要です。
- この戦略は、成行注文を使用した MQL4 スクリプトと同様に、成行注文 (
BuyMarket、SellMarket) のみに依存します。
保留中の行の実行をエミュレートします。
- Python の実装はありません。このパッケージでは C# バージョンのみが提供されます。
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class GTerminalStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public GTerminalStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 9).SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 26).SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = default;
_prevSlow = default;
_hasPrev = default;
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) return;
if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }
if (_cooldown > 0)
{
_cooldown--;
_prevFast = fast;
_prevSlow = slow;
return;
}
if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
{
var volume = Volume + Math.Abs(Position);
BuyMarket(volume);
_cooldown = 2;
}
else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
{
var volume = Volume + Math.Abs(Position);
SellMarket(volume);
_cooldown = 2;
}
_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, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class g_terminal_strategy(Strategy):
def __init__(self):
super(g_terminal_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 9).SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 26).SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))).SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
self._cooldown = 0
@property
def fast_period(self): return self._fast_period.Value
@property
def slow_period(self): return self._slow_period.Value
@property
def candle_type(self): return self._candle_type.Value
def OnReseted(self):
super(g_terminal_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
self._cooldown = 0
def OnStarted2(self, time):
super(g_terminal_strategy, self).OnStarted2(time)
self._has_prev = False
self._cooldown = 0
fast = ExponentialMovingAverage()
fast.Length = self.fast_period
slow = ExponentialMovingAverage()
slow.Length = self.slow_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, self.process_candle).Start()
def process_candle(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast)
slow_val = float(slow)
if not self._has_prev:
self._prev_fast = fast_val
self._prev_slow = slow_val
self._has_prev = True
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
volume = self.Volume + abs(self.Position)
self.BuyMarket(volume)
self._cooldown = 2
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
volume = self.Volume + abs(self.Position)
self.SellMarket(volume)
self._cooldown = 2
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return g_terminal_strategy()