Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Hummingbot plugin #1570

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
171 changes: 171 additions & 0 deletions packages/plugin-hummingbot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# Hummingbot Plugin for Eliza

A powerful plugin that integrates Hummingbot's market making capabilities with Eliza trading agents. This plugin enables Eliza to perform automated market making and trading operations using Hummingbot's infrastructure.

## Features

- Real-time market data streaming via WebSocket
- Simple market making strategy with configurable parameters
- Inventory skew management
- Order lifecycle management (create, cancel, track)
- Rate limiting and error handling
- Automatic reconnection and recovery
- Multi-level order book support

## Installation

```bash
npm install @eliza/plugin-hummingbot
```

## Usage in Eliza Character

Add the plugin to your character configuration:

```json
{
"plugins": ["@eliza/plugin-hummingbot"],
"settings": {
"HUMMINGBOT_CONFIG": {
"instance": {
"url": "http://localhost:15888",
"wsUrl": "ws://localhost:8060",
"apiKey": "your-hummingbot-api-key",
"instanceId": "eli-agent"
},
"defaultStrategy": {
"exchange": "binance",
"tradingPair": "BTC-USDT",
"orderAmount": 0.001,
"orderLevels": 2,
"maxOrderAge": 1800,
"inventorySkewEnabled": true,
"inventoryTargetBase": 50,
"bidSpread": 0.2,
"askSpread": 0.2,
"minSpread": 0.1,
"maxSpread": 0.5,
"priceSource": "current_market",
"orderRefreshTime": 60
}
}
}
}
```

> **Note:** The `url` and `apiKey` fields in the instance configuration are required. The plugin will throw an error if either of these values is missing or undefined.

## Quick Start

```typescript
import { HummingbotPlugin } from '@eliza/plugin-hummingbot';
import { SimpleMarketMaking } from '@eliza/plugin-hummingbot/strategies';

// Initialize the plugin
const plugin = new HummingbotPlugin({
instance: {
url: 'http://localhost:15888', // Default Hummingbot REST API port
wsUrl: 'ws://localhost:8060', // Default Hummingbot WebSocket port
apiKey: 'your-api-key',
instanceId: 'instance-1'
}
});

// Initialize plugin
await plugin.init();

// Configure market making strategy
const config = {
exchange: "binance",
tradingPair: "BTC-USDT",
orderAmount: 0.001, // Base order size in BTC
orderLevels: 2, // Number of orders on each side
maxOrderAge: 1800, // Maximum order age in seconds
inventorySkewEnabled: true,
inventoryTargetBase: 50, // Target base asset percentage
inventoryRangeMultiplier: 1.5,
bidSpread: 0.2, // 0.2% spread for bids
askSpread: 0.2, // 0.2% spread for asks
minSpread: 0.1, // Minimum allowed spread
maxSpread: 0.5, // Maximum allowed spread
priceSource: 'current_market',
minimumSpreadEnabled: true,
pingPongEnabled: false,
orderRefreshTime: 60 // Refresh orders every 60 seconds
};

// Create and start the strategy
const strategy = new SimpleMarketMaking(plugin, config);
const stopStrategy = await strategy.start();

// Handle shutdown gracefully
process.on('SIGINT', async () => {
console.log('Shutting down strategy...');
await stopStrategy();
process.exit(0);
});
```

## Configuration Guide

### Plugin Configuration

| Parameter | Type | Description | Required |
|-----------|--------|-------------|----------|
| url | string | Hummingbot REST API URL | Yes |
| wsUrl | string | Hummingbot WebSocket URL | Yes |
| apiKey | string | API key for authentication | Yes |
| instanceId| string | Unique identifier for the instance | Yes |

### Market Making Strategy Configuration

