Star 历史趋势
数据来源: GitHub API · 生成自 Stargazers.cn
README.md

OpenWhale

The programmable layer for composable, AI-native economic strategies

License TypeScript Node

中文说明 →

OpenWhale is a TypeScript framework for automated trading strategies. Monitors collect, Strategies decide, Executors act; the three are decoupled, so one strategy runs on any venue and against any data source, and can be written, audited and evolved by an AI.


Quick start

Development mode with hot reload. For a server see DEPLOYMENT.md.

Prerequisites: Node.js ≥ 20, pnpm ≥ 9 (npm i -g pnpm), git.

1. Clone and install

git clone https://github.com/OpenWhale-Org/OpenWhale.git
cd OpenWhale
pnpm install

2. Configure

cp .env.example .env

Edit .env — three variables are required on first boot:

OPENWHALE_MASTER_KEY=<random secret>     # encrypts stored credentials; generate with: openssl rand -hex 32
OPENWHALE_ADMIN_USER=admin               # first dashboard account
OPENWHALE_ADMIN_PASSWORD=<password>

The master key cannot be recovered — losing it means re-entering every API key. The admin variables create the first user; remove them after signing in. Everything else in .env.example is optional (ports, venue proxy, allowed origins).

3. Build and start

pnpm build
pnpm dev          # gateway on :3001, dashboard on :3000, both with hot reload

pnpm dev:gateway / pnpm dev:dashboard start one side only.

4. Sign in

Open http://localhost:3000 and sign in with the admin user. The dashboard offers a guided tour on first visit: a credential on the Hyperliquid testnet, an account, a copy-trading instance — no real funds.

5. Trade

Credentials → Accounts → Strategies → New strategy. A strategy instance binds params to accounts; activate it and follow it on Instances (live events, executions, runs, PnL).

Docker instead of steps 1–3:

cp .env.example .env         # same three variables
docker compose up -d --build

State lives in the openwhale-data volume; details in DEPLOYMENT.md.

