ルールの使用

ルールの作成

  • 注文登録条件のルールの作成:

    private void btnBuy_Click(object sender, RoutedEventArgs e)
    {
       var order = new Order
       { 
           Portfolio = Portfolio.SelectedPortfolio,
           Price = _instr1.BestAsk.Price,
           Security = _instr1,
           Volume = 1,
           Direction = Sides.Buy,
       };
       order
           .WhenRegistered(Connector)
           .Do(() => Connector.AddInfoLog("注文が正常に登録されました"))
           .Once()
           .Apply(this);
    
       // 注文登録
       Connector.RegisterOrder(order);
    }
    

    これで、イベントが発生したとき(注文が取引所に登録されたとき)、IMarketRule.Do(System.Action action ) メソッドで指定したアクションが呼び出されます。

    ルールの構築の最後に、MarketRuleHelper.Apply(StockSharp.Algo.IMarketRule rule ) メソッドを呼び出します。このメソッドがルールに対して呼び出されるまで、ルールは非アクティブです(IMarketRule.Do(System.Action action ) のハンドラーは呼び出されません)。

  • ストラテジー内でのルールの作成:

    class FirstStrategy : Strategy
    {
        protected override void OnStarted2(DateTime time)
        {
            // ローソク足へのサブスクリプション
            var candleSubscription = new Subscription(TimeSpan.FromMinutes(5).TimeFrame(), Security);
            this
                .WhenCandlesStarted(candleSubscription)
                .Do(ProcessCandle)
                .Apply(this);
    
            // ティック取引へのサブスクリプション
            var tickSubscription = new Subscription(DataType.Ticks, Security);
            tickSubscription
                .WhenTickTradeReceived(this)
                .Do(ProcessTick)
                .Apply(this);
    
            // サブスクリプション要求を送信
            Subscribe(candleSubscription);
            Subscribe(tickSubscription);
    
            base.OnStarted2(time);
        }
    
        // イベント処理用メソッド
        private void ProcessCandle(ICandleMessage candle) { /* ... */ }
        private void ProcessTick(ITickTradeMessage tick) { /* ... */ }
    }    
    
  • 不要なルールの削除。

    IMarketRule には IMarketRule.Token があります。これは、そのルールが関連付けられているルールのトークンです。たとえば、WhenCanceled ルールの場合、トークンは注文になります。

    注文キャンセル成功のルールがトリガーされたら、この注文に関連する他のすべてのルールを削除することを推奨します。

    var order = this.CreateOrder(direction, (decimal)Security.GetCurrentPrice(direction), Volume);
    var ruleCanceled = order.WhenCanceled(Connector);
    ruleCanceled
        .Do(() =>
        {
            this.AddInfoLog("注文が正常にキャンセルされました");
            // 注文に関連付けられたすべてのルールを削除
            Rules.RemoveRulesByToken(ruleCanceled, (IMarketRule)ruleCanceled.Token);
        })
        .Once()
        .Apply(this);
    order
        .WhenRegistered(Connector)
        .Do(() => this.AddInfoLog("注文が正常に登録されました"))
        .Once()
        .Apply(this);
    order
        .WhenRegisterFailed(Connector)
        .Do(() => this.AddInfoLog("注文は取引所に承認されませんでした"))
        .Once()
        .Apply(this);
    order
        .WhenMatched(Connector)
        .Do(() => this.AddInfoLog("Order fully executed"))
        .Once()
        .Apply(this);
    // 注文登録
    RegisterOrder(order);
    
  • 条件 MarketRuleHelper.Or(StockSharp.Algo.IMarketRule rule, StockSharp.Algo.IMarketRule[] rules ) / MarketRuleHelper.And(StockSharp.Algo.IMarketRule rule, StockSharp.Algo.IMarketRule[] rules ) によるルールの結合。

    時間が経過した OR ローソク足がクローズした場合:

    // ローソク足へのサブスクリプションを作成
    var subscription = new Subscription(TimeSpan.FromMinutes(5).TimeFrame(), Security);
    var timeInterval = TimeSpan.FromMilliseconds(5000);
    
    Connector
        .WhenIntervalElapsed(timeInterval)
        .Or(this.WhenCandlesStarted(subscription))
        .Do(() => this.AddInfoLog("ローソク足が確定または時間切れ"))
        .Once()
        .Apply(this);
    
    // サブスクリプション要求を送信
    Subscribe(subscription);
    

    または、次の形式です。

    // ローソク足へのサブスクリプションを作成
    var subscription = new Subscription(TimeSpan.FromMinutes(5).TimeFrame(), Security);
    var timeInterval = TimeSpan.FromMilliseconds(5000);
    
    MarketRuleHelper
        .Or(new IMarketRule[] {
            Connector.WhenIntervalElapsed(timeInterval), 
            this.WhenCandlesStarted(subscription)
        })
        .Do(() => this.AddInfoLog("ローソク足が確定または時間切れ"))
        .Once()
        .Apply(this);
    
    // サブスクリプション要求を送信
    Subscribe(subscription);
    

    直近約定価格が 135000 より高く AND 140000 より低い場合:

    // ティック取引へのサブスクリプションを作成
    var subscription = new Subscription(DataType.Ticks, Security);
    var priceMore = new Unit(135000m, UnitTypes.Limit);
    var priceLess = new Unit(140000m, UnitTypes.Limit);
    
    MarketRuleHelper
        .And(new IMarketRule[] {
            subscription.WhenLastTradePriceMore(this, 135000m), 
            subscription.WhenLastTradePriceLess(this, 140000m)
        })
        .Do(() => this.AddInfoLog($"直近約定価格は {priceMore} から {priceLess} の範囲内です"))
        .Apply(this);
    
    // サブスクリプション要求を送信
    Subscribe(subscription);
    

    [!TIP] IMarketRule.Do(System.Action action ) のハンドラーは、MarketRuleHelper.And(StockSharp.Algo.IMarketRule rule, StockSharp.Algo.IMarketRule[] rules ) で追加された最後のルールがトリガーされた後に呼び出されます。

  • ルール動作の周期性 - IMarketRule.Until(System.Func<System.Boolean> canFinish ):

    bool flag = false;
    
    // ティック取引へのサブスクリプションを作成
    var subscription = new Subscription(DataType.Ticks, Security);
    
    subscription
        .WhenTickTradeReceived(this)
        .Do((tick) =>
        {
            if(condition) flag = true;
        })
        .Until(() => flag)			
        .Apply(this);
    
    // サブスクリプション要求を送信
    Subscribe(subscription);
    

ルール使用例

ローソク足のルール

// 5分足へのサブスクリプションを作成
var subscription = new Subscription(TimeSpan.FromMinutes(5).TimeFrame(), Security);

// ローソク足をカウントする変数
var i = 0;
var diff = "10%".ToUnit();

// 新しいローソク足が開始したときにアクティブになるルール
this.WhenCandlesStarted(subscription)
	.Do((candle) =>
	{
		i++;

		// 入れ子のルール: 合計出来高がしきい値を超えたか確認
		this
			.WhenTotalVolumeMore(candle, diff)
			.Do((candle1) =>
			{
	LogInfo($"ルール WhenCandlesStarted と WhenTotalVolumeMore candle={candle1}");
	LogInfo($"ルール WhenCandlesStarted と WhenTotalVolumeMore i={i}");
			})
			.Once().Apply(this);

	}).Apply(this);
	
// サブスクリプション要求を送信
Subscribe(subscription);

オーダーブック(Market Depth)のルール

// オーダーブックデータへのサブスクリプション
var mdSub = new Subscription(DataType.MarketDepth, Security);

// 方法 1: チェーン内でルールを作成
mdSub.WhenOrderBookReceived(this).Do((depth) =>
{
	LogInfo($"Rule WhenOrderBookReceived #1 BestBid={depth.GetBestBid()}, BestAsk={depth.GetBestAsk()}");
}).Once().Apply(this);

// 方法 2: 先にルール変数を作成
var whenMarketDepthChanged = mdSub.WhenOrderBookReceived(this);

whenMarketDepthChanged.Do((depth) =>
{
	LogInfo($"Rule WhenOrderBookReceived #2 BestBid={depth.GetBestBid()}, BestAsk={depth.GetBestAsk()}");
}).Once().Apply(this);

// ルール内のルール
mdSub.WhenOrderBookReceived(this).Do((depth) =>
{
	LogInfo($"Rule WhenOrderBookReceived #3 BestBid={depth.GetBestBid()}, BestAsk={depth.GetBestAsk()}");

	// Once() を指定しないルール
	mdSub.WhenOrderBookReceived(this).Do((depth1) =>
	{
		LogInfo($"Rule WhenOrderBookReceived #4 BestBid={depth1.GetBestBid()}, BestAsk={depth1.GetBestAsk()}");
	}).Apply(this);
}).Once().Apply(this);

// サブスクリプション要求を送信
Subscribe(mdSub);

完了条件付きのルール

// オーダーブックデータへのサブスクリプション
var mdSub = new Subscription(DataType.MarketDepth, Security);

// カウンター
var i = 0;

// i が 10 に達するまでオーダーブックを処理するルールを作成
mdSub.WhenOrderBookReceived(this).Do(depth =>
{
	i++;
	LogInfo($"Rule WhenOrderBookReceived BestBid={depth.GetBestBid()}, BestAsk={depth.GetBestAsk()}");
	LogInfo($"Rule WhenOrderBookReceived i={i}");
})
.Until(() => i >= 10)
.Apply(this);

// サブスクリプション要求を送信
Subscribe(mdSub);

注文のルール

// ティック取引へのサブスクリプション
var sub = new Subscription(DataType.Ticks, Security);

// 最初のティックを受信したら、注文を作成する
sub.WhenTickTradeReceived(this).Do(() =>
{
	var order = CreateOrder(Sides.Buy, default, 1);

	var ruleReg = order.WhenRegistered(this);
	var ruleRegFailed = order.WhenRegisterFailed(this);

	ruleReg
		.Do(() => LogInfo("注文 #1 が登録されました"))
		.Once()
		.Apply(this)
		.Exclusive(ruleRegFailed);  // ルールは相互排他的

	ruleRegFailed
		.Do(() => LogInfo("注文 #1 は登録されていません"))
		.Once()
		.Apply(this)
		.Exclusive(ruleReg);  // ルールは相互排他的

	RegisterOrder(order);
}).Once().Apply(this);

// サブスクリプション要求を送信
Subscribe(sub);

価格変化のルール

// ティック取引へのサブスクリプション
var sub = new Subscription(DataType.Ticks, Security);

// ルールは最初のティックでアクティブになり、別のルールを作成する
sub.WhenTickTradeReceived(this).Do(t =>
{
	// 価格がいずれかの方向に 2 ポイント動いたときにアクティブになるルールを作成
	sub
		.WhenLastTradePriceMore(this, t.Price + 2)
		.Or(sub.WhenLastTradePriceLess(this, t.Price - 2))
		.Do(t =>
		{
			LogInfo($"ルール WhenLastTradePriceMore または WhenLastTradePriceLess が発動: tick={t}");
		})
		.Apply(this);
})
.Once() // このルールは一度だけ呼び出す
.Apply(this);

// サブスクリプション要求を送信
Subscribe(sub);