Data series
A data series holds one value per bar and is drawn by the platform according to its type and settings. The kinds of series and what each one is for:
| Series | Element | Used for |
|---|---|---|
| ValueDataSeries | decimal |
Lines, histograms, points, arrows |
| RangeDataSeries | RangeValue | A filled area between two values |
| PaintbarsDataSeries | Color? |
The color of each bar |
| CandleDataSeries | Candle | Candles drawn by the indicator |
| CandlePartSeries | decimal |
A part of the chart candles (open, high, ...) as a series |
| IndicatorSeries | decimal |
A series of another indicator as a source |
| PriceSelectionDataSeries | List of PriceSelectionValue | Marked price levels in bars and footprint cells |
| ObjectDataSeries | object |
Any object linked to a bar |
Create the series in the constructor and add them to DataSeries; the first series, DataSeries[0], is a
ValueDataSeries created by the base class and can be replaced (DataSeries[0] = _mySeries). The element with the
index of the bar is written in OnCalculate.
ValueDataSeries: numbers
A decimal per bar; every indicator has one from the start. Properties:
- VisualType: a line, a histogram, arrows and so on;
- Width, Color, LineDashStyle;
- ScaleIt: whether the series takes part in the automatic scaling;
- ShowCurrentValue: the last value on the price scale;
- ShowZeroValue: whether zero values are drawn;
- Digits: decimal places of the values on the price scale.
Methods: SetPointOfEndLine(bar) interrupts the line at a bar, RemovePointOfEndLine(bar) removes such a point, IsThisPointOfStartBar(bar) tells whether a line starts at the bar.
RangeDataSeries: ranges
Each element is a RangeValue with Upper and Lower; the area between them is
filled with RangeColor.
ScaleIt and Visible
work as for the other series. Bollinger Bands with a filled band:
using System.Windows.Media;
using ATAS.Indicators;
using ATAS.Indicators.Technical;
namespace ATAS.Docs.Samples.ChartIndicators;
public class BollingerBandsIndicator : Indicator
{
private readonly RangeDataSeries _band = new("BackGround");
private readonly StdDev _dev = new();
private readonly SMA _sma = new();
private decimal _width;
public int Period
{
get => _sma.Period;
set
{
if (value <= 0)
return;
_sma.Period = _dev.Period = value;
RecalculateValues();
}
}
public decimal Width
{
get => _width;
set
{
if (value <= 0)
return;
_width = value;
RecalculateValues();
}
}
public BollingerBandsIndicator()
{
((ValueDataSeries)DataSeries[0]).Color = Colors.Green;
DataSeries.Add(new ValueDataSeries("Up")
{
VisualType = VisualMode.Line
});
DataSeries.Add(new ValueDataSeries("Down")
{
VisualType = VisualMode.Line
});
DataSeries.Add(_band);
Period = 10;
Width = 1;
}
protected override void OnCalculate(int bar, decimal value)
{
var sma = _sma.Calculate(bar, value);
var dev = _dev.Calculate(bar, value);
this[bar] = sma;
DataSeries[1][bar] = sma + dev * Width;
DataSeries[2][bar] = sma - dev * Width;
_band[bar].Upper = sma + dev * Width;
_band[bar].Lower = sma - dev * Width;
}
}
PaintbarsDataSeries: bar colors
Each element is a nullable color: System.Windows.Media.Color? in the classic ATAS, System.Drawing.Color? in ATAS
X. A null element leaves the bar with its standard color. Visible
toggles the series; HideChart hides the standard bars, for
example when the indicator draws its own candles instead of them, as the Heiken Ashi below does:
using System;
using ATAS.Indicators;
namespace ATAS.Docs.Samples.ChartIndicators;
public class HeikenAshiIndicator : Indicator
{
private readonly CandleDataSeries _candles = new("Heiken Ashi");
private readonly PaintbarsDataSeries _bars = new("Bars") { IsHidden = true, HideChart = true };
public HeikenAshiIndicator() : base(true)
{
DenyToChangePanel = true;
DataSeries[0] = _bars;
DataSeries.Add(_candles);
}
protected override void OnCalculate(int bar, decimal value)
{
var candle = GetCandle(bar);
if (bar == 0)
{
_candles[bar] = new Candle
{
Close = candle.Close,
High = candle.High,
Low = candle.Low,
Open = candle.Open
};
}
else
{
var prevCandle = _candles[bar - 1];
var close = (candle.Open + candle.Close + candle.High + candle.Low) * 0.25m;
var open = (prevCandle.Open + prevCandle.Close) * 0.5m;
var high = Math.Max(Math.Max(close, open), candle.High);
var low = Math.Min(Math.Min(close, open), candle.Low);
_candles[bar] = new Candle
{
Close = close,
High = high,
Low = low,
Open = open,
};
}
}
}
A filter that colors the bars whose volume (or ticks, delta, bid or ask volume) is within a range:
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Windows.Media;
using ATAS.Indicators;
namespace ATAS.Docs.Samples.ChartIndicators;
[DisplayName("Bar's volume filter")]
public class BarVolumeFilterIndicator : Indicator
{
public enum VolumeType
{
Volume,
Ticks,
Delta,
Bid,
Ask
}
private readonly PaintbarsDataSeries _paintBars = new("Paint bars");
private int _minFilter;
private int _maxFilter = 100;
private Color _color = Colors.Orange;
private VolumeType _volumeType;
[Display(Name = "Type", Order = 5)]
public VolumeType Type
{
get => _volumeType;
set
{
_volumeType = value;
RecalculateValues();
}
}
[Display(Name = "Minimum", Order = 10)]
public int MinFilter
{
get => _minFilter;
set
{
_minFilter = value;
RecalculateValues();
}
}
[Display(Name = "Maximum", Order = 20)]
public int MaxFilter
{
get => _maxFilter;
set
{
_maxFilter = value;
RecalculateValues();
}
}
[Display(Name = "Color", Order = 30)]
public Color FilterColor
{
get => _color;
set
{
_color = value;
RecalculateValues();
}
}
public BarVolumeFilterIndicator() : base(true)
{
DataSeries[0] = _paintBars;
_paintBars.IsHidden = true;
DenyToChangePanel = true;
}
protected override void OnCalculate(int bar, decimal value)
{
var candle = GetCandle(bar);
var volume = Type switch
{
VolumeType.Volume => candle.Volume,
VolumeType.Ticks => candle.Ticks,
VolumeType.Delta => candle.Delta,
VolumeType.Bid => candle.Bid,
VolumeType.Ask => candle.Ask,
_ => throw new ArgumentOutOfRangeException()
};
if (volume > _minFilter && volume <= _maxFilter)
_paintBars[bar] = _color;
else
_paintBars[bar] = null;
}
}
CandleDataSeries: candles
Each element is a Candle drawn by the platform. An inverted chart in a separate panel:
using ATAS.Indicators;
namespace ATAS.Docs.Samples.ChartIndicators;
public class ReversalChartIndicator : Indicator
{
private readonly CandleDataSeries _reversalCandles = new("Candles");
public ReversalChartIndicator()
{
((ValueDataSeries)DataSeries[0]).VisualType = VisualMode.Hide;
DataSeries.Add(_reversalCandles);
Panel = IndicatorDataProvider.NewPanel;
}
protected override void OnCalculate(int bar, decimal value)
{
var candle = GetCandle(bar);
_reversalCandles[bar].High = -candle.High;
_reversalCandles[bar].Low = -candle.Low;
_reversalCandles[bar].Open = -candle.Open;
_reversalCandles[bar].Close = -candle.Close;
}
}
CandlePartSeries
A decimal series derived from one part of the chart candles (IndicatorCandle
created by an ICandleCreator). The part is a
DataSeriesType: Open, High, Low, Close, Volume, HL2, HLC3,
OHLC4, HLCC4 or Bars (for Bars the values are 0); any other value throws ArgumentOutOfRangeException in the
constructor.
IndicatorSeries
A wrapper that exposes a series of another indicator through IDataSeries, so that one indicator serves as the data source of another (see Composite indicators).
PriceSelectionDataSeries: marked price levels
Each element is the list of PriceSelectionValue of the bar: the price levels to mark in the bar or in its footprint cells, as the built-in Cluster Search does. The example marks the cells whose volume exceeds a filter:
using System.Linq;
using ATAS.Indicators;
namespace ATAS.Docs.Samples.ChartIndicators;
public class ClusterSearchIndicator : Indicator
{
private readonly PriceSelectionDataSeries _priceSelectionSeries = new("Clusters Selection");
private int _filter = 10;
public int Filter
{
get => _filter;
set
{
_filter = value;
RecalculateValues();
}
}
public ClusterSearchIndicator()
{
DataSeries.Add(_priceSelectionSeries);
}
protected override void OnCalculate(int bar, decimal value)
{
var tickSize = InstrumentInfo?.TickSize ?? 0;
if (tickSize <= 0)
return;
var candle = GetCandle(bar);
for (var price = candle.High; price >= candle.Low; price -= tickSize)
{
var volumeInfo = candle.GetPriceVolumeInfo(price);
if (volumeInfo == null)
continue;
if (volumeInfo.Volume > _filter)
{
var values = _priceSelectionSeries[bar];
var priceSelection = values.FirstOrDefault(t => t.MinimumPrice == volumeInfo.Price);
if (priceSelection == null)
{
values.Add(new PriceSelectionValue(volumeInfo.Price)
{
VisualObject = ObjectType.Rectangle,
Size = 10
});
}
}
}
}
}
ObjectDataSeries: any object
Links any object to a bar; also a way to pass complex objects between indicators.