GitHub で見る
Binario 戦略
概要
Binario はストップエントリーのブレイクアウトシステムで、ローソク足の高値と安値で計算された 2 つの移動平均エンベロープで価格を囲みます。価格がエンベロープ間で取引されているとき、戦略は次の方向性拡張を捉えるために対称的なストップ注文を配置します。注文は MetaTrader 5 のエキスパートアドバイザーを反映した固定のストップロスとテイクプロフィットオフセットを継承します。
StockSharp ポートはコアアイデアを維持しつつ、ローソク足サブスクリプション、インジケーターバインディング、自動化された注文管理などの高レベル API 機能を活用します。レベル 1 データは現在の bid/ask スプレッドを推定するために消費されます。これは元のエントリーオフセットを再現するために必要です。
取引ロジック
- 設定可能なメソッドと期間を使用して 2 つの移動平均を構築する(高値の上位、安値の下位)。
- 最新の終値が平均の間にある場合:
- 設定された差分バッファと現在のスプレッドを加えた上位平均の上にバイストップを配置する。
- 同じバッファを引いた下位平均の下にセルストップを配置する。
- 各保留注文は移動平均、
PointValue、pip ベースのパラメーターから導出された独自のストップロスとテイクプロフィットレベルを保存します。
- 注文が約定したとき、反対の保留注文がキャンセルされ、オープンポジションに対して新しい保護注文(ストップロスとテイクプロフィット)が登録されます。
- トレーリングストップロジックは価格がエントリー価格から少なくとも
TrailingStopPips + TrailingStepPips 進んだときにストップを絞り、MQL 実装の増分的な動作に対応します。
- ポジションがロングからショートに(またはその逆に)切り替わるときは、競合を避けるために既存の保護注文がキャンセルされます。
パラメーター
CandleType – 計算に使用するタイムフレーム。
MaPeriod – 両方の移動平均の長さ。
MaShift – 各移動平均に適用されるバーシフト(0 はデフォルト EA の動作を再現)。
HighMaMethod / LowMaMethod – 平滑化メソッド(SMA、EMA、SMMA、WMA、LWMA)。
PointValue – 取引シンボルの 1 pip を表す絶対価格値(ほとんどの FX メジャーは 0.0001、JPY ペアは 0.01 など)。
DifferencePips – 平均と保留注文の間のバッファ、pip で表現。
TakeProfitPips – 利益目標距離(pip 単位)。
TrailingStopPips – トレーリングストップ距離(pip 単位)(トレーリングを無効にするにはゼロに設定)。
TrailingStepPips – ストップが再び絞られる前に必要な最小追加利益(pip 単位)。
Volume(Strategy から継承)– 基本注文サイズ;逆転注文は絶対ポジションサイズを自動的に追加してエクスポージャーを完全に転換します。
すべての pip ベースのパラメーターは PointValue を介して絶対価格に変換され、MT5 バージョンで実行される Point * digits_adjust 変換を反映します。
注文管理
- 保留ストップ注文は、それぞれの側で戦略がフラットである間のみ有効です(新しいバイストップに対してロングポジションなし、新しいセルストップに対してショートポジションなし)。
- エントリーがトリガーされた後、戦略は対応するストップロスとテイクプロフィット注文を送信し、使用されていない反対のストップエントリーを削除します。
- ポジション逆転は孤立したストップを防ぐために新しいものを登録する前に古い保護注文をキャンセルします。
トレーリング動作
- ロングポジション:価格が少なくとも
TrailingStopPips + TrailingStepPips pip 獲得すると、移動が前のストップを少なくとも TrailingStepPips 超える限り、ストップは close - TrailingStopPips にシフトされます。
- ショートポジション:価格が同じ閾値で下落したとき、ストップはステップフィルターも適用しながら
close + TrailingStopPips に下げられます。
- トレーリングは MT5 の
PriceCurrent() 値の代替として最新のローソク足終値を使用します。
データ要件
- 選択した
CandleType のローソク足。
- スプレッドを計算するために最良 bid/ask 価格を取得するためのレベル 1 クォート。スプレッドが利用できない場合、戦略は商品の最小価格ステップまたは
PointValue にフォールバックします。
- ポジションサイジングは元の Lots/Risk の組み合わせの代わりに StockSharp の
Volume プロパティを通じて制御されます。
- StockSharp のストップ注文はその場で修正できないため、トレーリングが価格を変更するときに保護注文が再作成されます。
- MyTrades が報告する約定価格は保存された注文価格で近似されます;
PointValue と pip パラメーターをブローカーの仕様に合わせて調整してください。
- 戦略は完成したローソク足で実行されます。これは MT5 スクリプトでバー開放評価で「エキスパート各ティック」を有効にすることと同等です。
使用上の注意
- 商品のティックツーピップ関係に応じて
PointValue を設定する。
- MT5 テンプレートに合わせて移動平均メソッドと期間を設定する。
- 差分、テイクプロフィット、トレーリングコンポーネントに適切な pip 距離を選ぶ。
- スプレッドコンポーネントを正確に適用できるようにレベル 1 データが利用可能であることを確認する。
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>
/// Binario strategy (simplified). Uses two EMAs as channel and trades breakouts.
/// </summary>
public class BinarioStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _maPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
public BinarioStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_maPeriod = Param(nameof(MaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("MA Period", "Moving average length", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var highest = new Highest { Length = MaPeriod };
var lowest = new Lowest { Length = MaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(highest, lowest, (ICandleMessage candle, decimal highValue, decimal lowValue) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
var mid = (highValue + lowValue) / 2m;
var channelPadding = (highValue - lowValue) * 0.1m;
// Buy on breakout above channel midpoint
if (close > mid + channelPadding && Position <= 0)
{
BuyMarket();
}
// Sell on breakout below channel midpoint
else if (close < mid - channelPadding && Position >= 0)
{
SellMarket();
}
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, highest);
DrawIndicator(area, lowest);
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 Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class binario_strategy(Strategy):
def __init__(self):
super(binario_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candles", "General")
self._ma_period = self.Param("MaPeriod", 20) \
.SetDisplay("MA Period", "Moving average length", "Indicators")
@property
def CandleType(self):
return self._candle_type.Value
@property
def MaPeriod(self):
return self._ma_period.Value
def OnStarted2(self, time):
super(binario_strategy, self).OnStarted2(time)
highest = Highest()
highest.Length = self.MaPeriod
lowest = Lowest()
lowest.Length = self.MaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription \
.Bind(highest, lowest, self._on_process) \
.Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, highest)
self.DrawIndicator(area, lowest)
self.DrawOwnTrades(area)
def _on_process(self, candle, high_value, low_value):
if candle.State != CandleStates.Finished:
return
hv = float(high_value)
lv = float(low_value)
close = float(candle.ClosePrice)
mid = (hv + lv) / 2.0
channel_padding = (hv - lv) * 0.1
if close > mid + channel_padding and self.Position <= 0:
self.BuyMarket()
elif close < mid - channel_padding and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return binario_strategy()