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.1.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 the Python SDK repo 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
meridian test

# Run the strategy end-to-end
make run

meridian test auto-detects your plugin language and runs the appropriate test suite (pytest for Python, go test for Go). You can also use make test directly.

To run only the conformance tests required for marketplace submission:

meridian test conformance

make run executes src/strategy.py and prints positions, cash, and trade history to stdout.

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:

  TYPE            LANGUAGE   DESCRIPTION
  signal          python     Signal engine
  dgm             python     Data Gateway Manager
  ccm             python     Connectivity Module (broker adapter)
  oms             python     Order management plugin
  ems             python     Execution management plugin
  portfolio       python     Portfolio construction 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?