A SmartDOM column is a vertical strip of the ATAS SmartDOM module: one cell per price row, under a header. Besides the built-in columns (Price, Bid/Ask, Volume, Trades and so on) the SmartDOM can show columns from your own assembly. Such a column:
RenderContext, see «Graphics»);A column cannot place, modify or cancel orders and has no access to accounts or positions: it is a visualization of market data.
SmartDOM columns 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 (drawing) and ATAS.DataFeedsCore.dll (instrument data) from the platform folder, with <Private>false</Private>.
A column is:
SmartDomColumn (namespace ATAS.Indicators.SmartDom) with a public parameterless constructor;[SmartDomColumn(id)] attribute — the stable column id (see below) and, optionally, DisplayName: the name in the list of available columns and the default header;OnDrawCell; every other method is optional.| Method | Called |
|---|---|
| constructor | when the column is added or a saved layout is opened (and the tariff allows custom columns); the saved settings are applied right after it |
OnInitialize() | when the column is attached to a SmartDOM; Context is available from here on |
OnSettingsChanged() | after OnInitialize and every time the user changes a setting |
OnInstrumentChanged() | after the SmartDOM switched to another instrument, before the first data of the new one — reset accumulated data here; data of the previous instrument that was not delivered yet is discarded |
OnNewTrades(trades) | new trades (MarketDataArg, DataType == Trade), oldest first |
OnMarketDepthChanged(levels) | changed order book levels (DataType is Bid or Ask; volume 0 removes a level) |
OnBestBidAskChanged(bestPrice) | the best bid or ask changed |
OnTimer() | about ten times per second while the SmartDOM is visible |
OnDrawColumn(context, bounds) | once per frame, before the cells; bounds is the whole column, header included |
OnDrawCell(context, cell) | once per visible row of every frame |
OnDrawHeader(context, bounds, text) | once per frame; the default draws text (the header set by the user) like the built-in columns |
OnCellClick(cell, e) | the user clicked a cell; return true if you handled it (a handled right click opens no context menu) |
OnDispose() | the platform stops using the instance: the column was removed or its layout replaced, the SmartDOM was closed (also on a workspace switch or exit), the column was stopped by an error, the account or the tariff no longer allows it, its settings were replaced as a whole (template), or the DLL was reloaded. Called exactly once for every instance whose constructor completed, even if OnInitialize was not reached or threw; release timers, files and your own subscriptions here. No other method is called afterwards; an exception here is logged and ignored |
SmartDomCell gives the row Price, the cell Bounds and IsMouseOver. Before OnDrawCell the platform fills the cell with the column background (the Background setting every column has), so you draw only the content.
OnDrawCell cheap: it runs for every row of every frame on the drawing thread. Do heavy work in the data callbacks or OnTimer and only look up prepared values when drawing.Context instead of relying on a complete history.Context (ISmartDomColumnContext) is a read-only view of the SmartDOM:
| Member | Meaning |
|---|---|
Instrument, TickSize | the instrument the SmartDOM displays (IInstrumentInfo: name, exchange, tick size, and TimeZone / TimeZoneOffset — the time zone set for the instrument in the platform, as chart indicators get it; null while none is selected). For cross-trading and synthetic instruments this is the displayed instrument whose book and trades you receive, not the one orders go to |
Scale, RowPriceStep | ticks per row and the price step between rows |
VisibleHigh, VisibleLow, RowHeight | the rows of the last frame |
GetBidVolume(price), GetAskVolume(price) | volume of the order book level shown in a row (0 if none) |
GetDepth(isAsk) | snapshot of all bid or ask levels |
BestBid, BestAsk, LastTrade | the top of the book and the last trade (null while unknown) |
CumulativeBids, CumulativeAsks, MaxBidVolume, MaxAskVolume | totals of the shown order book |
HighOfDay, LowOfDay | the current day range |
Font, BoldFont, HeaderFont, TextFormat | the fonts and the text alignment chosen for the SmartDOM |
BackgroundColor, HeaderBackgroundColor, HeaderTextColor | standard colors |
FormatPrice(price), FormatVolume(volume) | the SmartDOM formatting of prices and volumes |
GetY(price), GetPrice(y) | conversions between rows and coordinates: GetY returns the top Y of the row in the last drawn frame, or null if the row is not visible |
Redraw() | asks for a new frame (for example, after OnTimer changed something) |
Public properties with a getter and a setter are the column settings. They are shown in the column settings of the SmartDOM below the common column settings (header, width, colors) and saved in the workspace and SmartDOM templates. Use [Display(Name = …, GroupName = …, Order = …)] for names, groups and order, [Range] for limits and [Browsable(false)] for values you want to keep but not show. Settings must be of concrete serializable types (numbers, strings, bool, enums, colors, filters); a setting that cannot be restored is skipped and keeps its default value. The values themselves are saved as ordinary JSON objects, so a nested settings class may use constructor parameters, read-only properties or public fields.
Settings are read and written by the settings window under the same lock as your other methods, with one exception: a nested settings object (for example a filter such as FilterInt) is edited in place by its editor on the UI thread, while your column may be running. The platform notices the change (the object must implement INotifyPropertyChanged, as the filters do) and calls OnSettingsChanged afterwards, serialized as usual. So read nested settings only in OnSettingsChanged and copy the values you need into your own fields; use those fields in the data and drawing methods.
If one of your methods throws (or the column repeatedly exceeds the time limit, see «Threading»), the platform writes the reason to the log, releases the instance (OnDispose) and shows «Error» in its header; the rest of the SmartDOM keeps working. A new instance with the saved settings starts when the user changes one of the column settings (header, width, colors), or when the layout is loaded again (workspace or SmartDOM template). Do not rely on this as a control flow — check your inputs instead.
The column below shows, for every row, the bid volume minus the ask volume of the order book levels within a few rows around it: a bar in the color of the dominating side and the value.
The colors are System.Windows.Media.Color settings, as in chart indicators (reference PresentationCore.dll); Convert() from ATAS.Indicators turns them into the System.Drawing.Color the drawing API expects. The Convert() for System.Windows.Media.Color exists only in the assemblies of the classic ATAS, so build such a column against them (net10.0-windows); the same DLL runs in ATAS X, where the platform converts these types automatically (see «Developing indicators for ATAS X»).
The argument of [SmartDomColumn] is the column id: the platform saves the column in workspaces and SmartDOM templates under this id, not under the class name. Rules:
<vendor>.<column-name> in lowercase letters, digits and dashes, for example mycompany.bid-ask-imbalance; the vendor part should identify you (company or author name);atas is reserved: a column from your assembly whose id starts with atas. is rejected when the assembly is loaded, and the reason is written to the platform log;Problems found while loading (an invalid, reserved or duplicate id, a missing public parameterless constructor) are written to the platform log, and the column is not listed.
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, heatmap indicators and SmartDOM columns together.
The columns appear in the SmartDOM settings, Columns tab, in the Custom group of the available columns. 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 columns settings again to see a new column; columns already in a SmartDOM switch to the new build and keep their settings.
If the DLL is removed, saved SmartDOM layouts keep the column: it is shown empty with «Not available» in the header and comes back with its settings when the DLL is installed again.
To sell a column, mark its class with [FeatureId("…")] (namespace OFT.Attributes), as for chart and heatmap indicators: the column is offered only to accounts that have the feature, and a column saved in a layout of an account without it stays empty with «Not available» in the header (its constructor is not called).
Custom SmartDOM columns can be restricted by the tariff (see «Developer API and tariffs»). In that case your columns are still listed in the columns settings, but adding one shows the tariff banner; columns already in a layout are shown empty with «Not available» in the header, and the platform does not create or call them. The tariff is checked on every frame, so the columns start working as soon as the restriction is lifted (for example, after the user logs on with another account) — no need to add them again.
RenderContext drawing API.[Display].