Click or drag to resize

Creating strategies

The basis of the creating strategies is the Strategy class, which includes the main trading options such as: portfolio, instrument, the current position, profit-loss, etc.

It is recommended that the strategy code has been implemented without binding to specified instrument or portfolio. This approach allows you to use strategy with different instruments on different trading accounts simultaneously or in different time periods:

Архитектура стратегий.

The Strategy class uses an approach based on events. Such code is compact and quickly reacts to market events due instant recall. If you use the iteration model, the code is called only after the TimeFrameStrategyTimeFrame timeframe end, and there is a chance to miss the necessary signals in the market. Therefore, it is recommended to use in the S# only events to create the logic of the strategies (all standard S# strategies implement this approach).

To use event-driven approach, you must use the StrategyRules property. The list of rules set through this property. Each of the rules stores an event trigger condition and the action itself, which handles this event. Here is the DeltaHedgeStrategy strategy code, which uses the event model:

C#
/// <summary>
/// The options delta hedging strategy.
/// </summary>
public class DeltaHedgeStrategy : HedgeStrategy
{
    /// <summary>
    /// Initializes a new instance of the <see cref="DeltaHedgeStrategy"/>.
    /// </summary>
    public DeltaHedgeStrategy()
    {
        _positionOffset = new StrategyParam<decimal>(this, "PositionOffset");
    }

    private readonly StrategyParam<decimal> _positionOffset;

    /// <summary>
    /// Shift in position for underlying asset, allowing not to hedge part of the options position.
    /// </summary>
    [CategoryLoc(LocalizedStrings.Str1244Key)]
    [DisplayNameLoc(LocalizedStrings.Str1245Key)]
    [DescriptionLoc(LocalizedStrings.Str1246Key)]
    public decimal PositionOffset
    {
        get { return _positionOffset.Value; }
        set { _positionOffset.Value = value; }
    }

    /// <summary>
    /// To get a list of orders rehedging the option position.
    /// </summary>
    /// <returns>Rehedging orders.</returns>
    protected override IEnumerable<Order> GetReHedgeOrders()
    {
        var futurePosition = BlackScholes.Delta(CurrentTime);

        if (futurePosition == null)
            return Enumerable.Empty<Order>();

        var diff = futurePosition.Value.Round() + PositionOffset;

        this.AddInfoLog(LocalizedStrings.Str1247Params,
            futurePosition, BlackScholes.UnderlyingAssetPosition.Position, PositionOffset, diff);

        if (diff == 0)
            return Enumerable.Empty<Order>();

        var dir = diff > 0 ? Sides.Sell : Sides.Buy;

        var price = Security.GetCurrentPrice(this, dir);

        if (price == null)
            return Enumerable.Empty<Order>();

        return new[]
        {
            new Order
            {
                Direction = dir,
                Volume = diff.Abs(),
                Security = BlackScholes.UnderlyingAsset,
                Portfolio = Portfolio,
                Price = price.ApplyOffset(dir, PriceOffset, Security)
            }
        };
    }
}

This strategy at start adds the rule on new trades event (for rehedging):

C#
_tradingStrategy
    .WhenNewMyTrades()
    .Do(ReHedge).Apply(this);

and also the rule for event of the futures contract change (its price):

C#
Security
    .WhenChanged()
    .Do(ReHedge).Apply(this);

In the DeltaHedgeStrategy rules are added by calling the MarketRuleHelperApply add-in method, that implicitly adds new StrategyRules objects to the IMarketRule list. This reduces the code and make it more readable. As long as the rule is not added to the strategy - it is inactive.

By default the rule is recurring, i.e. it is called as many times, as an event occurs. It will continue as long as the strategy is working, to which a rule is added (StrategyProcessState equals ProcessStatesStarted). If you want to create a rule that will be active from other condition (for example, a rule that closes the position when strategy stops should not depend on the ProcessStatesStarted) value), then you need to call the Until method. The criterion for the rule end is passed to this method

Caution note Caution
If the strategy has been forcibly stopped through the StrategyStop method (for example, when the user clicks on the program window), the strategy is not immediately stopped and goes into the ProcessStatesStopping state and will remain active as long as the list with the StrategyRules rules is not empty (that means that some rules are still active). Therefore, you must be careful with the addition of a rule stopping criterion not to make a strategy unstoppable.
Next Steps
See Also

Other Resources