Your first plugin
Your first plugin
Create the project, write a working indicator, build it, deploy it, and see it on a chart.
Create the project
A plugin is a normal class library. Create one and add the SDK package. This page builds an indicator because it is the quickest result to see on screen; the project shape is the same for every plugin kind.
shelldotnet new classlib -n MyFirstPlugin -f net10.0
cd MyFirstPlugin
dotnet add package SabrTrader.Sdk
Open the generated .csproj and make it look like the one below.
DeploySabrTraderPlugin is optional but worth setting now: it switches on an MSBuild
target from the SDK package that copies your built DLL into the plugin folder on every build.
MyFirstPlugin.csproj<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<!-- Copy the built DLL into Documents\SabrTrader\Plugins on every build. -->
<DeploySabrTraderPlugin>true</DeploySabrTraderPlugin>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SabrTrader.Sdk" Version="0.18.0" />
</ItemGroup>
</Project>
SabrTrader\Plugins in your real Documents
folder, including a Documents folder redirected to OneDrive or a network share. Set
<SabrTraderPluginsFolder> to deploy somewhere else; see
Where to deploy.
net10.0 covers every
plugin kind. Target net10.0-windows only if you choose to use WPF types yourself.
Write the indicator
Create MedianPrice.cs with the code below. It is a complete, working indicator that plots
each bar's median price, the midpoint between high and low. The
Indicators chapter explains each part in detail. The shape is a
writable output series, a constructor that registers a plot, and two lifecycle methods that fill the
series: once over history, then once per closed live bar.
MedianPrice.csusing SabrTrader.Pipeline.Indicators;
using SabrTrader.Pipeline.Plots;
using SabrTrader.Pipeline.Series;
namespace MyFirstPlugin;
[IndicatorDescription("Median price: the (high + low) / 2 midpoint of each bar.")]
public sealed class MedianPrice : IndicatorBase
{
// The indicator owns the writable backing store; the plot reads it.
private readonly ChunkedSeries<double> _output = new();
// Canonical ctor shape: parent for child composition (null = standalone),
// input for an explicit source series. The host calls this, then applies settings.
public MedianPrice(IIndicator? parent = null, ISeries<double>? input = null)
: base(parent, input)
{
// Register one plotted line. AddPlot is called once, from the ctor.
AddPlot(new Plot("Median", _output, PlotStyle.Line, new ChartColor(91, 157, 255), 1.5));
}
// History: one pass over the whole backfill, oldest bar first so values
// land in chronological order (i is barsAgo: Count-1 = oldest, 0 = newest).
public override void OnDataLoaded(IIndicatorContext ctx)
{
var bars = ctx.Bars(0);
for (int i = bars.Count - 1; i >= 0; i--)
_output.Append((bars[i].High + bars[i].Low) / 2.0);
}
// Live: one new value each time a bar closes.
public override void OnBarUpdate(IIndicatorContext ctx)
{
var b = ctx.Bars(0)[0];
_output.Append((b.High + b.Low) / 2.0);
}
}
That is the whole plugin. There is no registration code and no configuration: the platform finds
a public class deriving from IndicatorBase and registers it. The
[IndicatorDescription] text is the description users read in the indicator picker.
OnDataLoaded and OnBarUpdate are virtual lifecycle
methods on IndicatorBase; override the ones you need. ChunkedSeries<double>
is the SDK's writable series: Append adds a value in constant time, and
double.NaN values render as gaps. You hand the series to a Plot, and the
chart reads it from there.
Build & deploy
Build the project. With DeploySabrTraderPlugin set to true, the build
copies MyFirstPlugin.dll (and its PDB) into the plugin folder and logs where it went.
shelldotnet build -c Release
build logSabrTrader.Sdk: deploying plugin 'MyFirstPlugin.dll' to 'C:\Users\you\Documents\SabrTrader\Plugins'
To deploy by hand, copy bin\Release\net10.0\MyFirstPlugin.dll into
Documents\SabrTrader\Plugins. The Building &
deploying chapter covers the folder and what else may go in it.
See it on a chart
SabrTrader watches the plugin folder, so it does not matter whether it is running when you deploy. A DLL that is present at startup loads during startup; a DLL copied or rebuilt while the platform runs loads within a second or so of the copy finishing.
- Build (or copy the DLL) as above.
- Open a chart, open the indicator picker, and find MedianPrice in the list. Its
description is the text from
[IndicatorDescription]. - Add it. A blue median line is drawn over the bars, on history and live.
- Change the code and build again. The indicator on the open chart switches to the new build without a restart.
Plugins category. The platform logs every load, reload and registration error there,
naming the DLL or type involved. The
Troubleshooting page lists the common causes.