Тип свечи RangeUS, с дополнительным параметром для разворота
Пока изучаю систему, буду писать полезные статьи, вроде этой.
Если мешают, то напишите в коммент, Перестану))))
Что требуется: S#.API + понимание платформы.
И так. В основе классический рендж бар, но с дополнительным параметром ReverseSize (разворотный размер).
Размеры указываются в шагах цены. На картинке сбербанк с параметрами 10/30 шагов(PriceStep)
Как добавить на график.
Код
....
_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 например
Код
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;
}
}
}