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

tickerdb

v0.2.2

Published

Connect your agent to pre-computed market context that improves reasoning and reduces token usage.

Readme

TickerDB - Pre-computed market data for agents.

npm version CI

Connect your agent to hundreds of indicators like trend_direction, support_level, and analyst_consensus to improve reasoning and reduce token usage.

  • Zero dependencies -- uses native fetch (Node.js 18+)
  • First-class TypeScript support with full type definitions
  • Both ESM and CommonJS builds included
  • Rate limit info returned with every response

Installation

npm install tickerdb

Quick Start

import { TickerDB } from "tickerdb";

const client = new TickerDB({ apiKey: "tdb_your_api_key" });

// Get a summary for a single ticker
const { data, rateLimit } = await client.summary("AAPL");
console.log(data);
console.log(data.as_of_date); // "2026-04-11"
console.log(`Requests remaining: ${rateLimit.requestsRemaining}`);

Usage

Initialize the client

import { TickerDB } from "tickerdb";

const client = new TickerDB({
  apiKey: "tdb_your_api_key",
  // Optional: override the default base URL
  // baseUrl: "https://api.tickerdb.com/v1",
  // Optional: abort requests that take longer than N milliseconds
  // timeout: 30000,
});

When timeout is set, a request that doesn't complete in time is aborted and rejects with a TickerDBError of type "timeout" (status 408):

const client = new TickerDB({ apiKey: "tdb_your_api_key", timeout: 30000 });

try {
  const { data } = await client.summary("AAPL");
} catch (error) {
  if (error instanceof TickerDBError && error.type === "timeout") {
    console.error("Request timed out");
  }
}

Set maxRetries to automatically retry transient failures (HTTP 429, 408, and 5xx, plus network/timeout errors) with exponential backoff and jitter. It defaults to 0 (disabled). Retries apply to all requests, including non-idempotent writes, so enable it with that in mind:

const client = new TickerDB({ apiKey: "tdb_your_api_key", maxRetries: 2 });

Read methods (summary, search, ohlcv, ohlcvBars) accept a per-call signal to cancel a request. It composes with the client timeout, and a cancelled request is never retried:

const controller = new AbortController();
setTimeout(() => controller.abort(), 100);

const { data } = await client.summary("AAPL", { signal: controller.signal });

The fluent query builder exposes the same via .signal():

const { data } = await client.query()
  .eq("momentum_rsi_zone", "oversold")
  .signal(controller.signal)
  .execute();

Summary

Get a detailed summary for a single ticker.

const { data } = await client.summary("AAPL");

// With options
const { data: weekly } = await client.summary("AAPL", {
  timeframe: "weekly",
  date: "2025-01-15",
});

Summary payloads are intentionally forward-compatible. Current snapshots include top-level freshness like as_of_date, same-candle ohlcv.open/high/low/close/volume, richer volume fields such as price_direction_on_volume, raw support/resistance prices such as support_level.level_price, optional level metadata such as support_level.status_meta when requested, Pro sector_context fields like agreement and overbought_count, and stock-only fundamentals such as fundamentals.free_cash_flow and nested fundamentals.insider_activity when available.

Summary stays band-first by default, so sibling _meta / status_meta stability objects are omitted unless you opt in:

const { data } = await client.summary("AAPL", {
  meta: true,
});

const { data: narrow } = await client.summary("AAPL", {
  fields: ["trend.direction", "trend.direction_meta", "fundamentals.free_cash_flow"],
});

MA distance fields are available both in snapshots and events:

const { data: maSnapshot } = await client.summary("AAPL", {
  fields: ["trend.distance_from_ma_band.ma_50"],
});

console.log(maSnapshot.trend.distance_from_ma_band.ma_50);
// "proximity_above"

Semantic MA fields are available in the same trend object:

const { data: maSignals } = await client.summary("AAPL", {
  fields: [
    "trend.ma_slopes.ma_8",
    "trend.ma_slopes.ma_20",
    "trend.ma_slopes.ma_40",
    "trend.ma_slopes.ma_50",
    "trend.ma_slopes.ma_100",
    "trend.ma_slopes.ma_200",
    "trend.ma_compression_band",
    "trend.ma_crossover_event",
  ],
});

Summary with Date Range

Get a summary series for one ticker across a date range by passing start and end.

