npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

stock-market-gen

v1.2.3

Published

Generate realistic fake stock market data plus SVG charts (line, area, bar/OHLC, candlestick) and standalone HTML pages. Zero dependencies, seeded, works in Node and the browser.

Downloads

1,022

Readme

stock-market-gen

Generate realistic fake stock market data plus SVG charts and standalone HTML pages. Pure JS, zero dependencies, works in Node and the browser.

A modern, more capable replacement for the old fake-stock-market-generator package.

📖 Full documentation: stock-market-gen.readthedocs.io

Install

npm install stock-market-gen

Quick start

import { generateStock, renderLineChart } from 'stock-market-gen';

const stock = generateStock({ bars: 100, interval: '1d', seed: 'demo' });
const svg = renderLineChart(stock);

CommonJS works too:

const { generateStock, renderLineChart } = require('stock-market-gen');

What you can generate

  • single stocks or whole markets
  • OHLCV bars (open, high, low, close, volume)
  • kind: 'stock' (default) or 'crypto' for wildly different defaults
  • pick any time interval — "1m", "5m", "1h", "1d", "1w", "1mo", "1y" or raw milliseconds (calendar-aware for 1mo / 1y)
  • override anything: symbol, name, sector, start price, drift, volatility, start date
  • supply your own close prices (prices) or full OHLC bars (ohlc)
  • save to JSON and reload it later — output is plain data
  • pass a stocks array to define each company yourself
  • compare several companies on a single chart with renderMultiLineChart — including translucent gradient fills under each line
  • sub-cent precision: prices below $1 keep 4 decimals (below $0.01 keeps 6), so crypto-style series stay readable
  • reproducible output via a seed

Chart types

  • line — close price line
  • area — line plus filled area
  • bar — OHLC bar (tick-left, tick-right)
  • candlestick — classic candles, green up / red down

All renderers return a complete SVG string. Save it to a file, drop it into HTML, or pipe it anywhere.

Customize anything

Every field is optional. Set the ones you care about, the rest are generated for you. The package only invents the symbol and the price series — name, sector, startDate, etc. are yours to provide.

import { generateStock } from 'stock-market-gen';

const stock = generateStock({
  symbol: 'YOUR_SYMBOL',
  name: 'Your Company Name',
  sector: 'Your Sector',
  startPrice: 180,
  drift: 0.12,         // +12% per year
  volatility: 0.28,    // 28% per year
  bars: 60,
  interval: '1w',      // weekly bars
  startDate: '2024-01-01',
  seed: 'anything'
});

Same idea for a market — pass a stocks array and pin whatever you want per company:

import { generateMarket } from 'stock-market-gen';

const market = generateMarket({
  bars: 90,
  interval: '1mo',
  startDate: '2023-01-01',
  seed: 'demo',
  stocks: [
    { symbol: 'YOUR1', name: 'Your Company 1', sector: 'Your Sector' },
    { symbol: 'YOUR2', name: 'Your Company 2', sector: 'Your Sector', volatility: 0.45 },
    { symbol: 'YOUR3' } // name and sector left empty
  ]
});

Or skip the array entirely and just get random tickers with no company info:

const market = generateMarket({ count: 8, bars: 90, seed: 'demo' });

Bring your own prices

Got real prices, hand-picked numbers, or output from another model? Pass them straight in. The generator skips its random walk and uses your data.

import { generateStock } from 'stock-market-gen';

// Just the close prices — open/high/low/volume are synthesised around them
const stock = generateStock({
  symbol: 'MINE',
  name: 'My Series',
  startDate: '2024-01-01',
  interval: '1d',
  prices: [100, 101.5, 99.2, 103.8, 105.1, 102.4, 107.0]
});

// Or full OHLC bars, kept exactly as-is
const stock2 = generateStock({
  interval: '1d',
  startDate: '2024-01-01',
  ohlc: [
    { open: 100, high: 102, low: 99,  close: 101 },
    { open: 101, high: 105, low: 100, close: 104 }
  ]
});

Save and load with JSON

The output is plain JSON-safe data, so saving and reloading is trivial:

import { generateStock, toJSON, fromJSON } from 'stock-market-gen';
import { writeFileSync, readFileSync } from 'node:fs';

const stock = generateStock({ bars: 365, interval: '1d', seed: 'year' });

// Save
writeFileSync('stock.json', toJSON(stock));

// Load — bars are validated, then ready to render or analyse
const restored = fromJSON(readFileSync('stock.json', 'utf8'));

