Clone our Wealth-Lab 8 Extension Demo project on GitHub to get a head start in developing your own Extensions!

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.

Visual Studio 2026 Build Environment

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.Long for Buy/Sell Blocks
  • PositionType.Short for 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.