meridian
Autonomous market-making agents for RWA and long-tail assets where traditional AMMs fail.
Quick Start
git clone https://github.com/kcolbchain/meridian.git
cd meridian
pip install -r requirements.txt
# Run simulation with mock data
python -m src.agents.rwa_market_maker --config config/default.yaml --simulate
# Backtest a strategy
python -m src.backtest.engine --strategy adaptive_spread
The Problem
Current AMM models (constant product, concentrated liquidity) were designed for liquid, fungible tokens with continuous price discovery. They fail for real-world assets:
- Illiquid — RWA trades are infrequent, thin order books
- Irregular pricing — real estate, commodities, private credit don't have second-by-second feeds
- Geography-specific — the same asset class prices differently across jurisdictions
- Compliance-gated — not every counterparty can trade every asset
Constant product AMMs bleed capital in these conditions. LPs get destroyed by informed flow.
Architecture
┌─────────────────────────────────────┐
│ Agent Framework │
├──────────┬──────────┬───────────────┤
│ Strategies│ Oracle │ Backtest │
│ │ Feeds │ Engine │
├──────────┴──────────┴───────────────┤
│ Position & Risk Mgmt │
├─────────────────────────────────────┤
│ Chain Connectors (EVM) │
└─────────────────────────────────────┘
Base Agent
All agents extend BaseAgent which provides:
- Position tracking with PnL calculation (realized + unrealized)
- Order management and fill handling
- Event logging for analysis
- Main
tick()loop: evaluate → execute → rebalance
from src.agents.base_agent import BaseAgent
class MyAgent(BaseAgent):
def evaluate_market(self, market_data: dict) -> dict:
# Return signals dict
...
def execute_strategy(self, signals: dict) -> list[Order]:
# Generate orders from signals
...
def rebalance(self) -> list[Order]:
# Reduce exposure when limits exceeded
...
RWA Market Maker
The RWAMarketMaker is designed specifically for real-world assets:
| Feature | Description |
|---|---|
| Oracle-driven pricing | Prices based on real-world signals, not just pool state |
| Adaptive spreads | Wider in volatility, narrower in stability, adjusted for inventory |
| Geography-aware | Spread multiplier per jurisdiction (US 1.0x, IN 1.2x, LATAM 1.3x) |
| Inventory management | Auto-skews quotes to reduce directional exposure |
Constant Spread Strategy
Simple baseline: fixed bid/ask spread around a mid price. Good for benchmarking.
from src.strategies.constant_spread import compute_quotes, ConstantSpreadParams
params = ConstantSpreadParams(spread_bps=200) # 2% spread
quotes = compute_quotes(mid_price=100.0, params=params)
# {'bid': 99.0, 'ask': 101.0, 'spread_bps': 200}
Adaptive Spread Strategy
Adjusts spread based on volatility and inventory exposure. Widens when volatile, skews when inventory is imbalanced.
Writing Custom Strategies
Create a new file in src/strategies/ and implement the strategy interface. The agent framework is strategy-agnostic — plug in any pricing logic you want.
Oracle Price Feeds
Implement BasePriceFeed to integrate any data source:
MockPriceFeed— for testing and simulationChainlinkPriceFeed— Chainlink oracle integration (placeholder)- Custom feeds for real estate appraisals, commodity prices, etc.
Backtesting Engine
Replay historical data through any agent and measure performance:
from src.backtest.engine import BacktestEngine, BacktestTick
from src.agents.rwa_market_maker import RWAMarketMaker
agent = RWAMarketMaker("test", config)
engine = BacktestEngine(agent, fill_probability=0.4)
data = engine.generate_mock_data(100.0, 500)
result = engine.run(data)
print(f"Total PnL: {result.total_pnl:.2f}")
print(f"Sharpe: {result.sharpe_ratio:.3f}")
print(f"Max Drawdown: {result.max_drawdown:.2f}")
Configuration
All agent parameters are configurable via config/default.yaml:
agent:
initial_base: 0
initial_quote: 10000
base_spread_bps: 200
max_order_size_pct: 0.1
max_exposure: 50
geography: "default"