TickAtlas
TypeScript ~10 min setup

Node.js / TypeScript Integration

Type-safe access to 42 financial indicators, AI insights, and market data. Works with Express, Next.js, serverless functions, and any Node.js environment.

Installation

The client uses the built-in fetch API (Node 18+). No external dependencies required.

bash
# For older Node versions, install node-fetch
npm install node-fetch

TypeScript Interfaces

Full type definitions for all API responses:

typescript
// types.ts — TypeScript interfaces for TickAtlas API responses

interface IndicatorResponse {
  symbol: string;
  indicator: string;
  timeframe: string;
  timestamp: string;
  value: number;
  signal: "overbought" | "oversold" | "neutral" | "bullish" | "bearish";
  ohlc: { open: number; high: number; low: number; close: number };
  metadata: { period: number; source: string; data_age_seconds: number };
}

interface QuoteResponse {
  symbol: string;
  bid: number;
  ask: number;
  spread: number;
  timestamp: string;
}

interface SummaryResponse {
  symbol: string;
  timeframe: string;
  bias: "bullish" | "bearish" | "neutral";
  confidence: number;
  narrative: string;
  indicators_summary: Record<string, { value: number; signal: string }>;
}

interface ScreenerResult {
  symbol: string;
  value: number;
  signal: string;
}

interface ScreenerResponse {
  indicator: string;
  timeframe: string;
  results: ScreenerResult[];
}

Client Class

A type-safe client with automatic rate limit handling:

typescript
// tickatlas.ts — Type-safe API client

const BASE_URL = "https://tickatlas.com/v1";

export class TickAtlasClient {
  private apiKey: string;

  constructor(apiKey: string) {
    this.apiKey = apiKey;
  }

  private async request<T>(endpoint: string, params: Record<string, string>): Promise<T> {
    const url = new URL(`${BASE_URL}/${endpoint}`);
    Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));

    const res = await fetch(url.toString(), {
      headers: { "X-API-Key": this.apiKey },
    });

    if (res.status === 429) {
      const retryAfter = parseInt(res.headers.get("Retry-After") || "2", 10);
      await new Promise((r) => setTimeout(r, retryAfter * 1000));
      return this.request<T>(endpoint, params);
    }

    if (!res.ok) {
      throw new Error(`TickAtlas API error: ${res.status} ${res.statusText}`);
    }

    return res.json() as Promise<T>;
  }

  async indicator(symbol: string, indicator: string, timeframe = "H1"): Promise<IndicatorResponse> {
    return this.request<IndicatorResponse>("indicator", { symbol, indicator, timeframe });
  }

  async indicators(symbol: string, timeframe = "H1") {
    return this.request("indicators", { symbol, timeframe });
  }

  async summary(symbol: string, timeframe = "H1"): Promise<SummaryResponse> {
    return this.request<SummaryResponse>("summary", { symbol, timeframe });
  }

  async quote(symbol: string): Promise<QuoteResponse> {
    return this.request<QuoteResponse>("quote", { symbol });
  }

  async screener(indicator: string, opts: { timeframe?: string; min?: number; max?: number } = {}): Promise<ScreenerResponse> {
    const params: Record<string, string> = { indicator, timeframe: opts.timeframe || "H1" };
    if (opts.min !== undefined) params.min = String(opts.min);
    if (opts.max !== undefined) params.max = String(opts.max);
    return this.request<ScreenerResponse>("screener", params);
  }

  async multi(symbols: string[], indicators: string[], timeframe = "H1") {
    return this.request("multi", {
      symbols: symbols.join(","),
      indicators: indicators.join(","),
      timeframe,
    });
  }

  async ohlc(symbol: string, timeframe = "H1", bars = 100) {
    return this.request("ohlc", { symbol, timeframe, bars: String(bars) });
  }

  async heatmap(timeframe = "H1") {
    return this.request("heatmap", { timeframe });
  }

  async calendar() {
    return this.request("calendar", {});
  }
}

Express Middleware Example

Inject market data into your Express routes:

typescript
// Express middleware — inject market data into requests
import express from "express";
import { TickAtlasClient } from "./tickatlas";

const app = express();
const claw = new TickAtlasClient(process.env.CLAW_API_KEY!);

// Middleware to attach current RSI to request context
app.use("/api/trade", async (req, res, next) => {
  try {
    const symbol = req.query.symbol as string || "EURUSD";
    const rsi = await claw.indicator(symbol, "RSI_14", "H1");
    req.marketData = { rsi };
    next();
  } catch (err) {
    res.status(502).json({ error: "Market data unavailable" });
  }
});

app.get("/api/trade/signal", (req, res) => {
  const { rsi } = req.marketData;
  const action = rsi.value < 30 ? "BUY" : rsi.value > 70 ? "SELL" : "HOLD";
  res.json({ symbol: rsi.symbol, rsi: rsi.value, action });
});

app.listen(3000);

Scheduled Data Fetch

Use node-cron to fetch market summaries on a schedule:

typescript
// Scheduled data fetch with node-cron
import cron from "node-cron";
import { TickAtlasClient } from "./tickatlas";

const claw = new TickAtlasClient(process.env.CLAW_API_KEY!);

// Fetch market summary every hour on the hour
cron.schedule("0 * * * *", async () => {
  const symbols = ["EURUSD", "GBPUSD", "XAUUSD", "BTCUSD"];

  for (const symbol of symbols) {
    const summary = await claw.summary(symbol, "H1");
    console.log(
      `[${new Date().toISOString()}] ${symbol}: ` +
      `bias=${summary.bias} confidence=${summary.confidence}%`
    );

    // Store in database, send alert, etc.
    if (summary.confidence > 80) {
      console.log(`  HIGH CONFIDENCE: ${summary.narrative}`);
    }
  }
});

console.log("Scheduled market summary fetcher running...");