The gateway holds the runtime and all secrets; the dashboard is a frontend that proxies /api/* to it (OPENWHALE_GATEWAY_URL, default http://localhost:3001).

Venue proxy

OPENWHALE_HTTPS_PROXY=http://127.0.0.1:7897        # REST + WebSocket, every venue
OPENWHALE_HTTPS_PROXY_BINANCEUSDM=off              # per venue: ccxt id upper-cased; `off` = direct

HTTPS_PROXY and NODE_USE_ENV_PROXY are not honoured — ccxt uses its own fetch. The variable is namespaced so that order traffic never changes route through an unrelated proxy setting.

Authentication

Enforced by the gateway: every /api/* route requires a session; the dashboard only carries the cookie. Sessions are opaque SQLite tokens (7-day expiry, revocable); passwords are scrypt-hashed; there are no roles. Before exposing the gateway: terminate TLS in front of it (the session cookie is Secure), keep port 3001 off the public internet, set OPENWHALE_ALLOWED_ORIGIN only for cross-origin frontends. Details in DEPLOYMENT.md.


Why OpenWhale

  • Decoupled layers — Monitor → Strategy → Executor. Replace any layer without touching the others.
  • Venue-agnostic — strategies declare account slots; the venue is resolved from the bound account at activation.
  • Adapter matrix — venues are cells of a (kind × venue) matrix (exchange/perp × binance, …). Domain packages define kinds, venue packages fill cells; a data-driven ccxt roster ships twelve venues.
  • AI as a programmer — structured-output LLM inference inside strategies, and a skills/openwhale-dev skill that teaches Claude the framework contract.
  • Run tracing — every run persists what it saw, which gate refused, what it emitted. Survives restarts.
  • PnL attribution — executors claim the orders they place; fills, fees and funding are joined back to the instance. Two instances on one account stay separable.
  • Type-safe plugins — every component implements a strict TypeScript interface.

Core concepts

ConceptDefinition
MonitorCollects data and emits keyed records (venue:symbol). A contract with one or more implementations; users create per-key instances. Emits persist as JSONL and drive triggers.
StrategyPure decision logic. Declares monitor / executor / account dependencies by label, receives triggers, returns ExecutionInstruction[]. Params: base (required) and tunable (defaulted) zod schemas.
ExecutorTurns instructions into venue actions through adapter sessions — retries, idempotent client order ids, latency and slippage capture. Credential slots resolve to sessions (by kind) or raw credential data (raw: true); optional: true slots may stay unbound.
InstanceStrategy + params + account bindings, activated as a unit. Live events, executions, runs and logs hang off it.
AccountA named binding of a credential to an account implementation (generic or venue-specialized). Strategies read balances and positions through it.
TriggerCron schedules and monitor conditions (multi-source AND within a window). Subscriptions keep monitors collecting without waking the strategy; addMonitorSource adds sources discovered at runtime.
Portfolio journalOptional instance-scoped history: idempotent snapshots, fills, decisions, market bars. Core stores them and derives equity, drawdown and trade reports.
Monitor ──emit(key, data)──▶ TriggerManager ──StrategyContext──▶ Strategy ──ExecutionInstruction[]──▶ ExecutionQueue ──▶ Executor
                                                                     └─ run trace persisted

Dashboard

PageFunction
InstancesCards with folders, drag ordering, live net-PnL badge; per-instance Live Events, Executions, Runs, Logs; Board view with parameter editing, account rebinding, PnL panel.
PnLRealized / fees / funding / net / unrealized from the attribution ledger; by-symbol, raw fills, open positions at venue mark. Funding is split across instances by position at settlement.
RunsEvery run's gates, skips, sizing, instructions and log lines. Runs with instructions or errors persist; idle runs are sampled.
Monitor boardsPanels declared by plots(): line, bar, candles, sortable table; single/multi-select keys.
ParamsForms generated from zod .meta(): sections, sliders, units, conditional fields, market pickers, availability checks, list (row-table) params, live interactive illustrations.
ScriptsPlugin-shipped operator utilities run on demand against the runtime; monospace report, optional JSON and file attachments.
Compiler / AssistantNatural-language strategy compiler (experimental). Recommended path: Claude with skills/openwhale-dev.

Code examples

A minimal strategy

const decls = {
  monitors: [{ name: 'exchange/ticker', label: 'price' }],
  executors: [{ name: 'exchange/perp-trading', label: 'perp' }],
  accounts: [{ account: PerpAccount, label: 'main' }],
} as const satisfies StrategyDeclarations

class MomentumStrategy extends BaseStrategy<typeof decls> {
  readonly strategyId = 'momentum'
  override readonly monitors = decls.monitors
  override readonly executors = decls.executors
  override readonly accounts = decls.accounts

  readonly baseParamsSchema = z.object({
    symbol: z.string().meta({ displayName: 'Symbol' }),
    threshold: z.number().meta({ displayName: 'Entry price' }),
  })

  async evaluate(context: StrategyContext) {
    const { symbol, threshold } = this.baseParamsSchema.parse(this.params.base)
    const tick = context.getData('price', `${this.accountVenue('main')}:${symbol}`)
    this.trace('tick:read', { tick })                    // recorded in the run trace
    if (!tick || tick.price < threshold) return []

    return [
      this.instruction('perp', 'placeOrder', {
        symbol, side: 'buy', type: 'market', amount: 0.01,
      }),
    ]
  }
}

Assembling the runtime

const runtime = new OpenWhaleRuntime({ database, credentialStore })
runtime.loadPlugin(binancePlugin, {})
runtime.loadPlugin(hyperliquidPlugin, {})
await runtime.start()
await runtime.activate({
  strategyId: 'my-plugin/momentum',
  credentials: { main: 'My Binance' },       // the account binding decides the venue
  params: { base: { symbol: 'BTC/USDT:USDT', threshold: 60000 } },
})

AI-driven strategy with structured output

async evaluate(context: StrategyContext) {
  const data = await this.monitorData('market')?.readLatest(this.accountVenue('main'))

  const { action, confidence } = await this.llm({
    messages: [{ role: 'user', content: JSON.stringify(data) }],
    schema: z.object({
      action: z.enum(['buy', 'sell', 'hold']),
      confidence: z.number(),
    }),
  })
  if (action === 'hold' || confidence < 0.7) return []

  return [
    this.instruction('perp', 'placeOrder', {
      symbol: 'BTC/USDC:USDC', side: action, type: 'market', amount: 0.01,
    }),
  ]
}

An operator script

export const planPreview: ScriptDefinition = {
  id: 'plan-preview',
  name: 'Plan preview',
  paramsSchema: z.object({ instance: z.string().default('') }),
  paramOptions: async (runtime) => ({ instance: await listMyInstances(runtime) }),
  run: async ({ params, runtime }) => ({ text: await renderPlan(runtime, params) }),
}

Plugins

A plugin is a package whose default export is a factory returning its registrations:

export default definePlugin((ctx) => ({
  name: 'my-plugin',
  version: '1.0.0',
  monitorImplementations: [ /* contract / implementation / instance */ ],
  executors: [ /* … */ ],
  strategies: [ /* … */ ],
  scripts: [ /* operator utilities */ ],
  credentialTypes: [ /* schema, raw opt-in, connectivity test */ ],
  adapters: [ /* (kind × venue) cells */ ],
  accounts: [ /* account implementations */ ],
}))

