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

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


[img=104043]RangeUS.png[/img]

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

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

Как добавить на график. [code=cs] .... _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); [/code]

Сам код свечи и билдера Создайте новый класс в проекте, назовите его RangeUSCandle.cs например [code=cs] 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

/// <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;
    }
}

} [/code]

RangeUS.png 64 KB (899)




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

loading
clippy