Skip to content

dex-original/ai-trading-agent

Repository files navigation

AI Trading Agent

Repository (clone / issues / PRs): github.com/dex-original/ai-trading-agent

Keywords: trading-bot ai-trading openrouter lighter lighter-xyz perpetuals llm llm-agent tool-calling prisma postgresql bun typescript express react vite vercel-ai-sdk crypto bitcoin ethereum altcoin algorithmic-trading automated-trading quant quantitative fintech audit telemetry positions risk open-source defi research crypto-bot autonomous-agent streaming llm openapi portfolio dashboard invocations-timeseries prisma-studio cors rest-api javascript esm bun-runtime

Disclaimer: Automated trading carries significant financial risk. This software is provided for educational and experimental use. You are solely responsible for API keys, position sizing, capital at risk, and compliance with laws in your jurisdiction. Never trade funds you cannot afford to lose.


Table of contents

  1. Why this project is useful
  2. What you get
  3. Prerequisites
  4. Quick start
  5. How a single cycle works
  6. Database models and tool types
  7. Important: position side handling
  8. Optional dashboard API and UI
  9. Project layout
  10. Tech stack
  11. Troubleshooting
  12. Useful tips
  13. License

Why this project is useful

This agent is useful when you want a repeatable, observable loop between market data, an LLM, and a small set of exchange actions—without building that plumbing from scratch every time.

What it helps with Why that matters
Prompt + data assembly Each run merges candlestick-derived signals (intraday and longer horizon), balances, positions, and invocation count into one prompt (prompt.ts). You reuse the pipeline and only tune strategy text or markets.
Multi-model experimentation Add rows under Models with different openRoutermodelName strings to compare models on similar conditions, or route multiple Lighter accounts from one process, without duplicating the runner.
Auditing and review Responses and tool usage land in PostgreSQL (Invocations, ToolCalls), which is useful for debugging behavior, measuring how often the model opens vs. flattens, and tracing what was decided when.
Guardrailed automation The model does not get arbitrary API access—it only invokes the trading tools wired in code, which is useful for limiting blast radius compared to unrestricted agents.
Hands-off scheduling A fixed cadence (every 5 minutes after start) removes the need to manually trigger runs when you already trust your prompt and sizing rules.

Useful for: researchers comparing LLMs on trading prompts, builders prototyping Lighter + OpenRouter flows, and operators who want logs and database-backed history alongside automation.

Where this applies more widely

The implementation here targets Lighter and OpenRouter, but the shape of the project is easy to reuse in many environments:

Context How it extends
Other exchanges & venues The same loop—scheduled run → enriched prompt → constrained tools → persisted audit—maps to perpetuals, spots, or simulated/mock adapters if you swap the exchange layer (createPosition, cancelOrder, market data fetchers) for your APIs.
Education & labs Universities and coding bootcamps use this style of repo to teach tool-calling, risk disclosure, and observable agents without students wiring raw websocket trading from day one.
Product & fintech prototyping Teams can demo “AI-assisted execution” internally: keep PostgreSQL telemetry and prompts, stub orders in staging or paper flows, then harden gateway rules before any real capital.
LLM evaluation & research Any provider reachable through OpenRouter (or by substituting the AI SDK provider) lets you compare models on the same indicator snapshot and record outcomes in one database.
Compliance-minded workflows Immutable-style logs of model output + tool calls support post-hoc review—useful in regulated or internal-trading settings where you must show what the system did and when.
Home labs & VPS A small self-hosted Bun process fits low-cost servers or Raspberry Pi-class boxes for experimentation, monitoring, or personal alerting (with firewall and secret hygiene).

Across these cases, wide reuse comes from separating strategy text (prompt.ts), data assembly, narrow tools, and storage—you can transplant that split into quant stacks, alerting bots, or research harnesses beyond crypto.


What you get

Capability Summary
Multi-model orchestration Each row in Models drives its own scheduler pass with a distinct OpenRouter model name and Lighter credentials.
Rich context each run 5‑minute and 4‑hour signals (mid price, EMA20, MACD), open positions, and portfolio totals are injected into the prompt.
Auditable actions Invocations and tool calls (createPosition, closeAllPosition-style closes) are stored for review.
Periodic execution The agent cycle runs automatically every 5 minutes once started.

Prerequisites

  • Bun ≥ 1.x (recommended: match the version you use elsewhere in your stack).
  • PostgreSQL database reachable from your machine or server.
  • OpenRouter API key for the models you intend to call.
  • Lighter API key (and associated accountIndex) for each automated account configured in Models.

Quick start

1. Install dependencies

bun install

2. Configure environment

Create an environment file (for example .env) in this directory with at minimum:

Variable Required Purpose
DATABASE_URL Yes PostgreSQL connection string used by Prisma.
OPENROUTER_API_KEY Yes Authenticates requests to OpenRouter from the AI SDK provider.

3. Prepare the database

Generate the Prisma client and apply migrations (from this directory):

bunx prisma migrate deploy

Or during development:

bunx prisma migrate dev

4. Define trading profiles

