Discovery & metadata

Strategies

Discovery & metadata

How the host finds your strategy class without a registration step, and how [StrategyMetadata] sets the name and description users see.

Discovery & metadata

There is no manifest and no registration call. When it loads your plugin, the host scans the assembly for launchable Strategy subclasses and adds each one to its strategy catalog. A type is launchable when it is a public, non-abstract Strategy subclass with a public parameterless constructor, because the catalog creates one instance per run. Copying the plugin DLL into the plugins folder is the whole deployment step.

Without metadata the catalog shows a name derived from the class name: it drops a trailing Strategy and splits the PascalCase words, so MaCrossStrategy becomes “Ma Cross”. Add [StrategyMetadata] (namespace SabrTrader.Pipeline.Strategies.Catalog) to set a display name and a one-line description. Both appear in the Strategy Analyzer and in the Control Center launch form.

C#using SabrTrader.Pipeline.Strategies;
using SabrTrader.Pipeline.Strategies.Catalog;

[StrategyMetadata(DisplayName = "Donchian Breakout", Description = "Buys a break of the N-bar high.")]
public sealed class DonchianBreakout : Strategy { /* ... */ }
Constructor rule. The host creates your strategy itself, once for discovery and once per run, so the class must stay constructible with no arguments. Do per-run setup in OnInitialize. The protected helpers throw InvalidOperationException when called from the constructor, because the run context is bound later.

How parameters are discovered

For each launchable type the catalog creates a throwaway instance and runs its OnInitialize once, unbound, to capture the parameters it declares. That is how the launch form knows your inputs and their optimization ranges without running the strategy, and why OnInitialize should only declare: touching bars, orders or the account there throws on the probe. Discovery tolerates failures: an assembly that fails to load or a constructor that throws leaves that type out of the catalog, and an OnInitialize that throws keeps the parameters declared before the throw.

The catalog

The host keeps the discovered strategies in its catalog. Each entry has a stable id, the full type name for a compiled strategy, so a saved run keeps resolving after a display-name change. A lookup matches the id, the display name, the type name or the full type name, case-insensitively. Strategy lists are sorted by display name. A plugin does not use the catalog; it ships a discoverable class.

Hot-reloaded and dynamic strategies

The catalog also holds entries added at runtime, and the host's strategy lists refresh when that set changes. A hot-reloaded plugin adds its compiled strategy, or replaces the earlier build of the same type (matched by full type name). Running instances keep their code; the next run uses the new build. A configuration-backed strategy is added by id, and its parameters come from the same probe a compiled type gets. A display name already used by another strategy is rejected.