Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 70 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<h3 align="center">Autonomous Trading Agent for Hyperliquid</h3>

<p align="center">
14 strategies &bull; APEX multi-slot orchestrator &bull; REFLECT nightly review &bull; MCP server &bull; Agent Skills
18 strategies &bull; APEX multi-slot orchestrator &bull; REFLECT nightly review &bull; MCP server &bull; Agent Skills
</p>

<p align="center">
Expand All @@ -18,15 +18,15 @@

<p align="center">
<img src="https://img.shields.io/badge/python-3.10+-3776AB?logo=python&logoColor=white" alt="Python" />
<img src="https://img.shields.io/badge/strategies-14-C9A84C" alt="Strategies" />
<img src="https://img.shields.io/badge/tests-483%20passing-brightgreen" alt="Tests" />
<img src="https://img.shields.io/badge/strategies-18-C9A84C" alt="Strategies" />
<img src="https://img.shields.io/badge/tests-1317%20passing-brightgreen" alt="Tests" />
<img src="https://img.shields.io/badge/license-MIT-blue" alt="License" />
<img src="https://img.shields.io/badge/MCP-18%20tools-8A2BE2" alt="MCP" />
<img src="https://img.shields.io/badge/MCP-25%20tools-8A2BE2" alt="MCP" />
</p>

<p align="center">
<a href="https://railway.com/new/template?template=https://github.com/Nunchi-trade/agent-cli&envs=HL_PRIVATE_KEY,HL_TESTNET,RUN_MODE,APEX_PRESET&HL_TESTNETDefault=true&RUN_MODEDefault=apex&APEX_PRESETDefault=default">
<img src="https://railway.com/button.svg" alt="Deploy on Railway" height="36" />
<a href="https://auth.nunchi.trade">
<img src="https://img.shields.io/badge/Launch%20via-Nunchi%20Auth-C9A84C" alt="Launch via Nunchi Auth" height="36" />
</a>
</p>

Expand Down Expand Up @@ -135,7 +135,7 @@ Supporting strategies for portfolio management, block liquidity, and autonomous
|----------|-------------|----------------|-------------|
| `hedge_agent` | Inventory exposure reducer. Fires when net notional exceeds threshold. This is not the BTCSWP funding-rate hedge; use `hl hedge propose` / `hl hedge backtest` for that. | `notional_threshold` | Always-on risk overlay. Pairs with any MM or signal strategy. |
| `rfq_agent` | Block-size dark RFQ liquidity — quotes for large orders with wider spreads. | `min_size`, `spread_bps` | Institutional/block flow. Provides hidden liquidity for large counterparties. |
| `claude_agent` | Multi-model LLM trading agent. Sends market snapshot to an LLM (Gemini, Claude, or OpenAI), receives structured trade decisions. | `model`, `base_size` | Experimental/research. Autonomous decision-making using LLM reasoning. |
| `ai_agent` | Nunchi-hosted LLM trading agent. Sends market snapshots to hosted inference and receives structured trade decisions. | `model`, `base_size` | Subscription-gated hosted-agent product; not required for BYO-agent MCP use. |

### Quoting Engine Pipeline

Expand All @@ -146,10 +146,13 @@ Market Data -> Composite Fair Value -> Dynamic Spread -> Inventory Skew -> Multi
(4-signal blend) (fee+vol+tox) (price+size) (exponential decay)
```

### LLM Agent (Multi-Model)
### Hosted LLM Agent (Multi-Model)

`ai_agent` is the hosted-agent product path. Generic MCP users bring their own agent and call the MCP tools directly; they do not need these provider keys.

| Provider | Models | Env Variable |
|----------|--------|-------------|
| OpenRouter | `openrouter/auto`, `openrouter/fusion` | `OPENROUTER_API_KEY` |
| Google Gemini | `gemini-2.0-flash` (default), `gemini-2.5-pro` | `GEMINI_API_KEY` |
| Anthropic Claude | `claude-haiku-4-5-20251001`, `claude-sonnet-4-20250514` | `ANTHROPIC_API_KEY` |
| OpenAI | `gpt-4o`, `gpt-4o-mini`, `o3-mini` | `OPENAI_API_KEY` |
Expand Down Expand Up @@ -490,16 +493,48 @@ hl mcp serve # Start MCP server

## MCP Server

Expose all trading tools via [Model Context Protocol](https://modelcontextprotocol.io) for AI agent integration.
Expose all trading tools via [Model Context Protocol](https://modelcontextprotocol.io) for AI agent integration. This is the BYO-agent path: Cursor, Claude, Codex, or any custom MCP-capable agent calls MCP tools, and those tools invoke `agent-cli`.

### Hosted MCP (Recommended)

Use the hosted Nunchi MCP when you want a Robinhood-style setup: paste one URL into your AI client, authenticate with web-auth, select a wallet, and grant scoped tool access. Your AI client receives a scoped MCP token, not your exchange private key.

```bash
https://agent.nunchi.trade/mcp/trading
```

Client setup:

```bash
# Cursor
Settings -> Cursor Settings -> Tools & MCPs -> Connect
MCP URL: https://agent.nunchi.trade/mcp/trading

