# open-alpha-arena gives language models a crypto paper trading floor

> open-alpha-arena is a TypeScript paper trading environment for crypto markets, inspired by nof1 Alpha Arena, with an OpenAI compatible API so any model client can act on a portfolio. Quotes come from ccxt against Hyperliquid, and real trading is still on the todo list.

**etrobot/open-alpha-arena** — AI paper trading project inspired by nof1 Alpha Arena,  using cctx for quotation.

- Repository: https://github.com/etrobot/open-alpha-arena
- Website: https://finan.club
- Stars: 596 · Forks: 149
- Language: TypeScript
- License: not declared
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/etrobot-open-alpha-arena

## The simulator is the product, and live trading is not in it

open-alpha-arena is a project inspired by nof1 Alpha Arena, and the setup it offers is an AI trading bot on a crypto market. The homepage is finan.club, and the repository is described as an AI paper trading project that uses cctx, in the project description, for quotation.

The status list in the readme is short and worth reading carefully. Done are paper trading, an OpenAI compatible API, ccxt for quotation, and a pure TypeScript stack where the backend was ported from Python and nodejs-polars replaces pandas. Under TODO is real trading, with the note that you can in fact implement it with ccxt with the help of AI coding tools easily.

That last line is a design decision stated plainly. The project is deliberately a simulator with a clean seam where the exchange adapter would go, and the person who wrote it is telling you that the gap to live trading is small enough to close yourself if you want to.

The OpenAI compatible API is what makes the project more than a spreadsheet. It means a model client can drive the trading environment with the same request format it uses for chat, so the interesting experiment, which model manages a portfolio better, can be run without writing an exchange integration for every model you want to test.

## One runtime, one package manager, two processes

The tech stack table is the strongest statement in the readme, because it rules things out as much as it rules them in.

The frontend is React 18 with Vite, Tailwind and shadcn/ui. The backend is Hono with @hono/node-server, serving HTTP and WebSocket. The database is SQLite through Drizzle ORM with better-sqlite3. Validation is Zod. Factor calculations use nodejs-polars, and market data comes from ccxt against Hyperliquid.

The readme describes the whole thing as a pure TypeScript stack, one runtime and one package manager, and the key word there is one. The backend was ported from Python, and pandas was replaced by nodejs-polars rather than by a JavaScript dataframe library, which is an unusual choice to make and the reason the dependency list includes a native module that may need compiling.

The repository layout matches: a backend directory, a frontend directory, a pnpm-workspace.yaml and a pnpm-lock.yaml at the root, plus a Dockerfile and a docker-compose.yml. The root package.json is private and holds only workspace level scripts, delegating the real work to the two packages with pnpm filters.

The root scripts are worth noting because they show the intended workflow.

```json
  "scripts": {
    "dev": "concurrently \"pnpm run dev:backend\" \"pnpm run dev:frontend\"",
    "dev:frontend": "pnpm --filter ./frontend dev",
    "dev:backend": "pnpm --filter ./backend dev",
  },
```

Prerequisites are Node.js 20 or newer and pnpm, and the package manager is pinned to pnpm 8.15.5 with a lockfile hash in the package metadata.

## Two dev servers, one proxied API

The development setup is described in enough detail to be reproduced without guessing.

The install is one command.

```bash
pnpm install
```

And the dev script starts both processes, the backend on port 5611 and the frontend on 5621.

```bash
pnpm run dev
```

The readme gives the URLs to open: the frontend at http://localhost:5621 and the backend WebSocket at ws://localhost:5611/ws. Vite proxies the /api and /ws paths to the backend on 5611, so no extra configuration is needed, and if you want only the backend you can run it on its own with the filter flag.

```bash
pnpm --filter backend dev
```

The build and check commands are grouped together, and the comments in the readme say what each one covers.

```bash
pnpm run build          # frontend (Vite) + backend (tsc)
pnpm run typecheck      # backend type check only
pnpm --filter backend test   # factor regression test vs the pandas baseline
```

That last one is the interesting one. The test suite is described as a factor regression test against the pandas baseline, which is the check that matters for a port: if the original implementation computed a factor in Python with pandas, the TypeScript version with nodejs-polars has to produce the same numbers, and the test asserts that. The compiled backend lands in backend/dist and runs with node dist/index.js, and copying the frontend's dist directory into backend/static makes the backend serve the single page app itself, which is what the Dockerfile does for you.

## Three environment variables configure the whole backend

The configuration table is the entire surface, which tells you the backend is not doing anything clever with its environment.

PORT sets the HTTP and WebSocket port and defaults to 5611. DATABASE_PATH sets the SQLite file location and defaults to backend/data.db. LOG_LEVEL takes debug, info, warning or error and defaults to info.

That is it. No exchange keys appear in the table, which is consistent with the project being a paper trading simulator rather than a bot with exchange credentials, and it means a fresh checkout has no secret to fill in before it will start.

