Your first plugin
Your first plugin
Create the project, write a working indicator, build it, deploy it, and see it on a chart. This is the full round-trip — about ten minutes end to end.
Create the project
A plugin is a normal class library. Create one and add the SDK package. We will build an indicator here because it is the quickest thing to see on screen, but the project shape is identical for every plugin kind.
shelldotnet new classlib -n MyFirstPlugin -f net10.0
cd MyFirstPlugin
dotnet add package TradeStrike.Sdk --version 0.1.0
Open the generated .csproj and make it look like the one below. The two
DeployToAlgoStudioPlugins properties are optional but worth setting now: they come from
an MSBuild target inside the SDK package and copy your built DLL straight into the host's
Plugins folder on every build, so you never copy files by hand while developing.
MyFirstPlugin.csproj<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<!-- Copy the built DLL into the host's Plugins folder on every build. -->
<DeployToAlgoStudioPlugins>true</DeployToAlgoStudioPlugins>
<!-- Override the destination if you don't use the default %AppData% folder. -->
<AlgoStudioProPluginsFolder>C:\Program Files\TradeStrike\Plugins</AlgoStudioProPluginsFolder>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TradeStrike.Sdk" Version="0.1.0" />
</ItemGroup>
</Project>
AlgoStudioProPluginsFolder out, the target
deploys to %AppData%\AlgoStudioPro\Plugins. Set it explicitly when your host lives
elsewhere — see Where to deploy.
net10.0-windows and add <UseWPF>true</UseWPF>. Most indicators and
all strategies, bar types and data providers do not need WPF, so stay on plain
net10.0 unless you hit a reason to switch.
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. Read it once now; the
Indicators chapter explains every line in detail, but the shape is
already worth recognising: 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 TradeStrike.Pipeline.Indicators;
using TradeStrike.Pipeline.Plots;
using TradeStrike.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 entire plugin. Notice what is not there: no registration code, no manifest, no
host configuration. Discovery is purely by type — the loader sees a public class deriving from
IndicatorBase and registers it. The [IndicatorDescription] text becomes the
blurb users read in the Add-Indicator dialog.
OnDataLoaded and OnBarUpdate are virtual lifecycle
hooks on IndicatorBase; you override only the ones you need. ChunkedSeries<double>
is the SDK's writable, append-only series — appends are O(1) and NaN-aware, so warmup bars render
as gaps. You hand it to a Plot and the chart reads it; you never expose it directly.
Build & deploy
Build in Release. Because we set DeployToAlgoStudioPlugins=true, the build copies
MyFirstPlugin.dll into the host's Plugins folder and logs where it went.
shelldotnet build -c Release
build logTradeStrike.Sdk: deploying plugin 'MyFirstPlugin.dll' to 'C:\Program Files\TradeStrike\Plugins'
If you would rather copy the file yourself, that is fine too — just remember the one rule: copy
only the plugin DLL, never its dependencies or .deps.json. The exact folder and
the reasoning behind that rule are covered in the
Building & deploying chapter.
See it on a chart
Plugins are scanned once, at startup, so the workflow is "build, then relaunch". After that your indicator behaves exactly like a built-in one.
- Close TradeStrike if it is running.
- Launch it. During startup the plugin loader scans the
Pluginsfolder and registers your indicator into the shared catalog. - Open a chart, click Add Indicator, and find MedianPrice in the list — its
description is the text from
[IndicatorDescription]. - Add it. A blue median line is drawn over your candles, on history and live.
Plugins. The loader records every load and registration there, so a missing dependency
or a wrongly-deployed contract DLL is visible immediately. The
Troubleshooting page lists the common causes.