| Parameter | Type | Description | Required | Default |
|-----------|------|-------------|----------|---------|
| exchange | string | Exchange to trade on | Yes | - |
| tradingPair | string | Trading pair (e.g., "BTC-USDT") | Yes | - |
| orderAmount | number | Base order size | Yes | - |
| orderLevels | number | Number of orders on each side | No | 1 |
| maxOrderAge | number | Maximum order age in seconds | No | 1800 |
| inventorySkewEnabled | boolean | Enable inventory skew | No | false |
| inventoryTargetBase | number | Target base asset % | No | 50 |
| bidSpread | number | Bid spread percentage | Yes | - |
| askSpread | number | Ask spread percentage | Yes | - |
| minSpread | number | Minimum spread percentage | No | 0.1 |
| maxSpread | number | Maximum spread percentage | No | 0.5 |
| priceSource | string | Price source for orders | No | 'current_market' |
| orderRefreshTime | number | Order refresh interval (seconds) | No | 60 |

## API Reference

### HummingbotPlugin

#### Methods

- `init(): Promise<void>` - Initialize the plugin
- `subscribeToMarketData(exchange: string, symbol: string, callback: (data: MarketData) => void): Promise<() => void>` - Subscribe to market data
- `placeOrder(params: OrderParams): Promise<string>` - Place a new order
- `cancelOrder(exchange: string, orderId: string): Promise<boolean>` - Cancel an order
- `getOrderStatus(exchange: string, orderId: string): Promise<any>` - Get order status

### SimpleMarketMaking Strategy

#### Methods

- `start(): Promise<() => void>` - Start the market making strategy
- `updateBalances(): Promise<void>` - Update portfolio balances
- `cancelAllOrders(): Promise<void>` - Cancel all active orders

## Error Handling

The plugin implements comprehensive error handling:

- Rate limit handling with automatic retries
- WebSocket connection management with automatic reconnection
- Order validation and error reporting
- Balance checking before order placement

## Prerequisites

- Running Hummingbot instance
- Valid API credentials
- Sufficient balance on the target exchange
10 changes: 10 additions & 0 deletions packages/plugin-hummingbot/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
roots: ['<rootDir>/src'],
testMatch: ['**/__tests__/**/*.test.ts'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},
};
41 changes: 41 additions & 0 deletions packages/plugin-hummingbot/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name": "@eliza/plugin-hummingbot",
"version": "0.1.0",
"description": "Hummingbot integration for Eliza trading agents",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
"prepublishOnly": "pnpm run build",
"test": "jest",
"test:watch": "jest --watch"
},
"publishConfig": {
"access": "public"
},
"keywords": [
"eliza",
"plugin",
"hummingbot",
"trading",
"market-making",
"cryptocurrency"
],
"author": "Nethermind",
"license": "MIT",
"dependencies": {
"@ai16z/eliza": "workspace:*",
"axios": "^1.6.0",
"ws": "^8.16.0"
},
"devDependencies": {
"@types/jest": "^29.5.11",
"@types/ws": "^8.5.10",
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"typescript": "^5.0.0"
},
"peerDependencies": {
"@ai16z/eliza": "*"
}
}
25 changes: 25 additions & 0 deletions packages/plugin-hummingbot/src/actions/market-making.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { HummingbotPlugin } from '..';
import { SimpleMarketMaking } from '../strategies/simple-market-making';
import { MarketMakingConfig } from '../types';

export async function startMarketMaking(
plugin: HummingbotPlugin,
config: MarketMakingConfig
): Promise<() => Promise<void>> {
const strategy = new SimpleMarketMaking(plugin, config);
return strategy.start();
}

export async function stopMarketMaking(
plugin: HummingbotPlugin,
strategyId: string
): Promise<void> {
await plugin.stopStrategy(strategyId);
}

export async function getMarketMakingStatus(
plugin: HummingbotPlugin,
strategyId: string
): Promise<any> {
return plugin.getStrategyStatus(strategyId);
}
24 changes: 24 additions & 0 deletions packages/plugin-hummingbot/src/actions/orders.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { HummingbotPlugin } from '..';
import { OrderParams } from '../types';

export async function placeOrder(
plugin: HummingbotPlugin,
params: OrderParams
): Promise<string> {
return plugin.orderService.placeOrder(params);
}

export async function cancelOrder(
plugin: HummingbotPlugin,
exchange: string,
orderId: string
): Promise<boolean> {
return plugin.orderService.cancelOrder(exchange, orderId);
}

export async function cancelAllOrders(
plugin: HummingbotPlugin,
exchange: string
): Promise<void> {
await plugin.orderService.cancelAllOrders(exchange);
}
Loading
Loading