Custom Bar Types
A custom bar type transforms source market data into candles that charts and research workflows can select as a data series.
| Difficulty | Input | Applies to |
|---|---|---|
| Advanced | Base candles, trade ticks, or both | HyperionX 1.1.10 |
The stable runtime contract is BarTypeBase/IBarBuilder. Some 1.1.10 installers do not seed the custom-project convenience bases used by the Code Lab templates (CustomBarType and TickCountCustomBarType). The example below derives directly from BarTypeBase so it does not depend on that optional bootstrap source.
Choose the source model first
| Model | Use it when | Primary method |
|---|---|---|
| Base-bar transformation | Each source candle maps to or contributes to a custom candle | ProcessBaseBar(ICandle candle) |
| Tick construction | Candle boundaries depend on individual trades, volume, range, or another tick rule | ProcessTick(MarketTick tick) |
| End-of-stream finalization | A partial candle must be completed when the source ends | Flush() |
The Metadata declaration tells HyperionX which source the builder needs and how the series should appear in chart configuration.
Minimal pass-through builder
In Tools → Code Lab, select Bar Type → Pass-through bar type.
using System.Collections.Generic;
using HyperionX.Chart.Interfaces;
using HyperionX.Core.DataCalc.Bars;
using HyperionX.Core.Enums;
namespace HyperionX.Custom.BarTypes;
public class MyMinuteBars : BarTypeBase
{
public override string Name => nameof(MyMinuteBars);
public override string DisplayName => "My Minute Bars";
public override string Description => "Passes each source minute candle through unchanged.";
public override BarBuilderMetadata Metadata { get; } = new()
{
BuiltFrom = DataSeriesType.Minute,
SourceRequirement = BarSourceRequirement.BaseBars,
IsTimeBased = true,
IsIntraday = true,
SupportsRemoveLastBar = false,
DefaultDaysToLoad = 5,
DefaultChartStyle = "Candlestick"
};
public override void Reset(BarBuilderContext context)
{
}
public override IReadOnlyList<BarUpdate> ProcessBaseBar(ICandle candle)
{
if (candle == null)
return System.Array.Empty<BarUpdate>();
return new[] { BarUpdate.Add(candle) };
}
}
This example demonstrates the contract; it intentionally does not change the source bars.
Builder contract
| Member | Responsibility |
|---|---|
Name | Stable registration name. Keep it unique. |
DisplayName | User-facing name shown in the data-series selector. |
Description | Short explanation of the construction rule. |
Metadata | Source, timing, defaults, and chart-style capabilities. |
Reset(context) | Clear all builder state before processing a new run. |
ProcessBaseBar(candle) | Consume one source candle and return zero or more updates. |
ProcessTick(tick) | Consume one trade tick; the base implementation converts it to a candle. |
Flush() | Emit final updates after the source stream ends. |
BarBuilderContext supplies the selected DataSeriesParams and the resolved TickSize. Read those values in Reset(...) and copy only the small immutable settings the builder needs. The same type can be used by multiple charts; never store a context or construction state in static fields.
Metadata
BarBuilderMetadata currently includes:
| Property | Meaning |
|---|---|
BuiltFrom | Default DataSeriesType used as source. |
SourceRequirement | Whether the builder needs base bars or trade ticks. |
IsTimeBased | Whether candles have a fixed time interpretation. |
IsIntraday | Whether the resulting series is intraday. |
SupportsRemoveLastBar | Whether the builder can reverse its most recent published candle. |
DefaultDaysToLoad | Initial historical-data request size. |
DefaultChartStyle | Suggested chart renderer. |
UsesDataSeriesValueAsBarValue | Whether the user's interval value controls the custom rule. |
DefaultDataSeriesValue | Default value used when that option is enabled. |
Metadata is operational. If a tick-built series declares a base-bar requirement, HyperionX may request the wrong source data and the result will be invalid or empty.
BarSourceRequirement.QuoteTicks exists in the enum, but the current public construction pipeline does not establish a complete quote-tick delivery contract. Do not advertise a quote-built custom bar until the packaged runtime documents and tests that source path.
Returning updates
Each callback returns a list of BarUpdate operations:
| Factory | Meaning |
|---|---|
BarUpdate.Add(candle) | Append a new candle. |
BarUpdate.UpdateLast(candle) | Update the currently forming last candle. |
BarUpdate.ReplaceLast(candle) | Replace the last candle with a new finalized representation. |
BarUpdate.RemoveLast() | Remove the last candle; advertise support in metadata. |
A single source event may return no updates, one update, or several updates. Always return updates in the order HyperionX should apply them.
Discovery requirements
The registry loads a type only when it is:
- Concrete and assignable to the bar-builder contract.
- Constructible with a public parameterless constructor.
- Present in the successfully loaded custom assembly.
After a build and custom-assembly refresh, the builder appears as a custom choice using DisplayName. The registry creates a fresh builder instance for each use, so keep state on the instance rather than in static fields.
Registration keys use Name case-insensitively. If two builders publish the same name, the later registration replaces the earlier factory and descriptor. Treat a unique, stable Name as part of the saved-workspace compatibility contract.
Correctness checklist
- Reset every mutable field in
Reset(...). - Reject null or invalid source records without throwing.
- Preserve monotonically ordered candle timestamps.
- Keep OHLC relationships valid.
- Define whether volume and trade count accumulate or pass through.
- Mark completed versus forming candles consistently.
- Implement
Flush()when the final partial candle matters. - Do not claim
SupportsRemoveLastBarunlessRemoveLastbehavior is correct. - Test historical loads, incremental updates, reloads, and empty input.
- Compare chart output with research/backtest output on the same source data.
Tick-count shortcut
Code Lab also includes a Tick count bar type template based on the convenience TickCountCustomBarType. Use it when that bootstrap type exists and one candle should complete after the configured number of valid trade ticks. Derive from BarTypeBase and implement ProcessTick(...) directly when the convenience source is absent or the boundary rule is more complex.
Continue with Series and Bars, Market Data, and Build, test, and debug.