GitHub で見る
Farhad Hill バージョン 2 戦略 (C#)
概要
この戦略は、MetaTrader エキスパート アドバイザー「Farhad Hill バージョン 2」の StockSharp 移植です。
複数のインジケーターフィルターを組み合わせて、外国為替シンボルのトレンド反転を取引します。の
変換されたロジックは元のインジケーター スタック (MACD、Stochastic、Parabolic SAR、
モメンタム、およびオプションの移動平均クロス)とその資金管理とトレーリング
行動。
この戦略は単一の時間枠 (デフォルトの 30 分のローソク足) で機能し、1 つのみオープンします。
一度に位置を決めます。プロテクティブなストップロス、テイクプロフィット、および 3 つのトレーリングストップ スタイルは次のとおりです。
MQL バージョンのミラーリングがサポートされました。コード内のすべてのコメントは英語で次のように提供されます。
要求されました。
取引ロジック
- MACD フィルター – 有効にすると、ロングでは信号線の下に MACD の主線が必要になります。
ショートの場合は、信号線の上に MACD メインが必要です。
- Stochastic レベル フィルター – ロングは下限しきい値を下回る %K を要求し、ショートは要求します
上限しきい値を %K 上回っています。オプションのクロスフィルターを有効にすると、強気の
ロングには%K/%Dクロス(下から上へ)が必要で、ショートには弱気クロスが必要です。
- Parabolic SAR フィルター – ロングでは価格を下降ステップで SAR 下げる必要があります
(以前の SAR は現在よりも高かった);ショートパンツの場合は、価格を上回る SAR が必要です
ステップ。変換では、クローズされたローソク足価格が参照として使用されます。
- モメンタム フィルター – MQL 設定に一致するローソク足の始値に基づいて計算されます。
ロングには下限値を下回る勢いが必要で、ショートには上限を超える勢いが必要です。
閾値。
- 移動平均クロス (オプション) – 構成可能な MA タイプ、適用価格および期間。
ロングには遅い MA よりも速い MA が必要です。ショートには逆の関係が必要です。
この戦略は、終了したローソク足のシグナルのみを評価し、ローソク足が終了した場合は新しいエントリーをスキップします。
オープンポジションが存在します。計算されたロットを使用して成行注文でエントリーが発注されます
サイズ。
ポジション管理
- ストップロス/テイクプロフィット – pipsで指定します。ピップは楽器の
PriceStep、利用できない場合は 0.0001 に戻ります。
- トレーリングストップの種類
- 即時 – 価格がストップ距離を超えると、ストップは価格に従います。
- 遅延 – 価格がエントリーからトレーリング距離だけ動くまで待ちます。
固定オフセットでトレーリングします。
- 3 ステージ – 2 つの損益分岐点ステップで元の 3 レベルのロジックを再現します。
そして最終的な後続距離。
- 保護注文は
SellStop/BuyStop (ストップロス用) で発注されます。
SellLimit/BuyLimit (利益確定用) なので、取引所で表示されたままになります。
資金管理
- 固定ロット – 設定された固定量を取引します。
AccountIsMini が有効になっている場合、多くの
最小 0.1 のミニロット サイジングに変換されます。
- リスクの割合 – 元の計算式を再現します。
floor(FreeMargin * percent / 10000) / 10、MaxLots 制限によって制限され、調整されています
必要に応じてミニアカウント用に。ポートフォリオの値が利用できない場合、戦略は
固定ロットに戻ります。
パラメーター
すべてのパラメータは StrategyParam<T> オブジェクトを通じて公開され、最適化または
UIから変わりました。主要グループ:
| グループ |
パラメータ |
説明 |
| 一般 |
CandleType |
シグナルに使用されるローソク足の時間枠 |
| お金の管理 |
AccountIsMini, UseMoneyManagement, TradeSizePercent, FixedVolume, MaxLots |
|
| リスク |
StopLossPips, TakeProfitPips, UseTrailingStop, TrailingStopType, TrailingStopPips, FirstMovePips, TrailingStop1, SecondMovePips, TrailingStop2, ThirdMovePips, TrailingStop3 |
|
| 指標 |
UseMacd, UseStochasticLevel, UseStochasticCross, UseParabolicSar, UseMomentum, UseMovingAverageCross, MacdFast, MacdSlow, MacdSignal, StochasticK, StochasticD, StochasticSlowing, StochasticHigh, StochasticLow, MomentumPeriod, MomentumHigh, MomentumLow, SlowMaPeriod, FastMaPeriod, MaMode, MaPrice |
|
注意事項と前提条件
- Parabolic SAR の比較では、ローソク足の終値を使用して買値/売値チェックを概算します。
MT4から。これにより、履歴データに対するロジックの決定性が維持されます。
- 資金管理には、現在の株式を取得するために接続されたポートフォリオが必要です。それ以外の場合
固定ボリュームが使用されます。
- インジケーターの組み合わせは完了したローソク足でのみ処理され、時期尚早なローソク足を回避します。
部分データの信号。
ファイル
CS/FarhadHillVersion2Strategy.cs – 戦略の C# 実装。
README.md – このドキュメント。
README_ru.md – ロシア語の翻訳。
README_zh.md – 中国語翻訳。
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>
/// Farhad Hill V2 strategy - EMA + Momentum trend follower.
/// Buys when fast EMA crosses above slow EMA with positive momentum.
/// Sells on bearish crossover with negative momentum.
/// </summary>
public class FarhadHillVersion2Strategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _momentumPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int MomentumPeriod { get => _momentumPeriod.Value; set => _momentumPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public FarhadHillVersion2Strategy()
{
_fastPeriod = Param(nameof(FastPeriod), 8)
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 21)
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_momentumPeriod = Param(nameof(MomentumPeriod), 10)
.SetDisplay("Momentum", "Momentum period", "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(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var momentum = new Momentum { Length = MomentumPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, momentum, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow, decimal momentum)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev)
{
_prevFast = fast;
_prevSlow = slow;
_hasPrev = true;
return;
}
var crossUp = _prevFast <= _prevSlow && fast > slow;
var crossDown = _prevFast >= _prevSlow && fast < slow;
if (crossUp && momentum > 0 && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (crossDown && momentum < 0 && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_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
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage, Momentum
from StockSharp.Algo.Strategies import Strategy
class farhad_hill_version2_strategy(Strategy):
def __init__(self):
super(farhad_hill_version2_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 8) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 21) \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._momentum_period = self.Param("MomentumPeriod", 10) \
.SetDisplay("Momentum", "Momentum period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def momentum_period(self):
return self._momentum_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(farhad_hill_version2_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(farhad_hill_version2_strategy, self).OnStarted2(time)
self._has_prev = False
fast = ExponentialMovingAverage()
fast.Length = self.fast_period
slow = ExponentialMovingAverage()
slow.Length = self.slow_period
momentum = Momentum()
momentum.Length = self.momentum_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, momentum, self.process_candle).Start()
def process_candle(self, candle, fast, slow, momentum):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast)
slow_val = float(slow)
mom_val = float(momentum)
if not self._has_prev:
self._prev_fast = fast_val
self._prev_slow = slow_val
self._has_prev = True
return
cross_up = self._prev_fast <= self._prev_slow and fast_val > slow_val
cross_down = self._prev_fast >= self._prev_slow and fast_val < slow_val
if cross_up and mom_val > 0 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif cross_down and mom_val < 0 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return farhad_hill_version2_strategy()