Click or drag to resize

Custom type of candle

The S# allows to extend the capabilities of the CandleManager, giving the possibility to work with the custom types of candle. This is useful when you want to work with candles that are not supported at this time by S#. The following describes actions on tick candles adding (candles, which are created by the number of trades).

The tick candles implementation

  1. First you need to create your own type of candle. The type must be inherited from the Candle class:

    Caution note Caution
    Tick candles are supported by the S# as standard and this step is given as an example only.
    C#
    /// <summary>
    /// Tick candle.
    /// </summary>
    public class TickCandle : Candle
    {
        /// <summary>
        /// Maximum tick count.
        /// </summary>
        public int MaxTradeCount { get; set; }
    
        /// <summary>
        /// Current tick count.
        /// </summary>
        public int CurrentTradeCount { get; set; }
    
        /// <summary>
        /// Candle arg.
        /// </summary>
        public override object Arg
        {
            get { return MaxTradeCount; }
            set { MaxTradeCount = (int)value; }
        }
    
        /// <summary>
        /// Create a copy of <see cref="TickCandle"/>.
        /// </summary>
        /// <returns>Copy.</returns>
        public override Candle Clone()
        {
            return CopyTo(new TickCandle());
        }
    }
  2. Next, you must create the candles builder, for a new type of candles. To do this, create the CandleBuilderTCandleMessage implementation. Data of the ICandleBuilderSourceValue type will come to the ProcessValue method. Depending on the Sources, ICandleBuilderSourceValue may contain data as about the Trade, tick trade, and on the MarketDepth order book.

    The ProcessValue method should return or a new candle (if new data have led to the candle creation) or update the passed one (if the data is not enough to create a new candle). If the ProcessValue method returns a new candle, then the CandleBuilderTCandleMessage calls it again, passing to the method the same value ICandleBuilderSourceValue. The method will be called up until the ProcessValue returns the passsed candle. This is done for those cases when by one incoming value ICandleBuilderSourceValue several candles can be created:

    C#
    /// <summary>
    /// The builder of candles of <see cref="TickCandle"/> type.
    /// </summary>
    public class TickCandleBuilder : CandleBuilder<TickCandle>
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="TickCandleBuilder"/>.
        /// </summary>
        public TickCandleBuilder()
        {
        }
    
        /// <summary>
        /// Initializes a new instance of the <see cref="TickCandleBuilder"/>.
        /// </summary>
        /// <param name="container">The data container.</param>
        public TickCandleBuilder(ICandleBuilderContainer container)
            : base(container)
        {
        }
    
        /// <summary>
        /// To get time ranges for which this source of passed candles series has data.
        /// </summary>
        /// <param name="series">Candles series.</param>
        /// <returns>Time ranges.</returns>
        public override IEnumerable<Range<DateTimeOffset>> GetSupportedRanges(CandleSeries series)
        {
            var ranges = base.GetSupportedRanges(series).ToArray();
    
            if (!ranges.IsEmpty())
            {
                if (!(series.Arg is int))
                    throw new ArgumentException(LocalizedStrings.WrongCandleArg.Put(series.Arg), nameof(series));
    
                if ((int)series.Arg <= 0)
                    throw new ArgumentOutOfRangeException(nameof(series), series.Arg, LocalizedStrings.TickCountMustBePositive);
            }
    
            return ranges;
        }
    
        /// <summary>
        /// To create a new candle.
        /// </summary>
        /// <param name="series">Candles series.</param>
        /// <param name="value">Data with which a new candle should be created.</param>
        /// <returns>Created candle.</returns>
        protected override TickCandle CreateCandle(CandleSeries series, ICandleBuilderSourceValue value)
        {
            return FirstInitCandle(series, new TickCandle
            {
                MaxTradeCount = (int)series.Arg,
                OpenTime = value.Time,
                CloseTime = value.Time,
                HighTime = value.Time,
                LowTime = value.Time,
            }, value);
        }
    
        /// <summary>
        /// Whether the candle is created before data adding.
        /// </summary>
        /// <param name="series">Candles series.</param>
        /// <param name="candle">Candle.</param>
        /// <param name="value">Data by which it is decided to end the current candle creation.</param>
        /// <returns><see langword="true" /> if the candle should be finished. Otherwise, <see langword="false" />.</returns>
        protected override bool IsCandleFinishedBeforeChange(CandleSeries series, TickCandle candle, ICandleBuilderSourceValue value)
        {
            return candle.CurrentTradeCount >= candle.MaxTradeCount;
        }
    
        /// <summary>
        /// To update the candle data.
        /// </summary>
        /// <param name="series">Candles series.</param>
        /// <param name="candle">Candle.</param>
        /// <param name="value">Data.</param>
        protected override void UpdateCandle(CandleSeries series, TickCandle candle, ICandleBuilderSourceValue value)
        {
            base.UpdateCandle(series, candle, value);
            candle.CurrentTradeCount++;
        }
    }
  3. Then, when you create the CandleManager, to add this candles builder to the sources, which will take ticks from the IConnector:

    Caution note Caution
    The TickCandleBuilder, as a source of candles, is in the CandleManager as standard. This step is given as an example only.
    C#
    private OpenECryTrader _trader;
    private CandleManager _candleManager;
    
    ...
    
    _candleManager = new CandleManager(_trader);
    _candleManager.Sources.Add(new TickCandleBuilder { Sources = { new TradeCandleBuilderSource(_trader) } });
  4. To create the CandleSeries and to request the data on it:

    C#
    private RithmicTrader _trader;
    private Security _security;
    
    private CandleSeries _series;
    private CandleManager _candleManager;
    
    
    _series = new CandleSeries(typeof(TickCandle), _security, 1000);
    
    ...
    
    _candleManager.Start(_series);