Populate the Models table with one row per logical trader: each needs a unique name, OpenRouter routing string (openRoutermodelName), lighterApiKey, and accountIndex. Empty state means nothing runs—you must insert at least one valid record via your preferred SQL GUI, script, or Prisma Studio (bunx prisma studio) before expecting activity.

5. Run the agent

bun run index.ts

On startup and every five minutes afterward, the process loads every Models row and invokes invokeAgent for each. Logs include the enriched prompt body for observability—ensure logging does not violate your confidentiality policy in production environments.

Commands summary

Goal Command
Install deps bun install
Apply DB migrations bunx prisma migrate deploy (or migrate dev)
Generate Prisma client only bunx prisma generate
Browse DB bunx prisma studio
Run agent loop only bun run index.ts
Run HTTP dashboard API bun run backend.ts (needs same DATABASE_URL; port 3000)
Run frontend UI cd frontend && npm install && npm run dev

How a single cycle works

  1. Indicators — For each configured market (e.g. SOL, ZEC, HYPE), the agent fetches short- and medium-term candles and summarizes mid prices, EMA20, and MACD.
  2. State — It pulls portfolio value, available balance, and open positions tied to the Lighter credentials for that model.
  3. LLM turn — A trading prompt (prompt.ts) is filled with placeholders and sent to OpenRouter streaming through the AI SDK (streamText).
  4. Tools — If the model calls tools, executions are persisted under Invocations and ToolCalls, and invocation counts update on the corresponding Models row.

Strategy text and risk rules are defined in prompt.ts; adjust them there if you change markets or risk appetite.


Database models and tool types

Prisma schema: prisma/schema.prisma; client output: generated/prisma.

Model Purpose
Models One row per automated profile: name (unique), openRoutermodelName (OpenRouter model id), lighterApiKey, accountIndex, invocationCount.
Invocations One row per agent run: response (final model text after streaming completes), timestamps.
ToolCalls Rows linked to an invocation: toolCallType + JSON metadata.
PortfolioSize Time series of netPortfolio strings per model (used by the optional /performance API).

ToolCallType enum values: CREATE_POSITION, CLOSE_POSITION (close-all flow).


Important: position side handling

In index.ts, the createPosition tool handler inverts the model’s requested side relative to the LONG / SHORT enum sent by the LLM (the code comment states this is intentional: the executed side is the opposite of what the model chose). If you fork this repo, audit this line before live use—either remove the inversion or align your prompt so intended economics match execution.


Optional dashboard API and UI

Component How to run (typical) Role
HTTP API bun run backend.ts (from repo root, same env as the agent) Serves JSON on port 3000: GET /performance (cached portfolio history), GET /invocations?limit=N (recent runs with tool calls, limit ≤ 200).
Frontend cd frontend && npm install && npm run dev Vite dev server; point API calls at http://localhost:3000 (or your deployed backend).

The agent loop and the backend are separate processes—run both if you want the UI; run only index.ts if you only need automation and Prisma storage.


Project layout (high level)

Path / area Role
index.ts Entry point: 5-minute setInterval loop and invokeAgent (also runs main() once at startup).
backend.ts Express + CORS: /performance, /invocations.
prompt.ts System prompt template and trading constraints.
markets.ts Symbol → Lighter market metadata.
prisma/schema.prisma Models, Invocations, ToolCalls, PortfolioSize.
stockData.ts, openPositions.ts, createPosition.ts, cancelOrder.ts Market data and exchange-side effects.
frontend/ React dashboard (optional).

Tech stack

  • Runtime: Bun
  • AI: @openrouter/ai-sdk-provider, ai (Vercel AI SDK)
  • Data: Prisma Client (generated under generated/prisma) + PostgreSQL
  • API (optional): Express 5, CORS

Troubleshooting

Symptom What to check
Nothing runs on schedule Models table is empty or migration not applied; verify bunx prisma migrate deploy and at least one valid row.
OpenRouter or DB errors on startup OPENROUTER_API_KEY, DATABASE_URL; Postgres reachable from the host.
Lighter auth / position errors lighterApiKey and accountIndex match the account; markets.ts symbol keys match Lighter.
Backend returns empty invocations Agent must have run at least once; check Prisma Invocations in Studio.
Frontend cannot reach API CORS is enabled on backend.ts; ensure the frontend’s fetch URL matches where Express listens (default 3000).

Useful tips

  • Inspect history — Use bunx prisma studio to browse Invocations and ToolCalls when you need to see past model outputs and which tools actually ran.
  • Tune strategy without redeploying logic — Most behavioral rules live in prompt.ts and markets.ts; adjust copy, markets, or constraints there while keeping the same execution path.
  • Dry-run mindset — Even with logging, treat small account sizes and clear stop rules as essential; the agent is a tool, not a guarantee of profit.

License

License for this repository is unspecified; confirm with the repository owner before redistributing or using in commercial settings.

About

ai trading agent llm trading bot openrouter lighter perpetual crypto automated trading typescript postgresql prisma ai trading agent algorithmic trading crypto bot ai agent quant defi bun express react ai trading agent trading bot crypto automated trading ai trading agent open source streaming ai trading agent llm quant crypto ai trading agent

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages