Table of Contents

Spread Quoting Strategy

Overview

MqSpreadStrategy is a strategy that creates a spread in the market by simultaneously placing quotes for buying and selling. It uses two quoting processors to manage orders on both sides of the market.

Main Components

public class MqSpreadStrategy : Strategy
{
    private readonly StrategyParam<MarketPriceTypes> _priceType;
    private readonly StrategyParam<Unit> _priceOffset;
    private readonly StrategyParam<Unit> _bestPriceOffset;

    private QuotingProcessor _buyProcessor;
    private QuotingProcessor _sellProcessor;
}

Strategy Parameters

The strategy allows customizing the following parameters:

  • PriceType - market price type for quoting (default Following)
  • PriceOffset - price offset from the market price
  • BestPriceOffset - minimum deviation for quote update (default 0.1%)

Strategy Initialization

In the OnStarted method, the strategy subscribes to market time changes:

protected override void OnStarted(DateTimeOffset time)
{
    base.OnStarted(time);

    // Subscribe to market time changes for quote updates
    Connector.CurrentTimeChanged += Connector_CurrentTimeChanged;
    Connector_CurrentTimeChanged(new TimeSpan());
}

Managing Quoting Processors

The Connector_CurrentTimeChanged method is called when the market time changes and manages the creation and update of quoting processors:

private void Connector_CurrentTimeChanged(TimeSpan obj)
{
    // Create new processors only with zero position and if current ones are stopped
    if (Position != 0)
        return;

    if (_buyProcessor != null && _buyProcessor.LeftVolume > 0)
        return;

    if (_sellProcessor != null && _sellProcessor.LeftVolume > 0)
        return;

    // Release resources of existing processors
    _buyProcessor?.Dispose();
    _buyProcessor = null;

    _sellProcessor?.Dispose();
    _sellProcessor = null;

    // Create behaviors for market quoting
    var buyBehavior = new MarketQuotingBehavior(
        PriceOffset,
        BestPriceOffset,
        PriceType
    );

    var sellBehavior = new MarketQuotingBehavior(
        PriceOffset,
        BestPriceOffset,
        PriceType
    );

    // Create processor for buying
    _buyProcessor = new QuotingProcessor(
        buyBehavior,
        Security,
        Portfolio,
        Sides.Buy,
        Volume,
        Volume, // Maximum order volume
        TimeSpan.Zero, // No timeout
        this, // Strategy implements ISubscriptionProvider
        this, // Strategy implements IMarketRuleContainer
        this, // Strategy implements ITransactionProvider
        this, // Strategy implements ITimeProvider
        this, // Strategy implements IMarketDataProvider
        IsFormedAndOnlineAndAllowTrading, // Check trading permission
        true, // Use order book prices
        true  // Use last trade price if the order book is empty
    )
    {
        Parent = this
    };

    // Create processor for selling
    _sellProcessor = new QuotingProcessor(
        sellBehavior,
        Security,
        Portfolio,
        Sides.Sell,
        Volume,
        Volume, // Maximum order volume
        TimeSpan.Zero, // No timeout
        this, // Strategy implements ISubscriptionProvider
        this, // Strategy implements IMarketRuleContainer
        this, // Strategy implements ITransactionProvider
        this, // Strategy implements ITimeProvider
        this, // Strategy implements IMarketDataProvider
        IsFormedAndOnlineAndAllowTrading, // Check trading permission
        true, // Use order book prices
        true  // Use last trade price if the order book is empty
    )
    {
        Parent = this
    };

    // Log creation of new quoting processors
    this.AddInfoLog($"Created buy/sell spread at {CurrentTime}");

    // Subscribe to buy processor events for logging
    _buyProcessor.OrderRegistered += order =>
        this.AddInfoLog($"Buy order {order.TransactionId} registered at price {order.Price}");

    _buyProcessor.OrderFailed += fail =>
        this.AddInfoLog($"Buy order failed: {fail.Error.Message}");

    _buyProcessor.OwnTrade += trade =>
        this.AddInfoLog($"Buy trade executed: {trade.Trade.Volume} at {trade.Trade.Price}");

    _buyProcessor.Finished += isOk => {
        this.AddInfoLog($"Buy quoting finished with success: {isOk}");
        _buyProcessor?.Dispose();
        _buyProcessor = null;
    };

    // Subscribe to sell processor events for logging
    _sellProcessor.OrderRegistered += order =>
        this.AddInfoLog($"Sell order {order.TransactionId} registered at price {order.Price}");

    _sellProcessor.OrderFailed += fail =>
        this.AddInfoLog($"Sell order failed: {fail.Error.Message}");

    _sellProcessor.OwnTrade += trade =>
        this.AddInfoLog($"Sell trade executed: {trade.Trade.Volume} at {trade.Trade.Price}");

    _sellProcessor.Finished += isOk => {
        this.AddInfoLog($"Sell quoting finished with success: {isOk}");
        _sellProcessor?.Dispose();
        _sellProcessor = null;
    };

    // Start both processors
    _buyProcessor.Start();
    _sellProcessor.Start();
}

Resource Release

In the OnStopped method, the strategy releases resources:

protected override void OnStopped()
{
    // Unsubscribe to prevent memory leaks
    Connector.CurrentTimeChanged -= Connector_CurrentTimeChanged;

    // Release processor resources
    _buyProcessor?.Dispose();
    _buyProcessor = null;

    _sellProcessor?.Dispose();
    _sellProcessor = null;

    base.OnStopped();
}

Trading Logic

  • The strategy responds to market time changes
  • With zero position and stopped processors, two new processors are created:
    • Buy processor (Buy)
    • Sell processor (Sell)
  • Both processors are configured with the same volume and use the same quoting settings
  • Processors create a spread in the market by simultaneously placing buy and sell orders

Features

  • Uses modern quoting processor QuotingProcessor with MarketQuotingBehavior
  • Creates a spread in the market by simultaneously placing buy and sell orders
  • Works only with zero position, preventing accumulation of unwanted risk
  • Supports configuration of various quoting parameters (price type, offset, minimum deviation)
  • Includes detailed logging of quoting processor events
  • Properly manages resources when stopping the strategy and creating new processors
  • Supports working with different types of market prices (Following, Best, Opposite, etc.)