GitHub で見る
マクロス戦略
この戦略は、StockSharp の高レベル API を使用して、元の MQL/34176/MACross.mq4 エキスパート アドバイザーの動作を複製します。単一商品を移動平均クロスオーバーで取引し、ピップと口座資本で表現されるすべてのリスク管理を維持します。
取引ロジック
- 2 つの単純移動平均 (SMA) は、設定されたローソク足タイプに基づいて構築されます。
FastPeriod は価格の変更にすぐに反応します。
SlowPeriod は長期トレンドを平滑化します。
- 終了した各ローソク足の終値で、高速平均と低速平均が比較されます。
- 強気のクロスオーバー(低速を高速でクロスオーバー)すると、ロングポジションがオープンします。アクティブなショートは最初にフラット化されます。
- 弱気のクロスオーバー (低速を下回る高速クロス) は、既存のロングポジションを閉じた後、ショートポジションをオープンします。
- すべてのエントリーは、
LotSize から派生し、商品の制限 (VolumeStep、MinVolume、MaxVolume) に合わせた固定市場ボリュームを使用します。
- ポジションがオープンされた後、戦略は pips で測定される 2 つのリスク目標を追跡します。 pip サイズは、
Security.Decimals (またはフォールバックとして PriceStep) から自動的に推測されます。
TakeProfitPips は利益目標までの距離を定義します。これにヒットすると、現在の方向への市場の出口が発行されます。
StopLossPips は保護停止距離を定義します。これを突破するとポジションは直ちにクローズされます。
- 取引は
MinEquity の警備員によって一時停止されることがあります。現在のポートフォリオ値がしきい値を下回る場合、戦略はアクティブなポジションを管理し続けますが、新しいエントリーは許可されません。
すべての計算は完了したローソク足に対してのみ機能し、移動平均を評価する前に新しいバーを待機した元のエキスパートアドバイザーと完全に一致します。
可視化
チャート ペインが使用可能な場合、戦略は次のようにプロットします。
- 購読中のシリーズからキャンドルを入力します。
- 高速 SMA と低速 SMA。
- クロスオーバー ルールによってトリガーされるエントリーとエグジットを強調表示する独自の取引。
パラメーター
| 名前 |
種類 |
デフォルト |
説明 |
FastPeriod |
int |
8 |
クロスオーバー信号を生成する高速 SMA の長さ。 |
SlowPeriod |
int |
20 |
基準トレンドラインとして使用される遅い SMA の長さ。 |
TakeProfitPips |
decimal |
20 |
利益目標までの距離をピップ単位で表します。ピップサイズは商品の小数点から推測されます。 |
StopLossPips |
decimal |
20 |
ピップ単位の保護停止距離。利益目標と同じピップサイズ計算を使用します。 |
LotSize |
decimal |
1 |
基本注文量。この戦略では、成行注文を送信する前に、許容される最も近いサイズに丸められます。 |
MinEquity |
decimal |
100 |
口座の最低資本。ポートフォリオの価値がこのレベルを下回っている間、新しい取引はブロックされます。 |
CandleType |
DataType |
TimeSpan.FromMinutes(1).TimeFrame() |
SMA の計算と信号評価に使用されるローソク足シリーズ。 |
MQL バージョンとの違い
- 元の MQL のエキスパートは、ストップロスとテイクプロフィットの価格をゼロとして
OrderSend に渡しました。 StockSharp ポートは、完成した各ローソク足の終値を監視する手動終了と同じ動作をエミュレートします。
- 株式検証 (
cekMinEquity) は、AccountEquity() ではなく Portfolio.CurrentValue と Portfolio.BeginValue を読み取るようになりましたが、しきい値ロジックは保持されます。
- Pip サイズ検出は、
GetPipPoint ヘルパーを反映します。2 桁または 3 桁の引用符は 0.01 を使用し、4 桁または 5 桁の引用符は 0.0001 を使用します。それ以外の場合は、PriceStep が使用されます。
結果として得られる戦略は、公開されているすべてのパラメータを通じて最適化でき、StockSharp のグラフ作成およびリスク管理インフラストラクチャとシームレスに組み合わせることができます。
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// MA Cross strategy: SMA crossover.
/// Buys when fast SMA crosses above slow SMA, sells on cross below.
/// </summary>
public class MacrossStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public MacrossStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = 0;
_prevSlow = 0;
_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 fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (_hasPrev)
{
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
BuyMarket();
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
SellMarket();
}
else
{
if (fastValue > slowValue && Position <= 0)
BuyMarket();
else if (fastValue < slowValue && Position >= 0)
SellMarket();
}
_prevFast = fastValue;
_prevSlow = slowValue;
_hasPrev = true;
}
}
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 ma_cross_strategy(Strategy):
"""
MA Cross strategy: EMA crossover.
Buys when fast crosses above slow, sells on cross below.
"""
def __init__(self):
super(ma_cross_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 10).SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30).SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60))).SetDisplay("Candle Type", "Timeframe", "General")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(ma_cross_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(ma_cross_strategy, self).OnStarted2(time)
fast = ExponentialMovingAverage()
fast.Length = self._fast_period.Value
slow = ExponentialMovingAverage()
slow.Length = self._slow_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, self._process_candle).Start()
def _process_candle(self, candle, fast_val, slow_val):
if candle.State != CandleStates.Finished:
return
f = float(fast_val)
s = float(slow_val)
if self._has_prev:
if self._prev_fast <= self._prev_slow and f > s and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and f < s and self.Position >= 0:
self.SellMarket()
else:
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_fast = f
self._prev_slow = s
self._has_prev = True
return
if f > s and self.Position <= 0:
self.BuyMarket()
elif f < s and self.Position >= 0:
self.SellMarket()
self._prev_fast = f
self._prev_slow = s
self._has_prev = True
def CreateClone(self):
return ma_cross_strategy()