GitHub で見る
Exp XPeriodCandle X2戦略
概要
Exp XPeriodCandle X2はStockSharpの高レベルAPIを使用してオリジナルのMetaTraderエキスパートを再現します。戦略は各バーを平滑化し、設定可能なルックバックウィンドウの遅延始値を最新の平滑化された終値と比較することで、2つの時間軸に合成ローソク足を構築します。上位の時間軸のローソク足の色がトレンドバイアスを定義し、作業時間軸はエントリーとエグジットをトリガーするための色の遷移を待ちます。オプションのストップロスとテイクプロフィットの保護はソースコードのマネーマネジメント入力を複製します。
機能の仕組み
- トレンド検出 – 上位時間軸のサブスクリプションは選択された移動平均で始値と終値を平滑化します。各完了ローソク足は、平滑化された終値を
TrendPeriodバー前の遅延した平滑化された始値と比較します。遅延始値を上回る終値は強気の色(0)を生成し、下回る終値は弱気の色(2)を生成します。TrendSignalBarに格納された色が、グローバルトレンドがロング(+1)、ショート(-1)、またはニュートラルであるかを決定します。
- エントリーロジック – 作業時間軸は同じ平滑化を適用します。各完了ローソク足について、戦略は
EntrySignalBarで参照される現在と前の色を格納します。ショートセットアップは、上位時間軸のトレンドが弱気で、現在の色が0で前の色が2の場合に現れ、元のXPeriodCandleシグナルフリップを反映します。ロングセットアップはトレンドが強気で、現在の色が2で前の色が0であることを必要とします。
- ポジション管理 – 設定可能なトグルはトレンドフリップ(
CloseLongOnTrendFlip、CloseShortOnTrendFlip)とエントリーレベルのリバーサル(CloseLongOnEntrySignal、CloseShortOnEntrySignal)でポジションをクローズします。新しいトレードはVolume + |Position|でサイジングされるため、反対のシグナルはMQLエキスパートのように退出と反転の両方を行います。
- リスク管理 – オプションのストップロスとテイクプロフィットの距離は価格ステップで表されます(
StopLossTicks、TakeProfitTicks)。対応するブール値が有効な場合にのみ活性化されます。
- 平滑化メソッド – 元のSmoothAlgorithmsライブラリの代わりにStockSharpの移動平均が使用されます。利用可能なモードはSimple、Exponential、Smoothed (SMMA)、Weighted、Hull、Kaufman Adaptive、Jurikです。
TrendPhaseとEntryPhaseパラメーターはJurik平滑化にのみ影響し、±100の範囲に制限されます。
パラメーター
| パラメーター |
説明 |
TrendCandleType |
トレンドフィルターに使用される上位時間軸のローソク足タイプ。 |
EntryCandleType |
エントリーに使用される作業時間軸のローソク足タイプ。 |
TrendPeriod |
トレンド時間軸の遅延始値を定義する平滑化されたローソク足の数。 |
EntryPeriod |
エントリー時間軸の遅延始値を定義する平滑化されたローソク足の数。 |
TrendLength |
上位時間軸の合成ローソク足の平滑化長。 |
EntryLength |
作業時間軸の合成ローソク足の平滑化長。 |
TrendPhase |
トレンド時間軸のJurikフェーズパラメーター(他の平滑化タイプでは無視)。 |
EntryPhase |
エントリー時間軸のJurikフェーズパラメーター(他の平滑化タイプでは無視)。 |
TrendSignalBar |
トレンドローソク足の色を読み取るために使用されるシフト(1は最も最近閉じたバーに一致)。 |
EntrySignalBar |
エントリーカラーを読み取るために使用されるシフト(1は最後に閉じたバー、2は前のバーを参照)。 |
TrendSmoothing |
上位時間軸の平滑化に適用される移動平均タイプ。 |
EntrySmoothing |
作業時間軸の平滑化に適用される移動平均タイプ。 |
EnableLongEntries |
強気の条件が現れたときにロングポジションを許可します。 |
EnableShortEntries |
弱気の条件が現れたときにショートポジションを許可します。 |
CloseLongOnTrendFlip |
上位時間軸のトレンドが弱気になったときにロングポジションをクローズします。 |
CloseShortOnTrendFlip |
上位時間軸のトレンドが強気になったときにショートポジションをクローズします。 |
CloseLongOnEntrySignal |
エントリー時間軸が弱気の色をプリントしたときにロングポジションをクローズします。 |
CloseShortOnEntrySignal |
エントリー時間軸が強気の色をプリントしたときにショートポジションをクローズします。 |
UseStopLoss |
価格ステップで測定されたストップロス保護を有効にします。 |
StopLossTicks |
価格ステップでのストップロス距離。 |
UseTakeProfit |
価格ステップで測定されたテイクプロフィット保護を有効にします。 |
TakeProfitTicks |
価格ステップでのテイクプロフィット距離。 |
注意事項
- 遅延始値ロジックは設定された期間内の最も古い平滑化された始値を格納し、元のインジケーターのサーキュラーバッファに一致します。
TrendCandleTypeとEntryCandleTypeが同じ場合、ローソク足のサブスクリプションは1つだけ作成されますが、デュアルカラーロジックは引き続き機能します。
Volumeが適切に設定されていることを確認してください;反転トレードは自動的に現在の絶対ポジションを含み、MetaTraderのロット処理動作を複製します。
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Exp XPeriodCandle X2 strategy (simplified). Uses candle body analysis
/// with EMA trend filter for breakout entries.
/// </summary>
public class ExpXPeriodCandleX2Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaLength;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int EmaLength
{
get => _emaLength.Value;
set => _emaLength.Value = value;
}
public ExpXPeriodCandleX2Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_emaLength = Param(nameof(EmaLength), 20)
.SetGreaterThanZero()
.SetDisplay("EMA Length", "Trend EMA period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema = new ExponentialMovingAverage { Length = EmaLength };
decimal prevClose = 0, prevOpen = 0;
var hasPrev = false;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema, (ICandleMessage candle, decimal emaValue) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!hasPrev)
{
prevClose = candle.ClosePrice;
prevOpen = candle.OpenPrice;
hasPrev = true;
return;
}
if (!IsFormedAndOnlineAndAllowTrading())
{
prevClose = candle.ClosePrice;
prevOpen = candle.OpenPrice;
return;
}
var close = candle.ClosePrice;
// Two consecutive bullish candles above EMA
if (prevClose > prevOpen && close > candle.OpenPrice && close > emaValue && Position <= 0)
BuyMarket();
// Two consecutive bearish candles below EMA
else if (prevClose < prevOpen && close < candle.OpenPrice && close < emaValue && Position >= 0)
SellMarket();
prevClose = close;
prevOpen = candle.OpenPrice;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class exp_x_period_candle_x2_strategy(Strategy):
def __init__(self):
super(exp_x_period_candle_x2_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candles", "General")
self._ema_length = self.Param("EmaLength", 20) \
.SetDisplay("EMA Length", "Trend EMA period", "Indicators")
self._prev_close = 0.0
self._prev_open = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@property
def EmaLength(self):
return self._ema_length.Value
def OnReseted(self):
super(exp_x_period_candle_x2_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_open = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(exp_x_period_candle_x2_strategy, self).OnStarted2(time)
self._prev_close = 0.0
self._prev_open = 0.0
self._has_prev = False
ema = ExponentialMovingAverage()
ema.Length = self.EmaLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def _on_process(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
open_p = float(candle.OpenPrice)
if not self._has_prev:
self._prev_close = close
self._prev_open = open_p
self._has_prev = True
return
ev = float(ema_value)
if (self._prev_close > self._prev_open and close > open_p
and close > ev and self.Position <= 0):
self.BuyMarket()
elif (self._prev_close < self._prev_open and close < open_p
and close < ev and self.Position >= 0):
self.SellMarket()
self._prev_close = close
self._prev_open = open_p
def CreateClone(self):
return exp_x_period_candle_x2_strategy()