Personal AI trader. SmartCell is the control plane for autonomous crypto trading — it connects to exchanges, ingests signals from pluggable providers, and executes multi-entry positions with take-profit ladders, stop-loss automation, and full audit history.
The long-term goal: a self-contained trading node that runs on a Raspberry Pi. No cloud dependency, no subscription, no black box. Plug it into any supported exchange, load a signal provider or use the built-in AI strategy, pick your pairs and concurrent-trade limit, and let it run while you check the portfolio from time to time.
┌──────────────────────────────────────────────────────┐
│ SmartCell │
│ │
│ ┌────────────┐ ┌─────────────────────────────┐ │
│ │ Web UI │ │ REST API (Node.js/Express) │ │
│ │ React/Vite │──▶│ Risk engine · Position mgr │ │
│ └────────────┘ │ TP/SL monitor · Audit log │ │
│ └──────────────┬──────────────┘ │
└───────────────────────────────────┼──────────────────┘
│
┌─────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Signal Providers │ │ Exchanges │ │ Database │
│ │ │ │ │ │
│ • Freqtrade (AI) │ │ • Bitvavo ✓ │ │ MongoDB Atlas │
│ • Custom webhook │ │ • More later │ │ (or local) │
│ • Telegram │ │ │ │ │
│ • AI engine (→) │ │ │ │ │
└──────────────────┘ └──────────────────┘ └──────────────────┘Signal providers are loosely coupled — any service that POSTs to /api/providers/{name}/webhook can drive positions. Freqtrade is the built-in AI strategy provider; the interface is open to any other source.
The goal is a single-board device you can configure and forget:
- Hardware: Raspberry Pi + LCD screen + battery pack
- Software: SmartCell (this repo) + optional signal provider, deployed via Docker Compose
- User flow: connect exchange API keys → pick pairs → set concurrent-trade limit → choose signal source (built-in AI or custom strategy) → monitor portfolio on the LCD panel
- Safety: dry-run by default, hard kill-switch for live execution, per-position risk checks that no signal source can bypass
This is a personal trading node, not a SaaS product. One owner, one device, full control.
Bitvavo spot trading with Freqtrade as the signal provider, running as a paper-trade dry run. All features below are working in dry-run; live execution requires explicit opt-in.
Plan a position before touching the exchange. SmartCell stores your full trade plan — entries, take-profit targets, stop-loss — and executes it automatically once you start it.
- Multi-entry ladders — up to N limit or market entry orders per position, each with its own price and size.
- Take-profit ladder — define up to N TP targets with a price and a size percentage. Each TP is submitted as a limit sell automatically when entries fill.
- Stop-loss automation — set a stop price; the monitor fires a market sell of your entire filled position when price reaches it, cancels all pending TPs, and marks the position stopped.
- Partial fill accounting — average entry price and filled base amount update per fill. Unrealized P&L is live on every open position.
- Position lifecycle — planned → entering → open → reducing → closed / stopped.
- Start — submit all planned entry orders to the exchange.
- Edit — update take-profit targets, stop-loss price, or notes on a live position.
- Cancel a pending entry — remove a single unfilled limit order while keeping the rest running.
- Reprice an entry — change the limit price of an unfilled order in-flight.
- Close (partial or full) — sell any percentage (1–100 %) of your filled position as a market order.
- Reconcile — link real exchange fill amounts back to SmartCell entries after a crash or desync.
- Freqtrade — built-in AI strategy (
providers/freqtrade/SmartSellBridge.py). Multi-timeframe consensus (5m + 15m + 1h filter), configurable vote threshold. Sendsplanned_positionandclose_positionwebhooks to SmartCell. - Generic webhook — any service can POST a
trade_intentorplanned_positionpayload to the provider endpoint. - Telegram — ingest raw Telegram signals for manual review before conversion.
- Allowed markets list — editable from Settings, syncs to Freqtrade whitelist automatically.
- Max concurrent Freqtrade positions — configurable cap with live count in Settings.
- Max quote exposure per position (EUR) — hard risk limit.
- Require-dry-run flag — forces simulation until explicitly disabled.
- Global execution mode toggle (dry-run ↔ live) with confirmation gate.
All routes are under http://localhost:4100/api.
| Method | Path | What it does |
|---|---|---|
GET |
/positions |
List all positions |
POST |
/positions |
Create a new planned position |
GET |
/positions/:id |
Get a single position |
PATCH |
/positions/:id |
Update position (planned: full edit; entering: entries locked; open/reducing: TP/SL/notes only) |
DELETE |
/positions/:id |
Soft-delete a position |
POST |
/positions/:id/start |
Submit entry orders to exchange |
POST |
/positions/:id/reconcile |
Link exchange fills back to entries |
POST |
/positions/:id/sync |
On-demand TP/SL cycle + fill sync |
POST |
/positions/:id/close |
Partial or full market close (sizePercentage 1–100) |
GET |
/positions/:id/exchange-snapshot |
Exchange order/trade join with mismatch flags |
POST |
/positions/:id/entries/:index/cancel |
Cancel a single unfilled entry order |
PATCH |
/positions/:id/entries/:index |
Reprice a single unfilled entry order |
| Method | Path | What it does |
|---|---|---|
GET |
/trade-intents |
Paginated list of order requests (limit, offset) |
POST |
/trade-intents |
Submit a new order request through risk + execution |
| Method | Path | What it does |
|---|---|---|
GET |
/signals |
List recent signals (?source=freqtrade filters by source) |
POST |
/signals/telegram |
Ingest a raw Telegram signal for manual review |
POST |
/signals/webhook |
Ingest a structured webhook signal and convert safely |
| Method | Path | What it does |
|---|---|---|
GET |
/providers/freqtrade/status |
Freqtrade REST reachability + SmartCell QA hints (webhook secret, pairs) |
POST |
/providers/freqtrade/webhook |
Authenticated Freqtrade ingest: trade_intent or full planned_position |
| Method | Path | What it does |
|---|---|---|
GET |
/bitvavo/account |
Connection status + non-zero wallet balances |
GET |
/bitvavo/open-orders |
All resting orders on the exchange |
GET |
/bitvavo/orders |
Order history for a market |
GET |
/bitvavo/trades |
Fill/trade history for a market |
DELETE |
/bitvavo/orders |
Bulk cancel all open orders for a market |
POST |
/bitvavo/cancel-orders-after |
Refresh cancel-on-disconnect countdown |
| Method | Path | What it does |
|---|---|---|
GET |
/health |
API liveness check |
GET |
/bot/status |
Execution mode, exchange adapter state, risk config, FT cap info |
GET |
/settings |
Read current settings |
PATCH |
/settings |
Update execution mode, risk rules, allowed markets, toggles |
| Layer | Tech |
|---|---|
| Frontend | React, Vite, TypeScript, SCSS modules |
| State / data fetching | Redux Toolkit, RTK Query |
| Backend | Node.js, Express, TypeScript |
| Database | MongoDB, Mongoose, Zod |
| Tests | Vitest |
| Monorepo | pnpm workspaces |
| Signal provider | Freqtrade (Python, Docker) |
corepack pnpm installcp .env.example apps/api/.envEdit apps/api/.env and set MONGO_URI to your MongoDB Atlas connection string. Or start a local replica-set via Docker:
docker compose up -d mongodbFreqtrade paper-trade QA: follow docs/freqtrade-paper-trade-bootstrap.md then docs/freqtrade-paper-trade-runbook.md. The Freqtrade strategy lives at providers/freqtrade/SmartSellBridge.py.
corepack pnpm devWeb app: http://localhost:5173 · API: http://localhost:4100
corepack pnpm dev # API + web in watch mode
corepack pnpm paper-trade:preflight # API Vitest suite (before smoke / CI)
corepack pnpm paper-trade:smoke # webhook smoke test
corepack pnpm build # production build
corepack pnpm typecheck # TypeScript across all packages
corepack pnpm test # Vitest (shared + api + web)
corepack pnpm lint # ESLint
corepack pnpm staging-preflight # typecheck + lint + format:check
corepack pnpm storybook # UI kit at http://localhost:6006- Default execution mode is dry-run. No exchange credentials needed to explore the app.
- The browser never calls the exchange directly. All exchange interaction goes through the SmartCell API.
- Every order request passes deterministic risk checks before any execution adapter sees it. Signal providers cannot bypass them.
- Live execution requires explicit opt-in via the Settings execution mode switch.
ALLOW_PROVIDER_LIVE=falsehard-blocks provider-originated live orders even if execution mode is live.
| Document | Purpose |
|---|---|
docs/roadmap.md |
Feature roadmap |
providers/freqtrade/README.md |
Freqtrade signal provider setup and strategy reference |
docs/bitvavo-integration-notes.md |
Bitvavo API integration constraints |
docs/freqtrade-paper-trade-bootstrap.md |
Ordered setup steps for Freqtrade paper-trade QA |
docs/freqtrade-paper-trade-runbook.md |
Paper-only QA checklist and safety gates |
docs/freqtrade-reference-fast-qa-config.md |
Reference Freqtrade config.json for 5m QA loops |
docs/docker-and-config-source-of-truth.md |
Docker vs .env.example vs apps/api/.env |
docs/release-workflow.md |
Branch promotion and release process |
docs/i18n-crowdin.md |
i18n setup and Crowdin workflow |
CHANGELOG.md |
Release history |