const { data } = await client.summary("AAPL", {
  start: "2025-01-01",
  end: "2025-03-31",
});

Summary with Events Filter

Query event occurrences for a specific band field.

const { data } = await client.summary("AAPL", {
  field: "momentum_rsi_zone",
  band: "deep_oversold",
});

const { data: extremes } = await client.summary("AAPL", {
  field: "extremes_condition",
  band: "deep_oversold",
});

const { data: maEvents } = await client.summary("BTCUSD", {
  field: "trend_distance_ma50",
  band: "above",
  context_ticker: "SPY",
  context_field: "trend_distance_ma50",
  context_band: "below",
});

const { data: fcfEvents } = await client.summary("AAPL", {
  field: "fundamentals_free_cash_flow",
  band: "moderate_surplus",
});

For MA distance event fields such as trend_distance_ma50, grouped band: "above" and band: "below" aliases are supported in addition to granular values like "proximity_above".

Use stats: true when you want aggregate outcomes instead of raw event rows:

const { data } = await client.summary("SOLUSD", {
  field: "trend_distance_ma20",
  band: "above",
  context_ticker: "QQQ",
  context_field: "trend_distance_ma20",
  context_band: "above",
  before: "2025-07-01",
  stats: true,
});

console.log(data.stats);

OHLCV

Get raw daily OHLCV price bars for a single ticker. Bars are split/dividend-adjusted for equities and ETFs, and unadjusted for crypto. History depth is capped by your plan, and results are cursor-paginated.

const { data } = await client.ohlcv("AAPL");

console.log(data.bars[0]);
// { date: "2026-04-11", open: 172.3, high: 174.1, low: 171.8, close: 173.5, volume: 51234000 }

Control the range, order, and page size, and follow next_cursor to paginate:

const { data } = await client.ohlcv("AAPL", {
  start: "2025-01-01",
  end: "2025-03-31",
  order: "asc",
  limit: 500,
});

if (data.has_more) {
  const { data: next } = await client.ohlcv("AAPL", {
    cursor: data.next_cursor!,
    order: "asc",
  });
}

Each request costs ceil(rows / 100) credits (minimum 1).

To stream every bar across a range without managing the cursor yourself, use ohlcvBars(), which follows next_cursor automatically:

for await (const bar of client.ohlcvBars("AAPL", { start: "2024-01-01", order: "asc" })) {
  console.log(bar.date, bar.close);
}

Account

Get the authenticated account's tier, plan limits, and current usage. This is a read-only metadata endpoint and does not consume request quota.

const { data } = await client.account();

console.log(data.tier);                          // "pro"
console.log(data.limits.monthly_requests);       // plan request cap
console.log(data.usage.monthly_requests_remaining);
console.log(data.usage.credit_balance);

Watchlist

Get the saved watchlist snapshot for the authenticated account.

const { data } = await client.watchlist();
console.log(data.as_of_date); // shared snapshot date when available

const { data: historical } = await client.watchlist({
  date: "2025-01-15",
});

Add tickers to the saved watchlist:

const { data } = await client.addToWatchlist(["AAPL", "MSFT", "TSLA"]);

Remove tickers from the saved watchlist:

const { data } = await client.removeFromWatchlist(["TSLA"]);

Watchlist Changes

Get field-level state changes for your saved watchlist tickers since the last pipeline run.

const { data } = await client.watchlistChanges();

const { data: weekly } = await client.watchlistChanges({
  timeframe: "weekly",
});

Band Stability Metadata

Summary omits sibling _meta objects by default so the primary band label stays front-and-center. Set meta: true to include full paid-tier stability metadata across the response, or request just the few *_meta fields you need via fields.

Summary and watchlist responses also include as_of_date so you can see exactly which market session the snapshot represents.

const { data } = await client.summary("AAPL", {
  meta: true,
});

// The band value itself
console.log(data.trend.direction);          // "uptrend"

// Stability metadata for that band
console.log(data.trend.direction_meta);
// { stability: "established", periods_in_current_state: 18, flips_recent: 1, flips_lookback: 20 }

// New types available
import type { Stability, BandMeta } from "tickerdb";

Stability is one of "fresh", "holding", "established", or "volatile". BandMeta contains the full metadata object. Stability metadata is available on Plus and Pro tiers only.