toJSON(stock) is a thin wrapper around JSON.stringify. fromJSON(text) parses, validates, and returns a Stock ready to feed back into any chart renderer.

API

generateStock(options) -> Stock

| Option | Type | Default | Notes | |---------------|----------------------------|------------------|-------| | symbol | string | random 2-5 chars | | | name | string | none (you supply it) | optional company name | | sector | string | none (you supply it) | optional sector label | | kind | 'stock' \| 'crypto' | 'stock' | sets defaults for price range, drift and volatility | | startPrice | number | random in range | range depends on kind (50–500 for stocks, log-uniform 0.01–50000 for crypto) | | drift | number | random | annualised, e.g. 0.05 = +5%/yr | | volatility | number | random | annualised, e.g. 0.3 = 30%/yr | | bars | number | 100 | positive integer | | interval | number \| string | "1d" | ms or "1m"/"1h"/"1d"/"1w"/"1mo"/"1y" (calendar-aware for 1mo / 1y) | | startDate | Date \| number \| string | now - bars*interval | first bar timestamp | | seed | number \| string | random | reproducible output | | prices | number[] | none | use your own close prices; bars becomes the array length | | ohlc | Bar[] | none | use your own full OHLC bars verbatim |

generateMarket({ count, stocks, ...stockOptions }) -> Stock[]

Generate several unique tickers in one call. Pass count for an auto-generated market (random symbols, no name or sector), or stocks to define each company yourself. Any other option is applied as a shared default.

// Auto-generated, 8 random tickers, all daily, same seed -> same market
const market = generateMarket({ count: 8, bars: 90, interval: '1d', seed: 'demo' });

// Hand-picked companies, with shared defaults
const market = generateMarket({
  bars: 60,
  interval: '1w',
  seed: 'custom',
  stocks: [
    { symbol: 'YOUR1', name: 'Your Company 1', sector: 'Your Sector', startPrice: 180 },
    { symbol: 'YOUR2', name: 'Your Company 2', sector: 'Your Sector', volatility: 0.45 },
    { symbol: 'YOUR3' }
  ]
});

Per-line start prices and start dates on a multi-line chart

Every stock can have its own startPrice and startDate. When you render them with renderMultiLineChart in mode: 'price', each line begins at its own value:

import { generateStock, renderMultiLineChart } from 'stock-market-gen';
import { writeFileSync } from 'node:fs';

const a = generateStock({ symbol: 'LOW',  startPrice: 1.0, bars: 120, startDate: '2024-01-01', seed: 'a' });
const b = generateStock({ symbol: 'MID',  startPrice: 1.8, bars: 120, startDate: '2024-02-01', seed: 'b' });
const c = generateStock({ symbol: 'TINY', startPrice: 0.7, bars: 120, startDate: '2024-03-01', seed: 'c' });

writeFileSync(
  'starts.svg',
  renderMultiLineChart([a, b, c], { mode: 'price', title: 'Custom starts' })
);

mode: 'normalized' (the default) is great for comparing relative performance — every line starts at 100. mode: 'price' keeps the actual values, so different starting points stay visible.

renderChart(stock, type, options)

type is "line", "area", "bar" or "candlestick". Or call the dedicated renderers: renderLineChart, renderAreaChart, renderBarChart, renderCandlestickChart.

Chart options:

{
  width: 1000,             // default 1000
  height: 500,             // default 500
  theme: 'light',          // 'light' | 'dark'
  title: 'AAPL — daily',   // pass '' to suppress the default symbol/name title
  showGrid: true,
  showAxes: true,
  xTicks: 8,               // number of date labels on the X axis (default 8)
  yTicks: 5,               // number of price labels on the Y axis (default 5)
  padding: { top: 28, right: 24, bottom: 44, left: 64 },
  colors: { line: '#2563eb' } // override any single color
}

renderMultiLineChart(stocks, options) -> string

Render several companies on the same chart, with a built-in legend in the top-left. Series are plotted against actual timestamps, so stocks with different startDate values land at the right horizontal position.

import { generateMarket, renderMultiLineChart } from 'stock-market-gen';
import { writeFileSync } from 'node:fs';

const market = generateMarket({
  bars: 365, interval: '1d', startDate: '2024-01-01', seed: 'compare',
  stocks: [
    { symbol: 'ALPHA' },
    { symbol: 'BRAVO' },
    { symbol: 'CHARL', color: '#dc2626' } // optional explicit color
  ]
});

