Your First Plugin¶
Use the meridian CLI to scaffold a plugin project, add data, write strategy logic, and run it.
Install the CLI¶
Verify the installation:
Scaffold a Signal Plugin¶
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:
- Pull historical bars from the
window - Compute your indicator or signal
- 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¶
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:
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:
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:
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¶
- Strategy Gallery -- five complete strategies to study and modify
- What You Can Build -- explore all plugin types
- SDKs & Languages -- all SDKs, install commands, and API docs
You built a plugin
Ready to share it?
- Submit to the marketplace — get your plugin listed for other deployments to use
- Partner with us — bring your plugin to a wider audience
- Show it off in Discord #show-and-tell