Table of Contents

Trading Operations in Strategies

In StockSharp, the Strategy class provides various methods for working with orders, making it convenient to implement trading strategies.

Order Placement Methods

There are several ways to place orders in StockSharp strategies:

1. Using High-Level Methods

The simplest way is to use built-in methods that create and register an order in a single call:

// Buy at market price
BuyMarket(volume);

// Sell at market price
SellMarket(volume);

// Buy at limit price
BuyLimit(price, volume);

// Sell at limit price
SellLimit(price, volume);

// Close the current position at market price
ClosePosition();

These methods provide maximum simplicity and code readability. They automatically:

  • Create an order object with the specified parameters
  • Fill in the necessary fields (instrument, portfolio, etc.)
  • Register the order in the trading system

2. Using CreateOrder + RegisterOrder

A more flexible approach is to separate the creation and registration of orders:

// Create an order object
var order = CreateOrder(Sides.Buy, price, volume);

// Additional order settings
order.Comment = "My special order";
order.TimeInForce = TimeInForce.MatchOrCancel;

// Register the order
RegisterOrder(order);

The CreateOrder method creates an initialized order object that can be further customized before registration.

3. Direct Creation and Registration of an Order

For maximum control, you can create an order object directly and register it:

// Create an order object directly
var order = new Order
{
    Security = Security,
    Portfolio = Portfolio,
    Side = Sides.Buy,
    Type = OrderTypes.Limit,
    Price = price,
    Volume = volume,
    Comment = "Custom order"
};

// Register the order
RegisterOrder(order);

For more details on working with orders, see the Orders section.

Handling Order Events

After registering an order, it's important to track its status. In a strategy, you can:

1. Use Event Handlers

// Subscribe to the order change event
OrderChanged += OnOrderChanged;

// Subscribe to the order registration failure event
OrderRegisterFailed += OnOrderRegisterFailed;

private void OnOrderChanged(Order order)
{
    if (order.State == OrderStates.Done)
    {
        // Order executed - perform corresponding logic
    }
}

private void OnOrderRegisterFailed(OrderFail fail)
{
    // Handle order registration error
    LogError($"Order registration error: {fail.Error}");
}

2. Use Rules for Orders

A more powerful approach is to use rules for orders:

// Create an order
var order = BuyLimit(price, volume);

// Create a rule that will trigger when the order is executed
order
    .WhenMatched(this)
    .Do(() => {
        // Actions after order execution
        LogInfo($"Order {order.TransactionId} executed");
        
        // For example, place a stop order
        var stopOrder = SellLimit(price * 0.95, volume);
    })
    .Apply(this);

// Rule for handling registration error
order
    .WhenRegisterFailed(this)
    .Do(fail => {
        LogError($"Order registration error: {fail.Error}");
        // Possibly retry with different parameters
    })
    .Apply(this);

Detailed examples of using rules with orders can be found in the Order Rule Examples section.

Position Management

The strategy also provides methods for position management:

// Get current position
decimal currentPosition = Position;

// Close current position
ClosePosition();

// Protect position with stop-loss and take-profit
StartProtection(
    takeProfit: new Unit(50, UnitTypes.Absolute),   // take-profit
    stopLoss: new Unit(20, UnitTypes.Absolute),     // stop-loss
    isStopTrailing: true,                        // trailing stop
    useMarketOrders: true                        // use market orders
);

Strategy State Before Trading

Before executing trading operations, it's important to ensure that the strategy is in the correct state. StockSharp provides several properties and methods to check the readiness of the strategy:

IsFormed Property

The IsFormed property indicates whether all indicators used in the strategy are formed (warmed up). By default, it checks that all indicators added to the Indicators collection are in the state IIndicator.IsFormed = true.

More about working with indicators in a strategy can be found in the Indicators in Strategy section.

IsOnline Property

The IsOnline property shows whether the strategy is in real-time mode. It becomes true only when the strategy is started and all its market data subscriptions have transitioned to the SubscriptionStates.Online state.

More details about market data subscriptions in strategies can be found in the Market Data Subscriptions in Strategies section.

TradingMode Property

The TradingMode property defines the trading mode for the strategy. Possible values:

This property can be configured through strategy parameters:

