Графический рендерер индикаторов
Некоторые индикаторы требуют особого стиля прорисовки как, например, для индикатора BollingerBands это две линии. Или для индикатора Fractals это точки. В этом случае необходимо явно указывать в ChartIndicatorElement графический рендерер индикаторов.
var chartIndicatorElement = new ChartIndicatorElement()
{
IndicatorPainter = new BollingerBandsPainter(),
};
Рассмотрим на примере индикатора Fractals как создать собственный IndicatorPainter.
Все IndicatorPainter должны быть унаследованны от базового класса BaseChartIndicatorPainter<TIndicator> или интерфейса IChartIndicatorPainter:
/// <summary>
/// The chart element for <see cref="Fractals"/>.
/// </summary>
[Indicator(typeof(Fractals))]
public class FractalsPainter : BaseChartIndicatorPainter<Fractals>
{
...
}
Зададим элементы графика ChartLineElement которые будут представлять верхний и нижний фракталы:
/// <summary>
/// The chart element for <see cref="Fractals"/>.
/// </summary>
[Indicator(typeof(Fractals))]
public class FractalsPainter : BaseChartIndicatorPainter<Fractals>
{
/// <summary>
/// <see cref="Fractals.Up"/> dots color.
/// </summary>
[Display(
ResourceType = typeof(LocalizedStrings),
Name = LocalizedStrings.Str2035Key,
Description = LocalizedStrings.Str2036Key)]
public ChartLineElement Up { get; }
/// <summary>
/// <see cref="Fractals.Down"/> dots color.
/// </summary>
[Display(
ResourceType = typeof(LocalizedStrings),
Name = LocalizedStrings.Str2037Key,
Description = LocalizedStrings.Str2038Key)]
public ChartLineElement Down { get; }
...
}
В конструкторе FractalsPainter зададим им значения и основные свойства цвет, толщину и стиль прорисовки. После чего добавляем их как дочерний элемент графика:
...
/// <summary>
/// Create instance.
/// </summary>
public FractalsPainter()
{
Up = new ChartLineElement { Color = Colors.Green };
Down = new ChartLineElement { Color = Colors.Red };
Up.Style = Down.Style = ChartIndicatorDrawStyles.Dot;
Up.StrokeThickness = Down.StrokeThickness = 4;
AddChildElement(Up);
AddChildElement(Down);
}
...
Переопределяем метод BaseChartIndicatorPainter<TIndicator>.OnDraw(TIndicator indicator, System.Collections.Generic.IDictionary<StockSharp.Algo.Indicators.IIndicator,System.Collections.Generic.IList<StockSharp.Xaml.Charting.ChartDrawData.IndicatorData>> data ) в котором с помощью метода BaseChartIndicatorPainter<TIndicator>.DrawValues(System.Collections.Generic.IList<StockSharp.Xaml.Charting.ChartDrawData.IndicatorData> vals, StockSharp.Charting.IChartElement element, System.Func<StockSharp.Xaml.Charting.ChartDrawData.IndicatorData,System.Double> getValue ) прорисовываем индикатор:
...
/// <inheritdoc />
protected override bool OnDraw(Fractals ind, IDictionary<IIndicator, IList<ChartDrawData.IndicatorData>> data)
{
var result = false;
result |= DrawValues(data[ind.Down], Down);
result |= DrawValues(data[ind.Up], Up);
return result;
}
...
Полный код FractalsPainter:
/// <summary>
/// The chart element for <see cref="Fractals"/>.
/// </summary>
[Indicator(typeof(Fractals))]
public class FractalsPainter : BaseChartIndicatorPainter<Fractals>
{
/// <summary>
/// <see cref="Fractals.Up"/> dots color.
/// </summary>
[Display(
ResourceType = typeof(LocalizedStrings),
Name = LocalizedStrings.Str2035Key,
Description = LocalizedStrings.Str2036Key)]
public ChartLineElement Up { get; }
/// <summary>
/// <see cref="Fractals.Down"/> dots color.
/// </summary>
[Display(
ResourceType = typeof(LocalizedStrings),
Name = LocalizedStrings.Str2037Key,
Description = LocalizedStrings.Str2038Key)]
public ChartLineElement Down { get; }
/// <summary>
/// Create instance.
/// </summary>
public FractalsPainter()
{
Up = new ChartLineElement { Color = Colors.Green };
Down = new ChartLineElement { Color = Colors.Red };
Up.Style = Down.Style = ChartIndicatorDrawStyles.Dot;
Up.StrokeThickness = Down.StrokeThickness = 4;
AddChildElement(Up);
AddChildElement(Down);
}
/// <inheritdoc />
protected override bool OnDraw(Fractals ind, IDictionary<IIndicator, IList<ChartDrawData.IndicatorData>> data)
{
var result = false;
result |= DrawValues(data[ind.Down], Down);
result |= DrawValues(data[ind.Up], Up);
return result;
}
#region IPersistable
/// <inheritdoc />
public override void Load(SettingsStorage storage)
{
base.Load(storage);
Up.Load(storage.GetValue<SettingsStorage>(nameof(Up)));
Down.Load(storage.GetValue<SettingsStorage>(nameof(Down)));
}
/// <inheritdoc />
public override void Save(SettingsStorage storage)
{
base.Save(storage);
storage.SetValue(nameof(Up), Up.Save());
storage.SetValue(nameof(Down), Down.Save());
}
#endregion
}