Building Block Extension API
A Building Block Extension allows you to create custom Building Blocks that users can drag and drop onto the Building Block Strategy design surface in WealthLab 9. Building Blocks generate C# Strategy code behind the scenes, allowing an extension to provide reusable entries, exits, conditions, qualifiers, and other Strategy logic without requiring the user to write code.
Build Environment
You can create a BuildingBlock in a .NET development tool such as Visual Studio 2026.
Create a class library project that targets .NET10, then reference the WealthLab.Core library DLL that you'll find in the WL9 installation folder.
Your BuildingBlock will be a class in this library that descends from BuildingBlockBase, which is defined in the WealthLab.Core library, in the WealthLab.Backtest namespace. After you implement and build your library, simply copy the resulting assembly DLL into the WL9 installation folder. The next time WL9 starts up, it will discover your BuildingBlock, making it available in appropriate locations of the WL9 user interface.

By default, your Blocks appear under a node in the Building Block tree named after your extension assembly. You can change this by assigning a value to the Building Block's LibraryName property.
Accessing the Host (WL9) Environment
The IHost interface provides access to the current WealthLab environment. Extensions can use it to retrieve application-level information and services, such as the location of the user's WealthLab data folder or the DataSets defined by the user.
You can access the current IHost instance from anywhere in your extension through the WLHost singleton and its Instance property. For example, the following code retrieves the path to the user's WealthLab data folder:
string folder = WLHost.Instance.DataFolder;
Use WLHost.Instance whenever your extension needs access to functionality exposed by the IHost interface.
Building Block Types
Although BuildingBlockBase is the common base class for all Building Blocks, your implementation will normally derive from one of three specialized classes:
- EntryExitBuildingBlock - Entry and Exit Blocks
- ConditionBuildingBlock - Condition Blocks
- QualifierBuildingBlock - Qualifier Blocks
Configuring a Building Block
BuildingBlockBase derives from Configurable, which provides the standard WealthLab framework for configuring extensions. Building Blocks use a ConfigurableType of ParameterList, which should not be changed. Define the configurable settings for your Building Block by adding Parameter instances in GenerateParameters. The Configurable base class also provides descriptive properties that determine how your Building Block appears in WealthLab. Important properties to override include Name, Description, and GlyphResource.
Code Generation
Building Blocks work by generating C# code. WealthLab combines the code generated by all Blocks in a Strategy and compiles the result just like a C# Coded Strategy. You can see the generated code for a Building Block Strategy by selecting Open as C# Coded Strategy in the Strategy window. BuildingBlockBase provides several code-generation properties and methods corresponding to different parts of the generated Strategy.
Initialize
public virtual void Initialize()
Override this method to perform one-time initialization of the Building Block itself. This is typically where you register variables using RegisterVariable. You can also set LibraryName here to control the node under which the Block appears in the Building Block tree.
Private Variables
public List<string> VarCode
Contains C# declarations that will be injected into the private variables section of the generated Strategy. The Building Block framework provides variable registration and naming support to ensure that variable names remain unique even when multiple instances of the same Building Block are used in a Strategy.
public virtual void GenerateVarCode()
Generates the private variable declarations. Normally you do not need to override this method. The default implementation generates declarations for variables registered through RegisterVariable. If you override GenerateVarCode, call the base implementation before adding your own lines:
base.GenerateVarCode();
Strategy Initialization
public List<string> InitCode
Contains code that will be injected into the generated Strategy's Initialize method. Use this code to initialize indicators and other variables. Generated code can reference the bars BarHistory instance passed to the Strategy's Initialize method.
public virtual void GenerateInitCode()
Override this method and add the desired C# statements to InitCode.
Strategy Cleanup
public List<string> CleanupCode
Contains code that will be injected into the generated Strategy's Cleanup method. Generated code can reference the bars BarHistory instance passed to Cleanup.
public virtual void GenerateCleanupCode()
Override this method and add the desired C# statements to CleanupCode.
Main Execution Code
public List<string> MainCode
Contains code that will be injected into the generated Strategy's Execute method. Generated code can reference the bars BarHistory instance and the current index being processed.
public abstract void GenerateMainCode()
Override this method to generate the primary execution logic for the Building Block by adding C# statements to MainCode. The exact implementation depends on the type of Building Block.
PreExecute Code
public List<string> PreExecCode
Contains code that will be injected into the generated Strategy's PreExecute method. WealthLab generates a PreExecute override only when this collection contains code. The generated method uses the standard PreExecute signature, including the dt DateTime and participants List<BarHistory> parameters.
public virtual void GeneratePreExecCode()
Override this method and add C# statements to PreExecCode.
PostExecute Code
public List<string> PostExecCode
Contains code that will be injected into the generated Strategy's PostExecute method. WealthLab generates a PostExecute override only when this collection contains code. The generated method uses the standard PostExecute signature, including the dt DateTime and participants List<BarHistory> parameters.
public virtual void GeneratePostExecCode()
Override this method and add C# statements to PostExecCode.
BacktestBegin Code
public List<string> BacktestBeginCode
Contains code that will be injected into the generated Strategy's BacktestBegin method. WealthLab generates a BacktestBegin override only when this collection contains code.
public virtual void GenerateBacktestBeginCode()
Override this method and add C# statements to BacktestBeginCode.
BacktestComplete Code
public List<string> BacktestCompleteCode
Contains code that will be injected into the generated Strategy's BacktestComplete method. WealthLab generates a BacktestComplete override only when this collection contains code.
public virtual void GenerateBacktestCompleteCode()
Override this method and add C# statements to BacktestCompleteCode.
Adding Namespaces to Generated Code
public List<string> UsingClauseLibs
Contains namespaces that will be added to the using section of the generated Strategy. If your Building Block generates code that references classes from your extension or another namespace that WealthLab does not include by default, add the required namespace using AddToUsingClause.
public void AddToUsingClause(string libraryName)
Adds the specified namespace to the generated Strategy's using section. Use this helper instead of modifying UsingClauseLibs directly. It ensures that a namespace is added only once.
Building Block Parameters
public ParameterList Parameters
Contains the Parameter instances that configure the Building Block. WealthLab supports many Parameter types for values such as numbers, strings, indicators, enumerations, and comparison operations. See the Parameter class reference for the complete set of supported types.
public virtual void GenerateParameters()
Override this method to define the Building Block's configurable Parameters. Useful Configurable helper methods include:
- AddParameter
- AddIndicatorParameter
- AddValueCompareParameter
- AddEnumParameter
BuildingBlockTextOutput
// Parameter class property
public string BuildingBlockTextOutput
Use a Parameter's BuildingBlockTextOutput property when inserting its configured value into generated C# code. Unlike retrieving the Parameter's value directly, BuildingBlockTextOutput formats the value appropriately for inclusion in generated source code. For example:
public override void GenerateParameters()
{
AddParameter("Day of Week", ParameterType.Int32, 1);
AddValueCompareParameter();
}
public override void GenerateMainCode()
{
string day = Parameters[0].BuildingBlockTextOutput;
string operand = Parameters[1].AsCompareOperation;
MainCode.Add(
"if (bars.DateTimes[index].Day " + operand + " " + day + ")");
MainCode.Add(
" SetBackgroundColor(index, Colors.LightGreen);");
}
Building Block Description
Override the Description property to return a brief description of the Building Block in its current configuration. WealthLab displays this text on the Building Block Strategy design surface. For Entry and Exit Blocks, WealthLab prepends the appropriate action, such as Buy, Sell, Short, or Cover, so the Description should generally return only the remainder of the text. For example, an Entry Block might return:
at Market
and WealthLab would display:
Buy at Market
The Description should reflect the Block's current Parameter values so that users can understand its configuration directly from the design surface.
Defining Variables
public void RegisterVariable(
string varName,
string varType,
int parameterNum = -1)
Call RegisterVariable from Initialize to register a C# variable used by your generated code. When referring to a registered variable in InitCode, MainCode, or another code-generation collection, surround its registered name with angle brackets:
<variableName>
WealthLab replaces these references with unique variable names in the generated Strategy. This prevents naming conflicts when multiple instances of the same Building Block are used. If the variable corresponds to one of the Building Block's Parameters, supply that Parameter's zero-based index in parameterNum. For example:
public override void Initialize()
{
RegisterVariable("n", "int");
}
public override void GenerateInitCode()
{
InitCode.Add("<n> = bars.Count;");
}
public override void GenerateMainCode()
{
MainCode.Add("<n>--;");
}
The generated Strategy will use a unique C# variable name in place of <n>.
Working with Indicators
public void GenerateIndicatorInitCode(
int paramNum,
string paramName,
string parentIndicator = "")
Call this helper from GenerateInitCode to generate initialization code for a variable associated with an Indicator Parameter. Indicator Parameters are created using AddIndicatorParameter and have a Parameter type of Indicator or Smoother. Pass the zero-based Parameter index in paramNum and the corresponding registered variable name in paramName. For example:
public override void GenerateParameters()
{
AddIndicatorParameter("Slow MA", "SMA");
AddIndicatorParameter("Fast MA", "SMA");
}
public override void Initialize()
{
RegisterVariable("slowMA", "IndicatorBase", 0);
RegisterVariable("fastMA", "IndicatorBase", 1);
}
public override void GenerateInitCode()
{
GenerateIndicatorInitCode(0, "slowMA");
GenerateIndicatorInitCode(1, "fastMA");
}
Entry and Exit Building Blocks
Building Blocks that enter or exit positions derive from EntryExitBuildingBlock. Their primary responsibility is to generate the appropriate trading code.
public virtual bool IsEntry => false;
public virtual bool IsExit => false;
Override the appropriate property to return true depending on whether the Block represents an entry or an exit.
public virtual PositionType? PositionType
Override this property to indicate whether the Block operates on Long or Short positions:
PositionType.Longfor Buy/Sell BlocksPositionType.Shortfor Short/Cover Blocks
GroupCode
public int GroupCode
GroupCode is assigned by the Building Block framework and allows the generated Strategy to associate Entry and Exit Blocks with the appropriate position group. For an Entry Block, generated code should call PlaceTrade and assign the resulting Transaction to the predefined _transaction variable. For example, a Buy at Market Block can generate:
public override void GenerateMainCode()
{
MainCode.Add(
"_transaction = PlaceTrade(bars, TransactionType.Buy, " +
"OrderType.Market, 0, " + GroupCode + ");");
base.GenerateMainCode();
}
Note the call to base.GenerateMainCode() after adding the Entry code. For Exit Blocks, WealthLab provides a generated variable named foundPositionN, where N is the Block's GroupCode. An Exit Block can use this variable with ClosePosition:
public override void GenerateMainCode()
{
MainCode.Add(
"ClosePosition(foundPosition" + GroupCode +
", OrderType.Market);");
}
Condition Building Blocks
Condition Blocks derive from ConditionBuildingBlock. They typically evaluate their Parameters and generate an if statement that determines whether their child Blocks should execute.
public abstract void GenerateConditionCode()
Override GenerateConditionCode rather than GenerateMainCode. Add the generated condition to MainCode. The final generated line should be an if statement without an opening brace. For example:
public override void GenerateConditionCode()
{
string operand = Parameters[1].AsOperand;
string barsBack = Parameters[3].BuildingBlockTextOutput;
MainCode.Add(
"if (index - " + barsBack +
" >= 0 && <indicator1>[index] " +
operand +
" <indicator2>[index - " + barsBack + "])");
}
WealthLab's code generator supplies the body of the condition based on the Blocks nested beneath it.
Qualifier Building Blocks
Qualifier Blocks derive from QualifierBuildingBlock. A Qualifier modifies the behavior of a parent Condition Block by wrapping or otherwise altering its generated condition logic. Qualifier-generated code can reference the parent Condition's if statement using the special:
<Condition>
tag.
Like a Condition Block, the Qualifier's generated code should ultimately end with an if statement without an opening brace. For example, the following Qualifier evaluates its parent Condition a configurable number of bars ago:
using WealthLab.Core;
namespace WealthLab.Backtest
{
public class NBarsAgo : QualifierBuildingBlock
{
public override void GenerateParameters()
{
Parameter p = AddParameter(
"How many bars ago",
ParameterType.Int32,
1);
p.MinValue = 1.0;
}
public override void Initialize()
{
RegisterVariable("savedIndex", "int");
RegisterVariable("flag", "bool");
}
public override string Name => "N Bars Ago";
public override void GenerateMainCode()
{
string numBars =
Parameters[0].BuildingBlockTextOutput;
MainCode.Add("<savedIndex> = index;");
MainCode.Add("<flag> = false;");
MainCode.Add("index = index - " + numBars + ";");
MainCode.Add("if (index >= 0)");
MainCode.Add("{");
MainCode.Add("\t<Condition>");
MainCode.Add("\t\t<flag> = true;");
MainCode.Add("}");
MainCode.Add("index = <savedIndex>;");
MainCode.Add("if (<flag>)");
}
public override string Description
{
get
{
int bars = Parameters[0].AsInt;
return bars.ToString() +
(bars == 1 ? " bar" : " bars") +
" ago";
}
}
}
}
Supporting Same-Bar Exits
Some Exit Building Blocks can participate in WealthLab's same-bar exit processing.
SupportsSameBarExit
public virtual bool SupportsSameBarExit
Override this property and return true if the Exit Building Block supports same-bar exits. When supported, WealthLab displays a checkbox for the Block that allows the Strategy creator to enable same-bar exit processing.
GenerateSameBarExitCode
public virtual void GenerateSameBarExitCode()
Override this method to generate the code required for the same-bar exit. Add generated statements to the Building Block's SameBarExitCode collection, which is a List<string> similar to MainCode and InitCode. The generated code is injected into the Strategy's AssignAutoStopTargetPrices method. This code can reference the Transaction passed to the method as t and should call either:
- AssignAutoProfitTargetPrice
- AssignAutoStopLossPrice
These methods perform the necessary pruning when multiple same-bar Exit Blocks are present. You can also assume that a local double variable named price is available. For example, the Sell at Profit Target Block generates:
public override void GenerateSameBarExitCode()
{
double mult = Parameters[0].AsDouble / 100.0 + 1.0;
SameBarExitCode.Add(
"\t\t\tprice = executionPrice * " + mult + ";");
SameBarExitCode.Add(
"\t\t\tt.AssignAutoProfitTargetPrice(price);");
}
Associating a Building Block with a Strategy Gene
public virtual StrategyGeneBase GetGene()
If your Building Block can be represented by a Strategy Genetic Evolver Strategy Gene, override GetGene to establish the association. Create and return an instance of the appropriate StrategyGeneBase descendant and configure its properties using the Building Block's current Parameter values. This allows the Building Block to participate in WealthLab features that operate on Strategy Genes.