public SmaStrategy()
{
    _tradingMode = Param(nameof(TradingMode), StrategyTradingModes.Full)
                   .SetDisplay("Trading Mode", "Allowed trading operations", "Basic settings");
}

Helper Methods for State Checking

For convenient checking of the strategy's readiness to trade, StockSharp provides helper methods:

The IsFormedAndOnlineAndAllowTrading method accepts an optional parameter required of type StrategyTradingModes:

public bool IsFormedAndOnlineAndAllowTrading(StrategyTradingModes required = StrategyTradingModes.Full)

This parameter allows you to specify the minimum level of trading permissions required for a specific operation:

  1. StrategyTradingModes.Full (default value) - returns true only if the strategy is in full trading mode (TradingMode = StrategyTradingModes.Full). Used for operations that can increase a position.

  2. StrategyTradingModes.ReducePositionOnly - returns true if the strategy is in full trading mode or in position reduction mode only. Used for position closing or partial closing operations.

  3. StrategyTradingModes.CancelOrdersOnly - returns true with any active trading mode (except Disabled). Used for order cancellation operations.

This allows you to selectively permit or prohibit various trading operations depending on the current trading mode:

// For placing a new order that increases a position, full trading mode is required
if (IsFormedAndOnlineAndAllowTrading(StrategyTradingModes.Full))
{
    // We can place any orders
    RegisterOrder(CreateOrder(Sides.Buy, price, volume));
}
// For closing a position, the position reduction mode is sufficient
else if (IsFormedAndOnlineAndAllowTrading(StrategyTradingModes.ReducePositionOnly) && Position != 0)
{
    // We can only close the position
    ClosePosition();
}
// For cancelling active orders, the order cancellation mode is sufficient
else if (IsFormedAndOnlineAndAllowTrading(StrategyTradingModes.CancelOrdersOnly))
{
    // We can only cancel orders
    CancelActiveOrders();
}

Thus, this method allows you to implement a secure access control mechanism for trading functions, where more critical operations (such as opening new positions) require a higher level of permissions, and less critical ones (cancelling orders) are performed even in a limited trading mode.

It's good practice to use these methods before performing trading operations:

private void ProcessCandle(ICandleMessage candle)
{
    // Check if the strategy is formed and in online mode,
    // and if trading is allowed
    if (!IsFormedAndOnlineAndAllowTrading())
        return;
    
    // Trading logic
    // ...
}

Trading Operations Example

Below is an example demonstrating different ways of placing orders in a strategy and handling their execution:

protected override void OnStarted(DateTimeOffset time)
{
    base.OnStarted(time);
    
    // Subscribe to candles
    var subscription = new Subscription(
        DataType.TimeFrame(TimeSpan.FromMinutes(5)),
        Security);
    
    // Create a rule for processing candles
    Connector
        .WhenCandlesFinished(subscription)
        .Do(ProcessCandle)
        .Apply(this);
    
    Connector.Subscribe(subscription);
}

private void ProcessCandle(ICandleMessage candle)
{
    // Check if the strategy is ready to trade
    if (!this.IsFormedAndOnlineAndAllowTrading())
        return;
    
    // Example trading logic based on closing price
    if (candle.ClosePrice > _previousClose * 1.01)
    {
        // Option 1: Using a high-level method
        var order = BuyLimit(candle.ClosePrice, Volume);
        
        // Create a rule for handling order execution
        order
            .WhenMatched(this)
            .Do(() => {
                // When the order is executed, set stop-loss and take-profit
                StartProtection(
                    takeProfit: new Unit(50, UnitTypes.Absolute),
                    stopLoss: new Unit(20, UnitTypes.Absolute)
                );
            })
            .Apply(this);
    }
    else if (candle.ClosePrice < _previousClose * 0.99)
    {
        // Option 2: Separate creation and registration
        var order = CreateOrder(Sides.Sell, candle.ClosePrice, Volume);
        RegisterOrder(order);
        
        // Alternative way of handling through the event
        OrderChanged += (o) => {
            if (o == order && o.State == OrderStates.Done)
            {
                // Actions after execution
            }
        };
    }
    
    _previousClose = candle.ClosePrice;
}

See Also