DEV Community

Love Pareek
Love Pareek

Posted on

How I built a fake market data generator for trading UIs, no API keys, zero dependencies

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
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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'))
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
  • Zero dependencies
  • TypeScript support
  • Node.js 14+

Links


Would love feedback — what would make this
more useful for your workflow?

Top comments (0)