Тип свечи RangeUS, с дополнительным параметром для разворота

Тип свечи RangeUS, с дополнительным параметром для разворота
Atom
12/27/2016
gem81


RangeUS.png

Пока изучаю систему, буду писать полезные статьи, вроде этой.
Если мешают, то напишите в коммент, Перестану))))
Что требуется: S#.API + понимание платформы.

И так. В основе классический рендж бар, но с дополнительным параметром ReverseSize (разворотный размер).
Размеры указываются в шагах цены. На картинке сбербанк с параметрами 10/30 шагов(PriceStep)

Как добавить на график.
Code

....
                _series = new CandleSeries(typeof(RangeUSCandle), sec, new RangeUSArgs { RangeSize = (decimal)sec.PriceStep * 10, ReverseSize= (decimal)sec.PriceStep * 30 });
....
                _candleManager = new CandleManager(client);
                _candleManager.Sources.Add(new RangeUSCandleBuilder { Sources = { new TradeCandleBuilderSource(client) } });
....
                _candleManager.Start(_series);


Сам код свечи и билдера
Создайте новый класс в проекте, назовите его RangeUSCandle.cs например
Code

using Ecng.Collections;
using Ecng.Common;
using Ecng.ComponentModel;

using System;
using System.Collections.Generic;
using System.Linq;
using StockSharp.Algo.Candles;
using StockSharp.Algo.Candles.Compression;
using StockSharp.Localization;

namespace НазваниеВашегоПроекта
{
    public class RangeUSArgs
    {
        public decimal RangeSize;
        public decimal ReverseSize;
    }
    public enum RangeUSTrend
    {
         None = 0,
         UpTrend = 1,
         DownTrend = 2
    }

    /// <summary>
    /// Описание свечи
    /// </summary>
    public class RangeUSCandle : Candle
    {
        public override object Arg
        {
            get
            {
                return this.PriceRange;
            }
            set
            {
                this.PriceRange = (RangeUSArgs)value;
            }
        }

        /// <summary>
        /// Параметры свечи
        /// </summary>
        public RangeUSArgs PriceRange { get; set; }
        /// <summary>
        /// Текущий тренд. Значения: 1 восходящий, 2 нисходящий, 0 при инициации.
        /// </summary>
        public RangeUSTrend Trend;  
        public override Candle Clone()
        {
            return CopyTo(new RangeUSCandle());
        }
    }

    /// <summary>
    /// Построитель RangeUS свечей
    /// </summary>
    public class RangeUSCandleBuilder : CandleBuilder<RangeUSCandle>
    {
        public RangeUSCandleBuilder()
        {
        }

        public RangeUSCandleBuilder(ICandleBuilderContainer container)
            : base(container)
        {
        }

        public override IEnumerable<Range<DateTimeOffset>> GetSupportedRanges(CandleSeries series)
        {
            var ranges = base.GetSupportedRanges(series).ToArray();

            if (!ranges.IsEmpty())
            {
                if (!(series.Arg is RangeUSArgs))
                    throw new ArgumentException(LocalizedStrings.WrongCandleArg.Put(series.Arg), nameof(series));

                if (((RangeUSArgs)series.Arg).RangeSize <= 0)
                    throw new ArgumentOutOfRangeException(nameof(series), series.Arg, LocalizedStrings.PriceRangeMustBeGreaterThanZero);
            }

            return ranges;
        }

        protected override RangeUSCandle CreateCandle(CandleSeries series, ICandleBuilderSourceValue value)
        {
            // требуется перенести в новую свечу, понимание текущего направления.
            RangeUSTrend trend_value;
            if (CandleManager.GetCandleCount(series) > 0)
            {
                trend_value = CandleManager.GetCurrentCandle<RangeUSCandle>(series).Trend;
            } else {
                trend_value = RangeUSTrend.None;
            }
            return FirstInitCandle(series, new RangeUSCandle
            {
                PriceRange = (RangeUSArgs)series.Arg,
                OpenTime = value.Time,
                CloseTime = value.Time,
                HighTime = value.Time,
                LowTime = value.Time,
                Trend = trend_value,
            }, value);
        }

        protected override bool IsCandleFinishedBeforeChange(CandleSeries series, RangeUSCandle candle, ICandleBuilderSourceValue value)
        {
            var cm = CandleManager;
            var prev_candle = CandleHelper.GetCandle<RangeUSCandle>(cm,series,cm.GetCandleCount(series)-1);
            if(cm.GetCandleCount(series) <= 1)
            {
                // первая свеча. пытаемся понять направление
                candle.Trend = (candle.OpenPrice > value.Price) ? RangeUSTrend.DownTrend : RangeUSTrend.UpTrend;
                return candle.LowPrice + candle.PriceRange.RangeSize <= candle.HighPrice; //
            }
            if (candle.Trend == RangeUSTrend.UpTrend && value.Price > candle.OpenPrice)
            {
                return candle.OpenPrice + candle.PriceRange.RangeSize <= candle.HighPrice; //
            }
            if (candle.Trend == RangeUSTrend.DownTrend && value.Price < candle.OpenPrice)
            {
                return candle.OpenPrice - candle.PriceRange.RangeSize >= candle.LowPrice; //
            }
            var needReverse = candle.GetBody() > candle.PriceRange.ReverseSize; // 
            if (needReverse)
            {
                candle.Trend = (candle.Trend != RangeUSTrend.None & candle.Trend == RangeUSTrend.UpTrend) ? candle.Trend = RangeUSTrend.DownTrend : candle.Trend = RangeUSTrend.UpTrend;
            }
            return needReverse;
        }
    }
}
RangeUS.png 64 KB (609)




Attach files by dragging & dropping, , or pasting from the clipboard.

loading
clippy