MetaTrader 4 エキスパート アドバイザー GoldWarrior02b の包括的な StockSharp ポート (フォルダー MQL/7694)。
It blends a Commodity Channel Index (CCI), a custom impulse gauge and a handcrafted ZigZag swing detector
and evaluates signals only a few seconds before every 15 minute boundary.この翻訳の目標は、
to mimic the high-level logic of the original robot while respecting StockSharp's net-position execution model.
主な特徴
Impulse filter – replaces the DayImpuls custom indicator by averaging the candle open/close distance
商品の価格ステップによって正規化されます。
Net exposure – StockSharp keeps a single net position per security, so the multi-level hedging and lot scaling
from the MQL implementation are not reproduced.代わりに、この戦略は単一のエントリーボリュームに焦点を当てています。
取引ロジック
信号の準備
Subscribe to candles defined by CandleType (5 minute timeframe by default).
Calculate CCI and the impulse average using the shared ImpulsePeriod (default 21 bars).
Update the ZigZag swing direction once the deviation exceeds ZigZagDeviation points and the depth/backstep
制約が満たされています。
Store the previous values of the indicators to replicate the "current" (cci0, imp) and "previous" (cci1, nimp)
エキスパートアドバイザーで使用されるバッファー。
エントリールール
セットアップは、現在オープンなポジションがなく、最後の決済から少なくとも 15 秒が経過し、かつ
AllowEntryTime returns true (end of the 15 minute block).
長い:
最新のジグザグ スイングは下向きを指します (新しい安値は以前の安値よりも低い)。
どちらか
現在の CCI は前のバーと比較して増加しており、前の CCI は -50 未満であり、現在の CCI は -30 未満のままです。
the impulse turns positive and the previous impulse was negative;または
current CCI is below -200, the previous CCI was still lower, the impulse remains below ImpulseBuyThreshold
そして前の衝動よりも強いです。
短い:
最新のジグザグ スイングは上向きを指します (新しい高値は以前の高値よりも高くなります)。
どちらか
現在の CCI は前のバーと比べて減少しています。前のバー CCI は 50 を超えています。現在の CCI は 30 を超えています。
インパルスは負に変わり、前のインパルスは正でした。または
current CCI is above 200, the previous CCI was higher, the impulse stays above ImpulseSellThreshold
そして前の衝動よりも弱いです。
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>
/// Gold Warrior Impulse strategy - CCI crossover with EMA trend filter.
/// Buys when CCI crosses above zero while price is above EMA.
/// Sells when CCI crosses below zero while price is below EMA.
/// </summary>
public class GoldWarrior02bImpulseStrategy : Strategy
{
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevCci;
private bool _hasPrev;
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public GoldWarrior02bImpulseStrategy()
{
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetDisplay("CCI Period", "CCI lookback", "Indicators");
_emaPeriod = Param(nameof(EmaPeriod), 21)
.SetDisplay("EMA Period", "EMA trend filter", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnReseted() { base.OnReseted(); _prevCci = 0m; _hasPrev = false; }
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var cci = new CommodityChannelIndex { Length = CciPeriod };
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(cci, ema, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal cci, decimal ema)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
if (!_hasPrev)
{
_prevCci = cci;
_hasPrev = true;
return;
}
// CCI crosses above zero + price above EMA = buy
if (_prevCci <= 0 && cci > 0 && close > ema && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// CCI crosses below zero + price below EMA = sell
else if (_prevCci >= 0 && cci < 0 && close < ema && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevCci = cci;
}
}
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 CommodityChannelIndex, ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class gold_warrior02b_impulse_strategy(Strategy):
def __init__(self):
super(gold_warrior02b_impulse_strategy, self).__init__()
self._cci_period = self.Param("CciPeriod", 14).SetDisplay("CCI Period", "CCI lookback", "Indicators")
self._ema_period = self.Param("EmaPeriod", 21).SetDisplay("EMA Period", "EMA trend filter", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_cci = 0.0
self._has_prev = False
@property
def cci_period(self): return self._cci_period.Value
@property
def ema_period(self): return self._ema_period.Value
@property
def candle_type(self): return self._candle_type.Value
def OnReseted(self):
super(gold_warrior02b_impulse_strategy, self).OnReseted()
self._prev_cci = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(gold_warrior02b_impulse_strategy, self).OnStarted2(time)
self._has_prev = False
cci = CommodityChannelIndex()
cci.Length = self.cci_period
ema = ExponentialMovingAverage()
ema.Length = self.ema_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(cci, ema, self.process_candle).Start()
def process_candle(self, candle, cci, ema):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
cci_val = float(cci)
ema_val = float(ema)
if not self._has_prev:
self._prev_cci = cci_val
self._has_prev = True
return
if self._prev_cci <= 0 and cci_val > 0 and close > ema_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._prev_cci >= 0 and cci_val < 0 and close < ema_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_cci = cci_val
def CreateClone(self):
return gold_warrior02b_impulse_strategy()