Every time I built a trading UI, I hit the same wall - real data feeds cost thousands per month.
Free APIs have strict rate limits. And I just wanted to test my UI.
So I built trade-data-generator, an npm library that generates realistic synthetic market data for equity, forex, and crypto.
The Problem
Building a trading UI requires live market data.
Your options are:
- Bloomberg/Refinitiv — $2,000+/month
- Free APIs — rate limited, unreliable
- Hardcoded fake data — not realistic, The charts look broken None of these works well for development and testing.
The Solution
npm install trade-data-generator
Zero dependencies. Zero API keys. Works offline.
How It Works
const { MarketFeed } = require('trade-data-generator')
const feed = new MarketFeed({
type: 'crypto',
pairs: [
{ symbol: 'BTC/USDT', startPrice: 45000,
volatility: 0.004 },
{ symbol: 'ETH/USDT', startPrice: 2800,
volatility: 0.005 },
]
})
feed.on('tick', (data) => console.log(data))
feed.on('candle', (data) => console.log(data))
feed.on('depth', (data) => console.log(data))
feed.start()
What You Get
Every tick emits realistic data:
{
"symbol": "BTC/USDT",
"price": 45016.14,
"bid": 44993.63,
"ask": 45038.65,
"volume": 4,
"changePct": 0.04,
"high24h": 45200.00,
"low24h": 44800.00
}
Price Simulation
The price engine uses three forces:
1. Random walk - Box-Muller normal distribution. Small moves most of the time, occasional spikes. More realistic than
flat Math.random().
2. Mean reversion - Price always pulls back toward the start price. Prevents
infinite drift.
3. Trend bias - Optional slight upward or downward drift per symbol.
Order Book
Every depth event has a realistic order book:
- Best bid is always below best ask
- Volume tapers with depth (more liquidity near mid price)
- Spread is configurable per symbol
Market Hours
Equity and forex respect real market hours:
const feed = new MarketFeed({
type: 'equity',
marketHours: {
open: '09:30',
close: '16:00',
timezone: 'America/New_York',
days: [1, 2, 3, 4, 5],
},
pairs: [
{ symbol: 'AAPL', startPrice: 175.50 }
]
})
feed.on('open', (info) => console.log('Market opened'))
feed.on('closed', (info) => console.log('Market closed'))
Crypto is always open — no market hours needed.
WebSocket Integration
The library uses EventEmitter, you own
the WebSocket server. Works with Socket.io,
ws, Pusher, Ably, or anything else:
const { Server } = require('socket.io')
const io = new Server(3001)
feed.on('tick', (data) => {
io.to(data.symbol).emit('ticker_update', data)
})
feed.on('depth', (data) => {
io.to(data.symbol).emit('orderbook_update', data)
})
io.on('connection', (socket) => {
socket.on('subscribe', ({ symbol }) => {
socket.join(symbol)
socket.emit('snapshot', feed.getState(symbol))
})
})
feed.start()
Supported Markets
| Type | Always Open | Market Hours | Precision |
|---|---|---|---|
| Crypto | ✓ | Not needed | 2-8 dp |
| Forex | ✗ | Configurable | 5 dp |
| Equity | ✗ | Configurable | 2 dp |
Install
npm install trade-data-generator
- Zero dependencies
- TypeScript support
- Node.js 14+
Links
Would love feedback — what would make this
more useful for your workflow?
Top comments (0)