The database itself is SQLite through Drizzle ORM with better-sqlite3, which means the whole state of the arena, portfolios, positions and whatever the agents have done, is a single file on disk. For a paper trading environment that is the right shape, because the state is small, the reads are fast, and you can copy the file to inspect a run or archive it.

The one consequence to keep in mind is that this file is the entire history. There is no database server to back it up, and nothing in the readme describes a retention or export policy, so if you want to keep a record of a run, copying that file is the only mechanism described.

## The compose file is written for a machine with Traefik in front

The Docker section of the readme is one command, and the compose file behind it is short.

```bash
docker compose up --build
```

What that file contains is worth reading before you run it on a laptop.

```yaml
  app:
    build: .
    container_name: usmover
    restart: unless-stopped
    ports:
      - "5611:5611" 
    volumes:
      - ./data:/app/data 
```

The service is named app but the container is called usmover, which appears to be left over from an earlier name for the project, and the compose file is not a generic example: it carries Traefik labels that route the host oaa.finan.club to the container on the 5611 port with a Let's Encrypt certificate resolver, and it joins an external network called traefik that has to exist already.

There is also a mismatch worth verifying. The compose file mounts a host directory at /app/data, while the Dockerfile sets the environment variable DATABASE_PATH to /app/backend/data.db. Unless that variable is overridden in the compose environment, the SQLite file is written under /app/backend, not into the mounted directory, and the volume does nothing for persistence. If you intend to keep data across container restarts, check where the file actually lands.

The Dockerfile itself is a conventional two stage build on node:22-slim, with python3, make and g++ installed because better-sqlite3 and nodejs-polars may need to compile when no prebuilt binary matches the platform. The manifests are copied before the sources so the dependency layer caches, and the final image copies the workspace root node_modules and the backend node_modules together, because pnpm links packages relatively and copying only one of the two would break resolution.

## Where the project stops, and what to use instead

The first limit is the obvious one, and the readme is upfront about it: there is no live trading, and the mechanism that would provide it is not built. The TODO list names real trading and suggests implementing it with ccxt, so a project that needs actual orders should not expect to switch a flag here.

The second limit is the market. The stack table names ccxt with Hyperliquid, and while ccxt supports many exchanges, the readme only documents one, so a different venue means writing and testing the exchange integration yourself, which is the work the project has not done for you.

The third is the model side, and it is softer. The OpenAI compatible API means the arena is usable by any client that speaks that protocol, which is broad, but the readme does not document what the model actually sees, what it is asked to output, or how a strategy is evaluated. Those details are the substance of such an experiment, and the repository as described leaves them to the reader.

The alternative approaches are two. The first is the one the readme itself suggests, which is to keep ccxt and write the live trading layer on top of the simulator, a smaller change than building the arena from nothing. The second is to skip the arena entirely and point a model client at the exchange through ccxt directly, which removes the paper trading constraint but also removes the controlled environment that makes two models comparable. Neither is obviously better; the first keeps the experimental setup, the second keeps the simplicity.

## Conclusion

open-alpha-arena fits a team that wants to evaluate how a language model behaves with a real market, with real positions and real prices, but without real money, and who is willing to wire the same model client they use elsewhere against an OpenAI compatible endpoint. It is the wrong project for placing live trades, since the readme lists real trading as unfinished work, and it is the wrong project if you need a data source other than Hyperliquid without writing the exchange adapter yourself. Check first that the model client you use can talk to the OpenAI compatible API, that the ccxt exchange you need is covered, and that the SQLite file lands on a path that survives a container restart.

## FAQ

### Does open-alpha-arena place real trades?

No. The readme lists paper trading as done and real trading under TODO, adding that you can implement it with ccxt with the help of AI coding tools. The exchange adapter seam is there, the live order path is not.

### Where does open-alpha-arena get market data?

From ccxt, with Hyperliquid named as the market in the tech stack table. The project description says the same, that it uses ccxt for quotation.

### How do I run the open-alpha-arena dev servers?

Run pnpm install, then pnpm run dev. The backend listens on port 5611 and the frontend on 5621, and Vite proxies /api and /ws to the backend so no extra configuration is needed. pnpm --filter backend dev runs the backend on its own.

### Which environment variables does the open-alpha-arena backend read?

Three: PORT, which defaults to 5611, DATABASE_PATH, which defaults to backend/data.db, and LOG_LEVEL, which takes debug, info, warning or error and defaults to info. No exchange credentials are listed.

## Sources

- [etrobot/open-alpha-arena on GitHub](https://github.com/etrobot/open-alpha-arena)
- [Issues](https://github.com/etrobot/open-alpha-arena/issues)
- [Project website](https://finan.club)
- [README](https://github.com/etrobot/open-alpha-arena/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/etrobot-open-alpha-arena