# Claude Code
claude mcp add nunchi-trading --transport http https://agent.nunchi.trade/mcp/trading

# Codex CLI
codex mcp add nunchi-trading --url https://agent.nunchi.trade/mcp/trading
```

After connecting, authenticate in the browser consent flow and start with:

```text
Run setup_check, then show my account status and available strategies.
```

Hosted MCP access defaults to read-only/testnet. Write tools (`trade`, `run_strategy`, `apex_run`, `money_*`) and mainnet access require explicit web-auth consent and gateway-enforced limits.

### Local MCP (Development Only)

```bash
hl mcp serve # stdio transport (default)
hl mcp serve --transport sse # SSE transport
```

**18 tools exposed:** `account`, `status`, `trade`, `run_strategy`, `strategies`, `funding_hedge_propose`, `funding_hedge_backtest`, `radar_run`, `apex_status`, `apex_run`, `reflect_run`, `setup_check`, `builder_status`, `wallet_list`, `wallet_auto`, `agent_memory`, `trade_journal`, `judge_report`
**25 tools exposed:** `account`, `status`, `trade`, `run_strategy`, `strategies`, `funding_hedge_propose`, `funding_hedge_backtest`, `radar_run`, `apex_status`, `apex_run`, `reflect_run`, `setup_check`, `builder_status`, `wallet_list`, `wallet_auto`, `pair_status`, `approve_agent`, `money_withdraw`, `money_transfer_usd`, `money_deposit`, `money_bridge_status`, `agent_memory`, `trade_journal`, `judge_report`, `obsidian_context`

Fast tools (strategies, builder, wallet, setup, memory, journal, judge) call Python directly — zero subprocess overhead.
Fast tools (strategies, builder, wallet, setup, memory, journal, judge) call Python directly — zero subprocess overhead. Local MCP is for development and agent harness testing only; hosted MCP goes through web-auth for wallet selection, consent, and scoped token minting.

### HTTP API & SSE

Expand All @@ -509,59 +544,31 @@ Every deployed agent also exposes an HTTP REST API and SSE real-time feed for da

---

## Deploy on Railway

Two deployment options: **headless** (APEX runs strategies directly) or **OpenClaw agent** (conversational AI trading assistant with Telegram).

### Option A: Headless APEX (Deterministic)

One-click deploy to run APEX autonomously. No AI model needed — pure deterministic strategy execution.

[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/new/template?template=https://github.com/Nunchi-trade/agent-cli&envs=HL_PRIVATE_KEY,HL_TESTNET,RUN_MODE,APEX_PRESET&HL_TESTNETDefault=true&RUN_MODEDefault=apex&APEX_PRESETDefault=default)

| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `HL_PRIVATE_KEY` | Yes | — | Your Hyperliquid private key |
| `HL_TESTNET` | No | `true` | `true` for testnet, `false` for mainnet |
| `RUN_MODE` | No | `apex` | `apex`, `wolf` (alias), `strategy`, or `mcp` |
| `APEX_PRESET` | No | `default` | `conservative`, `default`, or `aggressive` |
## Hosted Agent Deployment

**Run modes:**
- **apex** (default) — APEX multi-slot orchestrator with autonomous entry, exit, Guard trailing stops, and REFLECT self-improvement loop
- **strategy** — Single strategy loop (set `STRATEGY=engine_mm`, `avellaneda_mm`, etc.)
- **mcp** — MCP server for AI agent integration (SSE transport)
The only supported hosted deployment path is **Nunchi-hosted**: users pay in web-auth, bind an agent wallet, and Nunchi provisions and manages the agent on Nunchi-owned Railway infrastructure.

### Option B: OpenClaw Agent (Conversational AI)
Start here:

One-click deploy of a full OpenClaw agent that uses our CLI as the tool backend. Talk to your trading bot via Telegram — it scans markets, enters trades, manages risk, and learns from its mistakes.
[Launch a hosted agent through Nunchi Auth](https://auth.nunchi.trade)

[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/new/template?template=https://github.com/Nunchi-trade/agent-cli/tree/main/deploy/openclaw-railway&envs=HL_PRIVATE_KEY,AI_PROVIDER,AI_API_KEY,TELEGRAM_BOT_TOKEN,TELEGRAM_USERNAME,HL_TESTNET&HL_TESTNETDefault=true)
User flow:

| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `HL_PRIVATE_KEY` | Yes | — | Your Hyperliquid private key |
| `AI_PROVIDER` | Yes | — | `anthropic`, `openai`, `gemini`, or `openrouter` |
| `AI_API_KEY` | Yes | — | API key for the chosen AI provider |
| `TELEGRAM_BOT_TOKEN` | Yes | — | Telegram bot token (from @BotFather) |
| `TELEGRAM_USERNAME` | Yes | — | Your Telegram @username |
| `HL_TESTNET` | No | `true` | `true` for testnet, `false` for mainnet |
1. Open web-auth and connect a wallet.
2. Bind or create an agent wallet.
3. Pay for the hosted-agent subscription with Stripe-supported payment methods or USDC.
4. Deploy the hosted agent from the wallet binding page.
5. Refresh status and open the hosted endpoint returned by web-auth.

**What you get:**
- OpenClaw gateway with web UI at `/openclaw`
- Telegram integration — chat with your bot to start/stop trading, run scans, check status
- Our 13 MCP trading tools as the agent's primary capabilities
- Persistent state across redeploys via `/data` volume
- Auto-onboard: bot sends "Agent ready" to Telegram on first deploy
- REFLECT self-improvement: the agent analyzes its own trades and adjusts strategy parameters
Hosted agents use Nunchi-owned inference credentials by default:

**How it works:**
1. Deploy sets up OpenClaw + our `hl mcp serve` as the tool provider
2. Bot auto-configures Telegram and sends you a ready message
3. Tell it "start trading" → it runs APEX with autonomous entry, exit, and risk management
4. Ask "how did we do?" → it runs REFLECT and reports performance metrics
5. The agent reads workspace files (AGENTS.md, SOUL.md) that define its trading behavior
| Variable | Default | Description |
|----------|---------|-------------|
| `AI_PROVIDER` | `openrouter` | OpenAI-compatible hosted inference |
| `AI_MODEL` | `openrouter/auto` | Low-latency/cost-aware default for chat and tool use |
| `NUNCHI_REFLECT_MODEL` | `openrouter/fusion` | Higher-confidence model for REFLECT/research-style analysis |

Both options persist state via Railway volume at `/data` — APEX state, REFLECT reports, Radar history, and agent memory survive redeploys.
Users do not need Railway credentials, Railway project access, or provider API keys. Billing, entitlement checks, wallet binding, secret injection, lifecycle controls, and hosted endpoint discovery all live in web-auth. This repository intentionally does not include Dockerfiles, `railway.toml`, or public deployment templates.

---

Expand All @@ -588,12 +595,12 @@ hl run engine_mm -i BTCSWP-USDYP --tick 10
```
cli/ CLI commands and trading engine
commands/ Subcommand modules (run, apex, radar, pulse, guard, reflect, house, ...)
mcp_server.py MCP server (18 tools via FastMCP)
mcp_server.py MCP server (25 tools via FastMCP)
hl_adapter.py Direct HL API adapter (live + mock)
builder_fee.py Builder fee config (HL native BuilderInfo)
keystore.py Encrypted keystore (geth-compatible)
strategy_registry.py Strategy + YEX market definitions
strategies/ 14 trading strategy implementations
strategies/ 18 trading strategy implementations
modules/ Pure logic modules (zero I/O)
apex_engine.py APEX decision engine
radar_engine.py Opportunity radar
Expand All @@ -612,7 +619,7 @@ skills/ Agent Skills (SKILL.md + runners)
sdk/ Strategy base class and model registry
parent/ HL API proxy, position tracking, risk management
scripts/ Backtest harness, bootstrap
tests/ Test suite (483 tests)
tests/ Test suite (1,317 tests)
```

---
Expand Down Expand Up @@ -664,9 +671,9 @@ hl run my_strategies.my_strategy:MyStrategy -i ETH-PERP --tick 10
| `HL_TESTNET` | No | `true` (default) or `false` for mainnet |
| `BUILDER_ADDRESS` | No | Override builder fee address |
| `BUILDER_FEE_TENTHS_BPS` | No | Override fee rate (default: 100 = 10 bps) |
| `ANTHROPIC_API_KEY` | No | For `claude_agent` with Claude |
| `GEMINI_API_KEY` | No | For `claude_agent` with Gemini |
| `OPENAI_API_KEY` | No | For `claude_agent` with OpenAI |
| `ANTHROPIC_API_KEY` | No | For `ai_agent` with Claude |
| `GEMINI_API_KEY` | No | For `ai_agent` with Gemini |
| `OPENAI_API_KEY` | No | For `ai_agent` with OpenAI |

\* Either `HL_PRIVATE_KEY` or a keystore with `HL_KEYSTORE_PASSWORD` is required.

Expand All @@ -676,7 +683,7 @@ hl run my_strategies.my_strategy:MyStrategy -i ETH-PERP --tick 10

```bash
pip install -e ".[dev]"
pytest tests/ -v # 483 tests
pytest tests/ -v # 1,317 tests
```

## Attribution
Expand Down
2 changes: 1 addition & 1 deletion cli/commands/mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ def mcp_serve(
raise typer.Exit(1)

server = create_mcp_server()
typer.echo(f"Starting MCP server (transport={transport}) ...")
typer.echo(f"Starting MCP server (transport={transport}) ...", err=True)
server.run(transport=transport)
2 changes: 1 addition & 1 deletion cli/commands/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def run_cmd(
),
model: Optional[str] = typer.Option(
None, "--model",
help="LLM model override for claude_agent strategy",
help="LLM model override for ai_agent strategy",
),
):
"""Start autonomous trading with a strategy."""
Expand Down
14 changes: 10 additions & 4 deletions cli/commands/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,17 @@ def setup_check():
else:
ok_items.append("Builder fee: not configured (optional)")

# 5. LLM key (for claude_agent)
if os.environ.get("ANTHROPIC_API_KEY") or os.environ.get("GEMINI_API_KEY"):
ok_items.append("LLM API key found")
# 5. Hosted LLM key (only needed for the subscription-gated ai_agent product path)
if (
os.environ.get("OPENROUTER_API_KEY")
or os.environ.get("AI_API_KEY")
or os.environ.get("ANTHROPIC_API_KEY")
or os.environ.get("GEMINI_API_KEY")
or os.environ.get("OPENAI_API_KEY")
):
ok_items.append("Hosted LLM API key found")
else:
ok_items.append("LLM API key: not set (only needed for claude_agent strategy)")
ok_items.append("Hosted LLM API key: not set (only needed for ai_agent)")

# 6. Data directories
data_dir = Path("data/cli")
Expand Down
47 changes: 32 additions & 15 deletions cli/mcp_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

Fast tools (account, strategies, builder, wallet, setup) call Python directly.
Long-running tools (run_strategy, apex_run, radar, reflect) use subprocess.

Hosted MCP is the bring-your-own-agent path: a user's MCP-capable agent calls
these tools, while web-auth handles wallet selection, consent, and scoped access.
The OpenRouter-backed ai_agent strategy belongs to the separate hosted-agent
product and is not required for generic MCP use.
"""
from __future__ import annotations

Expand Down Expand Up @@ -38,10 +43,12 @@ def create_mcp_server():
from mcp.server.fastmcp import FastMCP

mcp = FastMCP(
"yex-trader",
"nunchi-trading",
instructions=(
"Autonomous Hyperliquid trading CLI — 18 strategies, APEX orchestrator, "
"REFLECT reviews, and BTCSWP funding hedge proposals."
"Nunchi trading tools for MCP-capable agents. Bring your own agent; "
"web-auth selects the wallet and grants scoped tool access. Tools call "
"agent-cli for Hyperliquid/YEX trading, APEX orchestration, REFLECT "
"reviews, and BTCSWP funding hedge proposals."
),
)

Expand All @@ -51,7 +58,12 @@ def create_mcp_server():

@mcp.tool()
def strategies() -> str:
"""List all available trading strategies with descriptions and default parameters."""
"""List available agent-cli strategies.

Generic MCP clients can use any deterministic strategy directly. The
ai_agent strategy is the Nunchi-hosted LLM agent product path and may
require hosted-agent subscription/provider configuration.
"""
from cli.strategy_registry import STRATEGY_REGISTRY, YEX_MARKETS

result = {"strategies": {}, "yex_markets": {}}
Expand Down Expand Up @@ -124,7 +136,7 @@ def wallet_auto(save_env: bool = True) -> str:

@mcp.tool()
def setup_check() -> str:
"""Validate environment — SDK, keys, network, builder fee."""
"""Validate environment, web-auth pairing, network, and builder fee."""
import os
from cli.keystore import list_keystores
from cli.config import TradingConfig
Expand All @@ -145,20 +157,21 @@ def setup_check() -> str:
keystores = list_keystores()
from cli.web_auth import get_stored_pairing
pairing = get_stored_pairing()
if has_env_key:
if pairing is not None:
ok_items.append(f"Web-auth wallet selected ({pairing.selected_or_master_address})")
elif has_env_key:
ok_items.append("HL_PRIVATE_KEY set")
if pairing is None:
warnings.append(
"Raw-key mode active. Prefer hl pair connect or hosted Nunchi Auth for MCP/agent use."
)
warnings.append(
"Raw-key mode active. Prefer hl pair connect or hosted Nunchi Auth for MCP/agent use."
)
elif keystores:
ok_items.append(f"Keystore found ({len(keystores)} keys)")
else:
issues.append("No private key: set HL_PRIVATE_KEY or run wallet_auto")
if pairing is not None:
ok_items.append(f"Paired wallet active ({pairing.selected_or_master_address})")
else:
warnings.append("No paired wallet found. Run hl pair connect to enable browser-approved signing.")
if pairing is None:
warnings.append(
"No web-auth wallet selected. Run hl pair connect, or complete the hosted MCP connect flow."
)

# Network
testnet = os.environ.get("HL_TESTNET", "true").lower()
Expand All @@ -176,12 +189,16 @@ def setup_check() -> str:
"ok": ok_items,
"warnings": warnings,
"issues": issues,
"web_auth": {
"paired": pairing is not None,
"selected_wallet": pairing.selected_or_master_address if pairing is not None else None,
},
"passed": len(issues) == 0,
}, indent=2)

@mcp.tool()
def pair_status() -> str:
"""Show web-auth paired wallet status."""
"""Show the web-auth paired wallet selected for MCP tool calls."""
return _run_hl("pair", "status")

@mcp.tool()
Expand Down
7 changes: 4 additions & 3 deletions cli/skill.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ hl apex run --mainnet # APEX multi-slot
| `HL_TESTNET` | No | `true` (default) or `false` for mainnet |
| `BUILDER_ADDRESS` | No | Override builder fee address (default: hardcoded) |
| `BUILDER_FEE_TENTHS_BPS` | No | Override fee rate (default: 100 = 10 bps) |
| `ANTHROPIC_API_KEY` | No | For `claude_agent` strategy |
| `GEMINI_API_KEY` | No | For `claude_agent` with Gemini |
| `OPENROUTER_API_KEY` | No | For hosted `ai_agent` through OpenRouter |
| `ANTHROPIC_API_KEY` | No | For `ai_agent` with Claude |
| `GEMINI_API_KEY` | No | For `ai_agent` with Gemini |

\* Either `HL_PRIVATE_KEY` or a keystore with `HL_KEYSTORE_PASSWORD` is required.

Expand Down Expand Up @@ -205,7 +206,7 @@ Tools: `strategies`, `builder_status`, `wallet_list`, `wallet_auto`, `setup_chec
| aggressive_taker | Taker | Directional spread crossing with bias |
| hedge_agent | Risk | Inventory exposure reducer; BTCSWP funding hedge lives under `hl hedge` |
| rfq_agent | RFQ | Block-size dark RFQ liquidity |
| claude_agent | LLM | Claude/Gemini-powered autonomous trading agent |
| ai_agent | LLM | Hosted multi-provider autonomous trading agent |

## Instruments

Expand Down
Loading