Stability context also appears in Watchlist, which still includes paid-tier _meta objects by default, and in Watchlist Changes, which include stability fields inline for each changed band.

Query Builder

The SDK includes a fluent query builder for searching assets by categorical state. Chain methods in order: select, filters, sort, limit.

const { data } = await client.query()
  .select('ticker', 'sector', 'trend_distance_ma50', 'momentum_rsi_zone', 'fundamentals_free_cash_flow')
  .eq('trend_distance_ma50', 'proximity_above')
  .eq('fundamentals_free_cash_flow', 'moderate_surplus')
  .eq('sector', 'Technology')
  .sort('extremes_condition_percentile', 'asc')
  .limit(10)
  .execute()

Pass .date('YYYY-MM-DD') (or date in search()) to query a historical snapshot instead of the latest one:

const { data } = await client.query()
  .select('ticker', 'momentum_rsi_zone')
  .eq('momentum_rsi_zone', 'oversold')
  .date('2025-01-15')
  .execute()

Webhooks

Manage webhook subscriptions for the authenticated account. Valid event types are "watchlist.changes" and "data.ready".

// List
const { data } = await client.webhooks.list();

// Create — returns the signing secret once, on creation
const { data: created } = await client.webhooks.create({
  url: "https://example.com/hooks/tickerdb",
  events: { "watchlist.changes": true },
});

// Update
await client.webhooks.update({ id: created.id, active: false });

// Delete
await client.webhooks.delete({ id: created.id });

Inspect delivery history for debugging, optionally filtered to a single webhook:

const { data } = await client.webhooks.deliveries({
  webhook_id: created.id,
  limit: 50,
});

console.log(data.deliveries[0]);
// { id, webhook_id, event_type, status, http_status, attempt_count, ... }

Team

Manage teams for the authenticated account. Listing teams works on any tier; creating teams and inviting members requires the Business plan.

// List teams you belong to, plus your own pending invites
const { data } = await client.team.list();
console.log(data.teams[0]?.members);

// Create a team (Business tier)
const { data: created } = await client.team.create({ name: "Research desk" });
const teamId = created.team.id;

// Invite, promote, and manage members
await client.team.invite({ team_id: teamId, email: "[email protected]", role: "member" });
await client.team.promote({ team_id: teamId, user_id: "usr_123", role: "admin" });
await client.team.removeMember({ team_id: teamId, user_id: "usr_123" });

// Invites
await client.team.resendInvite({ team_id: teamId, invite_id: "inv_123" });
await client.team.cancelInvite({ team_id: teamId, invite_id: "inv_123" });

// Team administration
await client.team.rename({ team_id: teamId, name: "New name" });
await client.team.setSeats({ team_id: teamId, total_seats: 8 });
await client.team.leave({ team_id: teamId });

Error Handling

The SDK throws a TickerDBError for all non-2xx responses. The error includes the HTTP status code, a machine-readable error type, a human-readable message, and optional metadata.

import { TickerDB, TickerDBError } from "tickerdb";

const client = new TickerDB({ apiKey: "tdb_your_api_key" });

try {
  const { data } = await client.summary("AAPL");
} catch (error) {
  if (error instanceof TickerDBError) {
    console.error(`Status: ${error.status}`);
    console.error(`Type: ${error.type}`);
    console.error(`Message: ${error.message}`);

    if (error.status === 429) {
      console.error(`Rate limit resets at: ${error.resetAt}`);
    }

    if (error.upgradeUrl) {
      console.error(`Upgrade your plan: ${error.upgradeUrl}`);
    }
  }
}

Rate Limits

Every response includes parsed rate limit information:

const { data, rateLimit } = await client.summary("AAPL");

console.log(rateLimit.requestLimit);          // Total request limit
console.log(rateLimit.requestsUsed);          // Requests used
console.log(rateLimit.requestsRemaining);     // Requests remaining
console.log(rateLimit.requestReset);          // Reset timestamp
console.log(rateLimit.hourlyRequestLimit);    // Hourly limit
console.log(rateLimit.hourlyRequestsUsed);    // Hourly used
console.log(rateLimit.hourlyRequestsRemaining); // Hourly remaining
console.log(rateLimit.hourlyRequestReset);    // Hourly reset timestamp

Requirements

  • Node.js 18 or later (requires native fetch)

Links

License

MIT