Skip to content

Your First Plugin

Use the meridian CLI to scaffold a plugin project, add data, write strategy logic, and run it.

Install the CLI

# Download the latest binary from GitHub Releases:
# https://github.com/Societal-Lab-Inc/meridian-cli/releases
go install github.com/Societal-Lab-Inc/meridian-cli@latest

Verify the installation:

meridian version
# meridian-cli v0.4.0

Scaffold a Signal Plugin

meridian new signal --lang python --name my-momentum

This creates a complete, runnable project:

my-momentum/
├── Makefile              # test, run, lint, fmt targets
├── requirements.txt      # open-meridian + test deps
├── data/
│   └── sample.csv        # starter price data (AAPL, 60 days)
├── src/
│   └── strategy.py       # your strategy — edit this
└── tests/
    └── test_strategy.py  # unit test skeleton

Add Data

Drop a CSV into data/. The minimum columns are date and close:

date,open,high,low,close,volume
2024-01-02,150.00,152.50,149.50,151.00,1000000
2024-01-03,151.00,153.00,150.00,152.50,1100000
2024-01-04,152.50,154.00,151.50,153.75,950000

Column names are flexible — the SDK recognizes common variants:

Standard Also accepted
date timestamp, time, dt
open o, Open
high h, High
low l, Low
close c, Close, adj_close
volume vol, v, Volume

You can also use Parquet files, DataFrames, or lists of dicts. See Local Development for details.

Edit Your Strategy

Open src/strategy.py. The scaffold generates this starting point:

from meridian import LocalClient, SignalEngine
from decimal import Decimal

client = LocalClient(starting_cash=100_000)
client.load_bars("AAPL", "data/sample.csv")


class MomentumStrategy(SignalEngine):
    def on_data(self, window):
        """Called once per bar date with a rolling window of history."""
        bars = window.bars("AAPL", lookback=20)
        if len(bars) < 20:
            return

        # 20-day return
        ret = (bars[-1].close - bars[0].close) / bars[0].close

        pos = self.client.positions("AAPL")
        holding = pos.get("AAPL", {}).get("quantity", Decimal(0))

        if ret > 0.03 and holding == 0:
            self.submit_order("AAPL", "BUY", 100)
        elif ret < -0.02 and holding > 0:
            self.submit_order("AAPL", "SELL", int(holding))


MomentumStrategy(client).run(warmup=20)

print("Positions:", client.positions())
print("Cash:", client.cash())
print("Fills:", len(client.fills()))

The on_data pattern is the core of every signal plugin:

  1. Pull historical bars from the window
  2. Compute your indicator or signal
  3. Call self.submit_order() when conditions are met

The window object gives you access to all loaded symbols. Use window.bars(symbol, lookback=N) for a slice of history and window.latest(symbol) for the current bar.

Run and Test

# Run the unit tests
make test

# Run the strategy end-to-end
make run

make run executes src/strategy.py and prints positions, cash, and trade history to stdout. make test runs pytest against tests/test_strategy.py.

Scaffold a Data Adapter (DGM) Plugin

Signal plugins consume data. DGM (Data Gateway Module) plugins produce it. To scaffold a data adapter:

meridian new dgm --lang python --name my-csv-loader

This generates a different project structure tailored for data ingestion:

my-csv-loader/
├── Makefile
├── requirements.txt
├── config/
│   └── sources.yaml      # data source configuration
├── src/
│   └── adapter.py        # your data adapter — edit this
└── tests/
    └── test_adapter.py

The adapter template shows the pattern for reading from an external source and publishing bars:

from meridian import LocalClient

client = LocalClient()

# Load from your source
client.load_bars("AAPL", "data/aapl_daily.csv")
client.load_bars("MSFT", "data/msft_daily.csv")

# In connected mode, this publishes to platform.data.eod.*
# In local mode, it makes the data available to signal plugins

List Available Templates

See all scaffolds the CLI can generate:

meridian new --list
Available templates:
  signal      Signal / alpha generation plugin
  dgm         Data Gateway Module (data adapter)
  ccm         Connectivity Module (broker adapter)
  portfolio   Portfolio construction plugin
  oms         Order management plugin
  ems         Execution management plugin

Each template includes a Makefile, test skeleton, and example configuration appropriate to the plugin type.

Next Steps

You built a plugin

Ready to share it?