Candles and footprint
Candles
GetCandle(bar) returns the
IndicatorCandle of a bar. Bars are numbered from 0 to CurrentBar - 1, where
CurrentBar is the number of loaded bars; the bar parameter of
OnCalculate is always valid. An index below 0 or above CurrentBar - 1 throws an exception and interrupts the
calculation.
Besides the open, high, low, close, the volume, the bid and ask volumes and the delta, a candle has:
- LastTime: the time of the last trade of the bar;
- MaxDelta, MinDelta: the largest and the smallest delta the bar had;
- MaxOI, MinOI: the largest and the smallest open interest the bar had.
using ATAS.Indicators;
namespace ATAS.Docs.Samples.ChartIndicators.MarketData;
public class CandleValuesIndicator : Indicator
{
protected override void OnCalculate(int bar, decimal value)
{
var candle = GetCandle(bar);
var open = candle.Open;
var close = candle.Close;
var high = candle.High;
var low = candle.Low;
var volume = candle.Volume;
var ask = candle.Ask;
var bid = candle.Bid;
var delta = candle.Delta;
this[bar] = (high + low) / 2;
}
}
On the current bar OnCalculate is called on every tick, so call GetCandle(bar) once per call and keep the result
in a local variable (see Performance).
Footprint
The data of a bar at one price, a footprint cell, is a PriceVolumeInfo: the price, the volume, the bid and ask volumes, the number of ticks. A candle gives them several ways:
- GetPriceVolumeInfo(price): the cell at a price (
nullwhen nothing traded there); - GetAllPriceLevels(): every cell of the bar. It creates
an object per level; the overload with a
PriceVolumeInfoargument reuses that object instead, see Performance; - MaxVolumePriceInfo, MaxTickPriceInfo: the cell with the largest volume and the one with the most ticks;
- MaxPositiveDeltaPriceInfo, MaxNegativeDeltaPriceInfo: the cells with the largest and the smallest delta.
using ATAS.Indicators;
namespace ATAS.Docs.Samples.ChartIndicators.MarketData;
public class FootprintDataIndicator : Indicator
{
protected override void OnCalculate(int bar, decimal value)
{
var candle = GetCandle(bar);
// The level at one price
var highData = candle.GetPriceVolumeInfo(candle.High);
if (highData != null)
{
var highVolume = highData.Volume;
}
// The level with the maximum volume
var maxVolumeData = candle.MaxVolumePriceInfo;
if (maxVolumeData != null)
{
var maxVolume = maxVolumeData.Volume;
}
// Every level of the candle
var positiveDeltaLevels = 0;
foreach (var level in candle.GetAllPriceLevels())
{
if (level == null)
continue;
var price = level.Price;
var volume = level.Volume;
var delta = level.Ask - level.Bid;
if (delta > 0)
positiveDeltaLevels++;
}
this[bar] = positiveDeltaLevels;
}
}
Iterating the cells of a candle is far heavier than reading the candle itself: do it only when necessary and cache the intermediate results.