writeFileSync('compare.svg', renderMultiLineChart(market, {
  title: 'My Portfolio — 2024',
  mode: 'normalized', // or 'price' for raw values
  area: true,         // add translucent gradient fills under each line
  theme: 'dark'
}));

Multi-line specific options on top of the standard chart options:

| Option | Type | Default | Notes | |--------------|-------------------------------|----------------|-------| | mode | 'normalized' \| 'price' | 'normalized' | 'normalized' rebases each series to 100 at its first bar (great for comparing relative performance regardless of price level). 'price' keeps actual values. | | area | boolean | false | also draw a translucent gradient fill under each line | | legend | boolean | true | show the symbol legend in the top-left of the plot |

Per-stock color (hex string) is honored if set on the Stock object; otherwise a built-in palette is used.

renderHtmlPage(marketOrStock, options) -> string

Builds a self-contained HTML page with embedded SVG charts. Pass an array (whole market) or a single stock.

import { generateMarket, renderHtmlPage } from 'stock-market-gen';
import { writeFileSync } from 'node:fs';

const market = generateMarket({ count: 8, bars: 90, seed: 'page' });
writeFileSync('market.html', renderHtmlPage(market, { theme: 'dark' })); // line is the default

Examples

npm run example       # writes out/line.svg and out/candle.svg
npm run example:page  # writes out/market.html

Glossary

A few finance terms that show up in this package:

  • bar — a single data point covering one time period (open, high, low, close, volume). 100 bars on a daily chart = 100 days of data. The "bar chart" type is just one way to draw bars; line, area and candlestick all render the same bar data, just differently.
  • OHLC — open / high / low / close, the four prices per bar.
  • OHLCV — OHLC plus volume.
  • drift — average expected return per year. 0.1 = +10%/year on average.
  • volatility — how wild the swings are, annualised. 0.3 = roughly ±30% swings per year.
  • seed — any string or number. Same seed = same output every time.

Tutorial — building a market dashboard

Walk through a complete project from scratch. Output: a dashboard.html you can open in a browser.

1. Install

mkdir my-dashboard
cd my-dashboard
npm init -y
npm install stock-market-gen

Open package.json and add "type": "module" so you can use import.

2. Generate a market

Create dashboard.js:

import { generateMarket, renderHtmlPage } from 'stock-market-gen';
import { writeFileSync } from 'node:fs';

const market = generateMarket({
  bars: 365,                 // one year of daily data
  interval: '1d',
  startDate: '2024-01-01',
  seed: 'my-dashboard',      // change this for a different market
  stocks: [
    { symbol: 'NOVA', name: 'Nova Corp',     sector: 'Tech',     startPrice: 250, drift: 0.18, volatility: 0.35 },
    { symbol: 'HRBR', name: 'Harbor Bank',   sector: 'Finance',  startPrice: 120, drift: 0.06, volatility: 0.18 },
    { symbol: 'PEAK', name: 'Peak Energy',   sector: 'Energy',   startPrice: 60,  drift: -0.05, volatility: 0.45 },
    { symbol: 'GRVN', name: 'Greenvine Co.', sector: 'Consumer', startPrice: 80,  drift: 0.10, volatility: 0.22 }
  ]
});

writeFileSync('dashboard.html', renderHtmlPage(market, {
  title: 'My Portfolio',
  theme: 'dark'
}));

console.log('Open dashboard.html');

Run it:

node dashboard.js

Open dashboard.html in any browser. You get a dark-themed grid with one card per stock, each with a line chart, the latest price, and the percent change since day one.

3. Save the data

Want to keep the data so you can re-render later without regenerating?

import { toJSON } from 'stock-market-gen';
writeFileSync('market.json', toJSON(market));

4. Reload and analyse

import { fromJSON, renderCandlestickChart } from 'stock-market-gen';
import { readFileSync, writeFileSync } from 'node:fs';

const stocks = JSON.parse(readFileSync('market.json', 'utf8'));
const nova = fromJSON(stocks[0]);

// Compute simple moving average over the closes
const window = 20;
const closes = nova.bars.map((b) => b.close);
const sma = closes.map((_, i, a) => {
  if (i < window - 1) return null;
  const slice = a.slice(i - window + 1, i + 1);
  return slice.reduce((s, n) => s + n, 0) / window;
});

console.log(`${nova.symbol} latest close: ${closes.at(-1)}`);
console.log(`${nova.symbol} 20d SMA:      ${sma.at(-1).toFixed(2)}`);

