GitHub で見る
Martingale 賢い戦略
概要
Martingale Smart は、MetaTrader エキスパート アドバイザー「Martingale Smart」の変換です。この戦略では、一度に 1 つのオープン ポジションのみを保持し、負けるサイクルごとに 2 つの異なるエントリー フィルターを切り替えます。
- プライマリ フィルター – より高い時間枠 MACD ヒストグラムの方向と組み合わせた 2 つの単純な移動平均間のクロスオーバー。これはデフォルトの入力モードです。
- 二次フィルター – 移動平均エンベロープ。前のサイクルの浮動損失が負の場合、戦略はこのフィルターに切り替わります。別の損失が発生すると、一次フィルタに戻ります。
マーチンゲール成分により、損失サイクル後の次の取引の量が増加します。最後のボリュームを乗算するか (クラシック マーチンゲール)、固定増分を追加することができます。
データサブスクリプション
CandleType – 主な計算と取引管理に使用される時間枠。
MacdTimeFrame – MACD フィルター専用の 2 番目の時間枠。 PERIOD_MN1 の期間を使用した元の EA を模倣するために、デフォルトは 1 か月になります。
どちらのサブスクリプションも OnStarted で自動的に開始されます。
取引ロジック
- 新しい取引は、オープンポジションがなく、すべての指標が形成された場合にのみ考慮されます。
- 高速 MA が低速 MA を下回り、MACD ラインがシグナルより上にある場合、一次フィルターはロングになります (弱気の場合も同じロジック)。これらの条件は、1 小節シフトして
iMA と iMACD を使用した元の EA に従います。
- 2 次フィルターは単純な移動平均エンベロープを使用します。下側のバンドを上回る終値はロングエントリーを示し、上側のバンドを下回る終値はショートエントリーを示します。これにより、
iEnvelopes に基づいたロジックが再現されます。
- サイクルがマイナスの利益で終了すると、戦略は代替フィルターに切り替わり、マーチンゲール パラメーターに従って次のボリュームを計算します。収益性の高いサイクルでは、現在のフィルターが維持され、ボリュームが初期値にリセットされます。
- 保護的なストップロスとテイクプロフィットレベルは、ピップベースの距離を使用して各エントリーの直後に付加されます。
リスク管理
- 損益分岐点 – 未実現利益が
BreakEvenTriggerPips に達すると、ストップロスはエントリー価格にオプションのオフセットを加えた値に跳ね上がります。
- クラシック トレーリング ストップ – 最新の終値から
TrailingStopPips 離れた位置に移動ストップを維持します。
- マネーでの利益確定 – 変動利益が
MoneyTakeProfit を超えたときにポジションを閉じます。
- パーセントでのテイクプロフィット – 目標金額と似ていますが、現在のポートフォリオ値のパーセンテージで表されます。
- マネー トレーリング ストップ – 変動利益が
MoneyTrailingTarget に達すると有効になります。その後、この戦略は利益のピークを追跡し、ドローダウンが MoneyTrailingDrawdown を超えたときにポジションを清算します。
すべての金銭計算は、商品の PriceStep と StepPrice に依存します。データ ソースがそれらを提供しない場合、戦略は単純な価格×数量の見積もりに戻ります。
パラメーター
| パラメータ |
説明 |
UseMoneyTakeProfit |
固定金額テイクプロフィットルールを有効にします。 |
MoneyTakeProfit |
アカウント通貨での変動利益目標。 |
UsePercentTakeProfit |
パーセンテージベースのテイクプロフィットを有効にします。 |
PercentTakeProfit |
ポートフォリオ価値の%としての変動利益目標。 |
EnableMoneyTrailing |
お金に追随する利益を可能にします。 |
MoneyTrailingTarget |
トレーリングブロックを有効にする利益レベル。 |
MoneyTrailingDrawdown |
トレーリングがアクティブになった場合の最大許容利益還元。 |
UseBreakEven |
設定された距離の後にストップロスを損益分岐点に移動します。 |
BreakEvenTriggerPips |
ストップが移動するまでに必要な利益距離 (ピップ単位)。 |
BreakEvenOffsetPips |
追加のピップが損益分岐点に追加されました。 |
MartingaleMultiplier |
負けたサイクルの後に適用される乗算係数。 |
InitialVolume |
各サイクルの最初の注文に使用されるボリューム。 |
UseDoubleVolume |
true の場合、ボリュームを乗算します。それ以外の場合は、LotIncrement を適用します。 |
LotIncrement |
倍増が無効な場合に使用される固定ロット増分。 |
TrailingStopPips |
古典的なトレーリングストップの距離 (ピップ単位)。 |
StopLossPips |
初期のストップロス距離 (pips)。 |
TakeProfitPips |
初期のテイクプロフィット距離 (pips)。 |
FastMaPeriod |
高速移動平均の期間。 |
SlowMaPeriod |
ゆっくりとした移動平均の期間。 |
EnvelopePeriod |
エンベロープ移動平均の期間。 |
EnvelopeDeviation |
封筒の幅 (パーセント単位)。 |
MacdFastLength |
MACD 内の高速な EMA の長さ。 |
MacdSlowLength |
MACD 内の EMA の長さが遅い。 |
MacdSignalLength |
MACD 内の信号 EMA の長さ。 |
CandleType |
メインシグナルの時間枠。 |
MacdTimeFrame |
MACD ローソク足のタイムフレーム。 |
使用上の注意
- マーチンゲール ステップは、前のポジションが損失で完全にクローズされた場合にのみ実行されます。
- この戦略では、一度に 1 つのオープン ポジションが想定されます。反対方向にエントリーする前に、常に現在のポジションを清算します。
- 正確な金額ベースのしきい値を得るには、商品の契約仕様 (
PriceStep、StepPrice、および VolumeStep) を設定します。
- 損益分岐点とトレーリングストップは、メインタイムフレームの閉じたローソク足で評価されます。バー内スパイクは無視されます。
- 変換では、
iMACD への直接呼び出しの代わりに、StockSharp の高レベルの API (SubscribeCandles + Bind) と MovingAverageConvergenceDivergenceSignal インジケーターが使用されます。
- 一部のブローカー固有のチェック (フリーズ レベル、手動メール/通知呼び出し、チケットベースのループ) は、StockSharp エンジンが内部で管理するため省略されます。
- 金銭ベースの保護は、StockSharp のアカウント モデルに合わせて、チケットごとの計算ではなく、集計されたポジションに基づいて機能します。
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Smart Martingale strategy: MACD + MA filter with martingale volume on loss.
/// Buys when fast MA crosses above slow MA. Sells on cross below.
/// </summary>
public class MartingaleSmartStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
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 MartingaleSmartStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast MA", "Fast SMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow MA", "Slow SMA period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new SimpleMovingAverage { Length = FastPeriod };
var slow = new SimpleMovingAverage { Length = SlowPeriod };
decimal? prevFast = null;
decimal? prevSlow = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, (candle, fastVal, slowVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (prevFast.HasValue && prevSlow.HasValue)
{
if (prevFast.Value <= prevSlow.Value && fastVal > slowVal && Position <= 0)
BuyMarket();
else if (prevFast.Value >= prevSlow.Value && fastVal < slowVal && Position >= 0)
SellMarket();
}
prevFast = fastVal;
prevSlow = slowVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class martingale_smart_strategy(Strategy):
def __init__(self):
super(martingale_smart_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._fast_period = self.Param("FastPeriod", 10) \
.SetGreaterThanZero() \
.SetDisplay("Fast MA", "Fast SMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30) \
.SetGreaterThanZero() \
.SetDisplay("Slow MA", "Slow SMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(martingale_smart_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(martingale_smart_strategy, self).OnStarted2(time)
self._fast_ind = SimpleMovingAverage()
self._fast_ind.Length = self._fast_period.Value
self._slow_ind = SimpleMovingAverage()
self._slow_ind.Length = self._slow_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._fast_ind, self._slow_ind, self._process_candle).Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if self._prev_fast is not None and self._prev_slow is not None:
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
self.SellMarket()
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return martingale_smart_strategy()