A heatmap indicator draws on top of the ATAS Heatmap module (and in its sub-panels). It is a different kind of indicator from the chart indicators described in the previous articles:
IHeatmapProfileConsumer.GetRequiredProfilePeriods (see «Threading» below);Heatmap indicators work the same way in the classic ATAS and in ATAS X.
Create a class library exactly as for a chart indicator (see «Development of a user indicator»). Besides ATAS.Indicators.dll, reference OFT.Rendering.dll (visual descriptors, trade ticks) and ATAS.DataFeedsCore.dll (MBO records) from the platform folder, with <Private>false</Private>.
A heatmap indicator consists of:
HeatmapIndicator<TSettings> marked with the [HeatmapIndicator(typeId)] attribute and a public parameterless constructor;Describe<TSelf>(): the visuals (price line, value area, level lines, sub-panel scalar or pair, histogram) and their series; the returned handles are kept in static readonly fields;Version property (the platform only checks that the property exists and saves its value with the other settings; compare it in your code to recognise settings saved by an older build); its public properties are shown in the indicator settings and are available through the inherited Settings property;| Interface | Implement when |
|---|---|
IHeatmapTradeTickConsumer | you react to trades (ProcessTicksAsync) — most indicators do |
IHeatmapProfileConsumer | you react to market-profile snapshots (POC, value area, OHLC) |
IHeatmapMboConsumer | you aggregate MBO data — icebergs, annotated trades (ProcessMboAsync) |
IHeatmapWarmupIndicator | you want history before the live data starts |
IHeatmapTimerConsumer | you need periodic calls independent of the data |
IHeatmapHistoricalDataLoadedConsumer | you rebuild when the user scrolls into older history |
IHeatmapDisposableIndicator | you hold resources that must be released |
Rules worth remembering:
using var lease = State.BeginUpdate(); in a data callback. Disposing the lease publishes the changes; a second lease while one is open throws.Append expects non-decreasing timestamps; samples out of order are dropped.HeatmapTickBatch or its spans after the call returns — the buffer is reused.cancellationToken of a call is cancelled after 2 seconds (30 seconds for WarmUpAsync); a call that then ends with OperationCanceledException counts as a timeout, and 3 timeouts within 30 seconds stop the indicator. A call that is still running when the same time has passed once more after the cancellation, or that throws any other exception, stops the indicator at once.OnStateResetCoreAsync is called when the platform cleared the state (for example, the instrument changed): reset your accumulators there and do not write to the state.The platform calls ConfigureAsync, the data callbacks (ProcessTicksAsync, ProcessProfileAsync, ProcessMboAsync, …), the timer, warm-up and reset methods one at a time, on the instance's own task: fields used only by them need no locks. ConfigureAsync comes first, with the saved settings, and again after every change of the settings; the first call precedes the first OnStateResetCoreAsync, so Context and Runtime are still null in it.
The exception is IHeatmapProfileConsumer.GetRequiredProfilePeriods. The platform's profile pump calls it from its own thread at any time, concurrently with the instance's task. It must be thread-safe, cheap and non-blocking:
ConfigureAsync (or another serialized method) and store it in a volatile field, replacing the whole array, never modifying it in place;An empty set means the instance needs no profile data now; the platform then requests no profiles for it.
The indicator below draws a VWAP line from trades and, when MBO data is available, the number of tracked icebergs in a sub-panel:
The first argument of [HeatmapIndicator] is the TypeId: the stable identifier under which the platform saves the indicator in heatmap templates and workspaces. Rules:
<vendor>.<indicator-name>: lowercase Latin letters, digits and dashes, each part starting with a letter, exactly one dot — for example mycompany.vwap-icebergs; the vendor part should identify you (company or author name). An indicator from your assembly with another TypeId (upper case, no dot, underscores, …) is rejected when the assembly is loaded, and the reason is written to the platform log. SmartDOM columns, Watchlist columns and custom modules use the same rule for their ids;heatmap and atas are reserved for the built-in indicators: an indicator from your assembly whose TypeId starts with heatmap. or atas. (in any letter case) is rejected when the assembly is loaded, and the reason is written to the platform log;Version of the settings class and convert older settings in your own code;Put the DLL into the Extensions folder or into the Indicators folder next to it, where chart indicators are installed (AppData%\ATAS\Extensions or AppData%\ATAS\Indicators for the classic ATAS, AppData%\ATAS X\Extensions or AppData%\ATAS X\Indicators for ATAS X; the platform reads both), or distribute it through the marketplace — one DLL may contain chart indicators and heatmap indicators together.
The platform watches both folders. ATAS X loads a new or replaced DLL by itself about a second after the files stop changing; the classic ATAS shows a reload button in the status bar and loads the libraries when the user presses it (an AI agent uses the ATAS Connect tool extensions_reload). A file that could not be loaded is named with the reason and does not stop the other files — see Extending %ATAS, «Reloading a library». After the libraries are reloaded, open the heatmap indicators window again — the new build of the indicator is listed there, and instances already on the heatmap switch to it the next time the indicators are applied (or when the heatmap is reopened). Problems found while loading (an invalid descriptor, a missing parameterless constructor, an invalid, reserved or duplicate TypeId) are written to the platform log, and the indicator is not listed.
Implement IHeatmapMboConsumer to receive MBO analytics: the platform keeps one MBO subscription per instrument and sends every consumer the same immutable snapshot (HeatmapMboDataSnapshot) — annotated trades, tracked icebergs, the data status and the live edge. Each instance applies its own filters; do not modify the snapshot. Check snapshot.Status.Kind before using the data: MBO is available only for instruments and connections that provide it.
MBO data for third-party indicators can also be restricted by the tariff (see «Developer API and tariffs»). In that case ProcessMboAsync is not called and Context.MboDataSource is null. Design the indicator so that its other parts keep working without MBO data, as in the example above.