writeFileSync('nova.svg', renderCandlestickChart(nova, { theme: 'light' }));

5. Use your own prices

Have real data, hand-picked numbers, or output from another system? Skip the random walk:

import { generateStock, renderLineChart } from 'stock-market-gen';
import { writeFileSync } from 'node:fs';

const myCloses = [100, 102.3, 101.1, 105.7, 108.2, 106.9, 110.5, 113.0, 111.4, 115.8];

const stock = generateStock({
  symbol: 'MINE',
  name: 'My Series',
  startDate: '2024-06-01',
  interval: '1d',
  prices: myCloses           // bar count is taken from this array
});

writeFileSync('mine.svg', renderLineChart(stock));

prices gives close prices only and the package fills in plausible open/high/low/volume. If you have full OHLC, pass ohlc: [...] instead and every value is preserved exactly.

6. Embed a chart in a web page

Every render function returns an SVG string, which is just text. Drop it directly into HTML:

import { generateStock, renderAreaChart } from 'stock-market-gen';
import { writeFileSync } from 'node:fs';

const stock = generateStock({ bars: 120, seed: 'web' });
const svg = renderAreaChart(stock, { width: 1000, height: 400, theme: 'light' });

const html = `<!doctype html>
<title>${stock.symbol}</title>
<body style="font-family: system-ui; padding: 24px;">
  <h1>${stock.symbol}</h1>
  ${svg}
</body>`;

writeFileSync('chart.html', html);

Or in a browser bundle, use it the same way — just inject the returned string into the DOM with innerHTML.

7. Reproducibility

Pass the same seed and you get the exact same output, on any machine, in any version of Node. This is useful for tests, demos, and golden snapshots:

const a = generateStock({ bars: 50, seed: 'pinned' });
const b = generateStock({ bars: 50, seed: 'pinned' });
// a.bars deep-equals b.bars

Drop the seed and you get fresh random data every run.

Recipes

Compare multiple companies with gradient area fills

import { generateMarket, renderMultiLineChart } from 'stock-market-gen';
import { writeFileSync } from 'node:fs';

const market = generateMarket({
  bars: 365,
  interval: '1d',
  startDate: '2024-01-01',
  seed: 'compare',
  stocks: [
    { symbol: 'ALPHA' },
    { symbol: 'BRAVO' },
    { symbol: 'CHARL', color: '#dc2626' }
  ]
});

writeFileSync('compare.svg', renderMultiLineChart(market, {
  title: 'My Portfolio — 2024',
  mode: 'price',
  area: true,
  theme: 'dark'
}));

When area: true, fills are split into per-segment trapezoids. A series that's tall in one region but small in another only sits under its neighbours where it actually is taller — layering can flip across the chart, so a small spike won't get hidden by a big one elsewhere.

Generate crypto instead of stocks

import { generateStock, generateMarket } from 'stock-market-gen';

const btc  = generateStock({ kind: 'crypto', symbol: 'BTC', bars: 365 });
const coins = generateMarket({ count: 5, bars: 90, kind: 'crypto', seed: 'coins' });

Crypto uses log-distributed start prices (anywhere from sub-$1 to $50k+), higher drift and much higher volatility than stocks.

Sub-cent prices

Prices below $1 keep 4 decimals automatically; below $0.01 they keep 6. Axis labels follow suit, so a chart of $0.0008 tokens stays readable.

import { generateStock, renderLineChart } from 'stock-market-gen';
import { writeFileSync } from 'node:fs';

const tiny = generateStock({ kind: 'crypto', symbol: 'TINY', startPrice: 0.0008, bars: 120, seed: 'tiny' });
writeFileSync('tiny.svg', renderLineChart(tiny, { theme: 'dark' }));

Just one chart

import { generateStock, renderLineChart } from 'stock-market-gen';
const svg = renderLineChart(generateStock({ bars: 100 }));

A bigger market with random tickers

const market = generateMarket({ count: 25, bars: 90, seed: 'demo' });

Every chart type, side by side

import { generateStock, renderChart } from 'stock-market-gen';
import { writeFileSync } from 'node:fs';

const stock = generateStock({ bars: 60, seed: 'demo' });
for (const t of ['line', 'area', 'bar', 'candlestick']) {
  writeFileSync(`${t}.svg`, renderChart(stock, t));
}

Custom colors

renderLineChart(stock, {
  theme: 'dark',
  colors: { line: '#fbbf24', grid: '#444' }
});

License

MIT