Install from the Plugins page — npm name, GitHub owner/repo (optional ref), local path, or a built .js/.mjs bundle — or runtime.loadPlugin() in code. A GitHub install is built by npm, so a source-only repo needs a prepare script; private repos need OPENWHALE_GITHUB_TOKEN.

Rules:

  • The plugin name is its namespace (my-plugin/momentum). A taken name gets a new namespace at install (alice-funding-arb); a namespace is fixed once instances reference it.
  • Adapter cells and credential types are global: two plugins providing the same venue cannot coexist. Registration is all-or-nothing.
  • Overwrite keeps instances, accounts and credentials; instances whose strategy the new version dropped are marked broken, not deleted.
  • npm installs show a newer registry version in the rail and update in one click (same overwrite path).
  • Uninstall is refused while an instance, account or credential references the plugin; the plugin's monitor instances are deleted with it.
  • Each install loads from its own copy under plugins/staged/, so reinstalling needs no restart.

Writing plugins with Claude

Copy skills/openwhale-dev/ into your plugin project's .claude/skills/ (or reference this repo's path), describe the strategy, and Claude produces a complete plugin package — monitors, executors, strategies, tests — installable from the Plugins page.


Use cases

CategoryShape
Funding / basis arbitragePerp vs spot or perp vs perp, timed around settlement, hedged
Cross-venue arbitrageThe same instrument on two venues, two accounts, one strategy
Market makingTwo-sided quotes managed against inventory and volatility; includes incentive-band quoting on DEXs
Statistical arbitrage / pairsSpread or z-score monitors driving hedged multi-leg positions
Trend following / mean reversionIndicator-driven directional strategies on any market
Grid / DCAScheduled or level-triggered accumulation and distribution
Copy tradingMirror a target account or wallet with proportional sizing and caps
On-chain yieldWallet-keyed accounts on lending, LP, and yield-tokenization protocols
On-chain arbitrageDEX-to-DEX and DEX-to-CEX price gaps, executed from wallet accounts
Airdrop farmingScheduled protocol interactions across many wallets, each an account
Launch sniping / new listingsMonitor listings and token launches, enter on the event with size caps
Meme tradingFast on-chain momentum with hard stops and position limits
News / social signalsMonitors over news feeds and social posts (X, Telegram), LLM-classified, traded with limits
AI-driven signalsStructured-output LLM inference as one input among the others, risk limits in code

Packages

framework/ engine and domains · venues/ exchange integrations · apps/ gateway and dashboard · strategies/ reference plugins.

PackageRole
@openwhaleorg/coreEngine: adapter matrix, accounts, monitor model, strategy/executor/trigger, run traces, PnL attribution, scripts, definePlugin and decorators
@openwhaleorg/exchangeKinds exchange/perp and exchange/spot: account views, trading executors, market monitors
@openwhaleorg/web3Kind web3/chain: EVM session, wallet account, web3/evm and web3/rpc credential types
@openwhaleorg/ccxt-adapterccxt implementation of the exchange adapters and the data-driven venue roster
@openwhaleorg/hyperliquid / binance / asterVenue plugins: credential types, adapter cells, venue-specialized accounts
@openwhaleorg/gatewayBackend: runtime, auth, REST + SSE API, compiler service, plugin install
@openwhaleorg/dashboardNext.js frontend
@openwhaleorg/examplesReference strategies: momentum, mean reversion, DCA, LLM analyst, copy trading
@openwhaleorg/compilerNL → code → validation ladder → review → hot load

Release check: pnpm check:publish packs every package and verifies the peer ranges inside the tarballs (workspace:^ is resolved at pack time and appears nowhere in the repo).


Contributing

Issues for ideas and bugs; PRs for fixes, venue plugins and strategy examples.

License

MIT

关于 About

A framework for AI-driven economic activity. Declarative, composable, observable, deterministic.
ai-agentcryptostrategytrading

语言 Languages

TypeScript97.3%
CSS2.1%
Shell0.3%
JavaScript0.2%
Dockerfile0.1%

提交活跃度 Commit Activity

代码提交热力图
过去 52 周的开发活跃度
271
Total Commits
峰值: 98次/周
Less
More

核心贡献者 Contributors