Documentation

TickerFlow is a high-performance, professional-grade HTML5 charting library built with TypeScript and optimized for financial applications.

Getting Started

Follow these steps to get TickerFlow running in your application. The process takes less than 5 minutes.

1

Create Your Account

Sign up for a TickerFlow account to access your dashboard and manage your Professional license.

Get Professional License
2

Professional License

Obtain your Professional license key ($499/year) which includes unrestricted access to all charting engine features, indicators, and priority support.

Professional License
$499/year
  • All Technical Indicators
  • Real-time Streaming
  • Custom Indicators API
  • Priority Support
View full pricing details
3

Get Your License Key

After signing up, go to your dashboard and create a license key. This key unlocks features based on your plan.

Your License KeyActive
SP-A1B2C3D4-E5F6G7H8-XY12
Go to Dashboard
4

Get the Library

Choose your preferred method to integrate the TickerFlow engine:

Recommended: Institutional Direct DownloadPro Only

Download the optimized production build (`tickerflow-chart.js`) directly from your dashboard. This allows you to self-host the library on your internal infrastructure for maximum performance and security.

Download from Dashboard
Advanced: npm Integration
javascript
1npm install @tickerflow/core

Private npm registry access is available for Enterprise infrastructure.

5

Initialize with Your License Key

Add your license key when initializing the chart. Store it in environment variables for security.

Environment variables (.env file):

javascript
1# .env.local (Next.js) or .env (Vite/React)
2NEXT_PUBLIC_TICKERFLOW_KEY=SP-A1B2C3D4-E5F6G7H8-XY12
3NEXT_PUBLIC_ALPACA_KEY=your_alpaca_api_key
4NEXT_PUBLIC_ALPACA_SECRET=your_alpaca_secret_key

Initialize the chart:

javascript
1const chart = new StockChart.StockChartWidget({
2  ticker: 'XXXX', // Use 'XXXX' for simulated live data
3  apiKey: process.env.NEXT_PUBLIC_ALPACA_KEY,
4  secretKey: process.env.NEXT_PUBLIC_ALPACA_SECRET,
5  licenseKey: process.env.NEXT_PUBLIC_TICKERFLOW_KEY,
6  theme: 'dark',
7  defaultTimeframe: '15m',
8});
9
10chart.mount(document.getElementById('chart-container'));
6

Build Your First Workspace

From an end‑user perspective, the workflow is simple: load a chart, set your market, add indicators, and save your layout or workspace for later use.

  • Search a ticker, set timeframe, and theme.
  • Add indicators and drawings from the toolbars.
  • Save a layout, then create a workspace with multiple charts.
  • Switch between saved workspaces anytime.

You're Ready!

Your chart is now live! Continue reading for framework-specific examples and advanced features.

Quick tip: The license key is validated automatically. Features are enabled based on your plan tier.

License Tiers & Features

  • All Chart Types (Candlestick, Line, Area)
  • All Technical Indicators
  • Real-time Streaming
  • Custom Indicators API
  • Unlimited Data Points
  • Unlimited Chart Instances
  • White-label (Remove branding)
  • Priority Support

Vanilla JavaScript / HTML

Perfect for simple websites, WordPress, or legacy applications.

javascript
1<!DOCTYPE html>
2<html>
3<head>
4  <title>My Trading App</title>
5  <script src="https://cdn.tickerflow.dev/v1/tickerflow.min.js"></script>
6</head>
7<body>
8  <div id="chart-container" style="width: 100%; height: 600px;"></div>
9
10  <script>
11    const chart = new StockChart.StockChartWidget({
12      ticker: 'XXXX', // Use 'XXXX' for simulated live data
13      apiKey: 'YOUR_ALPACA_KEY',
14      secretKey: 'YOUR_ALPACA_SECRET',
15      licenseKey: 'YOUR_TICKERFLOW_LICENSE_KEY',
16      theme: 'dark',
17      defaultTimeframe: '15m'
18    });
19    
20    chart.mount(document.getElementById('chart-container'));
21  </script>
22</body>
23</html>

Next.js / React

We provide custom hooks for seamless React integration with full SSR support.

javascript
1// components/TradingChart.tsx
2'use client';
3
4import { useStockChart, ChartCanvas } from 'tickerflow';
5
6export default function TradingChart() {
7  const { chart, bars, isLoading, isLive, setTicker, setTimeframe } = useStockChart({
8    licenseKey: process.env.NEXT_PUBLIC_TICKERFLOW_KEY!,
9    ticker: 'BTC/USDT',
10    instrument: 'crypto',
11    cryptoConnector: 'binance',
12    binance: {
13      // Optional overrides
14      restBaseUrl: 'https://api.binance.com',
15      wsBaseUrl: 'wss://stream.binance.com:9443',
16      defaultQuoteAsset: 'USDT',
17    },
18    theme: 'dark',
19    defaultTimeframe: '15m',
20    width: 800,
21    height: 600,
22  });
23
24  if (!chart) return <div>Loading...</div>;
25
26  return (
27    <div className="h-screen w-full">
28      <ChartCanvas chart={chart} bars={bars} width={800} height={600} />
29    </div>
30  );
31}

Vue.js

Use a ref to mount the widget in the onMounted lifecycle hook.

javascript
1<template>
2  <div ref="chartContainer" class="chart-container" style="width: 100%; height: 600px;"></div>
3</template>
4
5<script setup>
6import { onMounted, ref, onBeforeUnmount } from 'vue';
7import { StockChartWidget } from 'tickerflow';
8
9const chartContainer = ref(null);
10let widget = null;
11
12onMounted(() => {
13  widget = new StockChartWidget({
14    ticker: 'AAPL',
15    apiKey: import.meta.env.VITE_ALPACA_KEY,
16    secretKey: import.meta.env.VITE_ALPACA_SECRET,
17    licenseKey: import.meta.env.VITE_TICKERFLOW_KEY,
18    connector: 'alpaca', // 'alpaca' | 'massive' | 'yahoo'
19    theme: 'dark',
20    defaultTimeframe: '15m',
21    width: 800,
22    height: 600,
23  });
24  widget.mount(chartContainer.value);
25});
26
27onBeforeUnmount(() => {
28  if (widget) widget.destroy();
29});
30</script>

Technical Indicators

TickerFlow includes 20+ professional-grade indicators used by traders worldwide. Indicators are rendered in real-time and automatically update with live data.

Overlay Indicators

Rendered directly on the price chart

  • EMAExponential Moving Average
  • SMASimple Moving Average
  • Bollinger BandsVolatility bands ±2σ
  • VWAPVolume Weighted Avg Price
  • Ichimoku CloudSupport/resistance zones
  • Parabolic SARTrend reversal points

Separate Pane Indicators

Rendered in their own panel below the chart

  • RSIRelative Strength Index (0-100)
  • MACDMoving Avg Convergence/Divergence
  • StochasticMomentum oscillator (%K, %D)
  • VolumeBar volume with coloring
  • ATRAverage True Range
  • OBVOn-Balance Volume

Strategy IndicatorsProfessional

Advanced multi-signal indicators for professional traders

ORB (Opening Range Breakout)

Identifies breakout levels based on the first 15-30 minutes of trading. Shows high/low range with extension targets.

SMC (Smart Money Concepts)

Detects order blocks, fair value gaps (FVG), break of structure (BOS), and liquidity zones.

W-Lines (EMA Cloud Strategy)

Dual EMA (9/21) cloud system with multi-timeframe trend panel. Shows bullish/bearish cloud fills, PDR (Prior Day Range) levels, and reclaim signals when price re-enters the cloud.

Adding Indicators

Use chart.addIndicator(type, options) to add any indicator. Each indicator has sensible defaults, but you can customize colors, lengths, and other parameters.

javascript
1// Add a simple EMA with custom color
2chart.addIndicator('ema', { length: 50, color: '#3b82f6' });
3
4// Add RSI with custom overbought/oversold levels
5chart.addIndicator('rsi', { 
6  length: 14, 
7  overbought: 70, 
8  oversold: 30 
9});
10
11// Add MACD with custom parameters
12chart.addIndicator('macd', { 
13  fast: 12, 
14  slow: 26, 
15  signal: 9,
16  histogramColors: { positive: '#22c55e', negative: '#ef4444' }
17});
18
19// Add Bollinger Bands
20chart.addIndicator('bollinger', { 
21  length: 20, 
22  stdDev: 2,
23  color: '#8b5cf6'
24});
25
26// Remove an indicator
27chart.removeIndicator('ema');

Note: All indicators including Advanced and Strategy indicators are available with the Professional license.

Custom Indicators

Overview

The Custom Indicator API allows you to extend TickerFlow with your own proprietary algorithms. Unlike other libraries that require you to learn a domain-specific language, TickerFlow lets you write indicators in standard JavaScript or TypeScript.

Your indicators become first-class citizens in the chart:

  • They appear in the Indicators Menu.
  • They have auto-generated Settings Dialogs based on your config.
  • They support Custom Rendering (Canvas API) for advanced visualizations.

1. Configuration

The configuration object defines how your indicator looks and behaves in the UI.

Key Properties

id

Unique identifier (e.g., 'my_algo').

placement

'overlay' (main chart) or 'separate' (bottom pane).

inputs

Array of user-editable fields (numbers, booleans, selects).

outputs

Default styling for lines (color, width).

javascript
1const config = {
2  name: "Super Trend",
3  type: "super_trend",
4  placement: "overlay",
5  inputs: [
6    { name: "period", type: "number", default: 10, min: 1 },
7    { name: "multiplier", type: "number", default: 3.0, step: 0.1 }
8  ],
9  outputs: [
10    { name: "up", color: "#00ff00" },
11    { name: "down", color: "#ff0000" }
12  ]
13};

2. Calculation (TALib)

The calculate function contains your logic. It receives the full history of bars, the user's current input values, and the TALib helper library — a collection of pre-built technical analysis functions so you don't have to implement them from scratch.

Function Signature

javascript
1const calculate = (bars: Bar[], inputs: Record<string, any>, lib: TALib) => IndicatorValue[]
bars

Array of OHLCV bar objects with timestamp, open, high, low, close, volume

inputs

User-configured values from your config.inputs definition

lib

TALib helper object with technical analysis functions

TALib Function Reference

Moving Averages
lib.sma(source, length)Returns: number[]

Simple Moving Average — The arithmetic mean of the last length values. Commonly used to smooth price data and identify trends.

javascript
1const close = bars.map(b => b.close);
2const sma20 = lib.sma(close, 20);  // 20-period SMA
3const sma50 = lib.sma(close, 50);  // 50-period SMA
4
5// SMA crossover strategy
6const goldenCross = lib.crossover(sma20, sma50);  // Fast crosses above slow
lib.ema(source, length)Returns: number[]

Exponential Moving Average — Weighted moving average that gives more importance to recent prices. Reacts faster to price changes than SMA. Uses multiplier: k = 2 / (length + 1)

javascript
1const close = bars.map(b => b.close);
2const ema9 = lib.ema(close, 9);    // Fast EMA (scalping)
3const ema21 = lib.ema(close, 21);  // Medium EMA (swing)
4const ema200 = lib.ema(close, 200); // Slow EMA (trend)
5
6// EMA ribbon
7const emas = [9, 21, 55, 100, 200].map(len => lib.ema(close, len));
Oscillators & Momentum
lib.rsi(source, length)Returns: number[]

Relative Strength Index — Momentum oscillator measuring speed and magnitude of price changes. Returns values 0-100. Traditional interpretation: >70 = overbought, <30 = oversold.

javascript
1const close = bars.map(b => b.close);
2const rsi = lib.rsi(close, 14);  // Standard 14-period RSI
3
4// Detect overbought/oversold
5return bars.map((b, i) => ({
6  timestamp: b.timestamp,
7  value: rsi[i],
8  // Signal when RSI crosses key levels
9  signal: lib.crossunder([rsi[i]], 30)[0] ? 'oversold' 
10        : lib.crossover([rsi[i]], 70)[0] ? 'overbought' 
11        : null
12}));
Volatility
lib.stdev(source, length)Returns: number[]

Standard Deviation — Measures price volatility/dispersion from the mean. Used to calculate Bollinger Bands and other volatility-based indicators.

javascript
1const close = bars.map(b => b.close);
2const sma20 = lib.sma(close, 20);
3const stdev20 = lib.stdev(close, 20);
4
5// Build Bollinger Bands manually
6const upperBand = sma20.map((sma, i) => sma + (stdev20[i] * 2));
7const lowerBand = sma20.map((sma, i) => sma - (stdev20[i] * 2));
8
9// Bollinger Band Width (volatility measure)
10const bbWidth = upperBand.map((upper, i) => (upper - lowerBand[i]) / sma20[i]);
Price Extremes
lib.highest(source, length)Returns: number[]

Highest Value — Returns the maximum value over the last length periods. Useful for Donchian Channels, breakout detection, and ATR calculations.

javascript
1const high = bars.map(b => b.high);
2const low = bars.map(b => b.low);
3
4// Donchian Channel (20-period)
5const donchianHigh = lib.highest(high, 20);
6const donchianLow = lib.lowest(low, 20);
7const donchianMid = donchianHigh.map((h, i) => (h + donchianLow[i]) / 2);
8
9// Breakout detection
10const breakoutUp = lib.crossover(high, donchianHigh);
lib.lowest(source, length)Returns: number[]

Lowest Value — Returns the minimum value over the last length periods. Commonly used with highest() for channel-based strategies.

javascript
1const close = bars.map(b => b.close);
2const low = bars.map(b => b.low);
3
4// Williams %R (similar to Stochastic)
5const highest14 = lib.highest(close, 14);
6const lowest14 = lib.lowest(low, 14);
7const williamsR = close.map((c, i) => 
8  ((highest14[i] - c) / (highest14[i] - lowest14[i])) * -100
9);
Crossover Detection
lib.crossover(a, b)Returns: boolean[]

Crossover — Returns true when series a crosses above series b. The second parameter can be an array OR a constant number. Essential for signal generation.

javascript
1const close = bars.map(b => b.close);
2const ema9 = lib.ema(close, 9);
3const ema21 = lib.ema(close, 21);
4
5// EMA crossover (array vs array)
6const bullishCross = lib.crossover(ema9, ema21);
7
8// Price crosses above a level (array vs constant)
9const breaksResistance = lib.crossover(close, 150.00);
10
11// RSI exits oversold (crosses above 30)
12const rsi = lib.rsi(close, 14);
13const rsiExitOversold = lib.crossover(rsi, 30);
lib.crossunder(a, b)Returns: boolean[]

Crossunder — Returns true when series a crosses below series b. Same signature as crossover. Used for sell signals or stop-loss triggers.

javascript
1const close = bars.map(b => b.close);
2const ema9 = lib.ema(close, 9);
3const ema21 = lib.ema(close, 21);
4
5// EMA death cross
6const bearishCross = lib.crossunder(ema9, ema21);
7
8// Price breaks support
9const breaksSupport = lib.crossunder(close, 140.00);
10
11// RSI enters overbought territory
12const rsi = lib.rsi(close, 14);
13const rsiEnterOverbought = lib.crossover(rsi, 70);  // Use crossover for entering
14const rsiExitOverbought = lib.crossunder(rsi, 70);  // Use crossunder for exiting

Complete Calculate Example

Here's a full example showing how to build a custom "Dual EMA Crossover" indicator with buy/sell signals:

javascript
1const calculate = (bars, inputs, lib) => {
2  // 1. Extract price data from bars
3  const close = bars.map(b => b.close);
4  
5  // 2. Get user inputs (defined in config.inputs)
6  const fastLength = inputs.fastLength || 9;
7  const slowLength = inputs.slowLength || 21;
8  
9  // 3. Calculate EMAs using TALib
10  const fastEMA = lib.ema(close, fastLength);
11  const slowEMA = lib.ema(close, slowLength);
12  
13  // 4. Detect crossovers for signals
14  const bullishCross = lib.crossover(fastEMA, slowEMA);
15  const bearishCross = lib.crossunder(fastEMA, slowEMA);
16  
17  // 5. Return indicator values
18  return bars.map((bar, i) => ({
19    timestamp: bar.timestamp,
20    
21    // Multiple output values (for multi-line indicators)
22    fast: fastEMA[i],
23    slow: slowEMA[i],
24    
25    // Signal data (for custom rendering)
26    signal: bullishCross[i] ? 'buy' 
27          : bearishCross[i] ? 'sell' 
28          : null,
29    signalPrice: bar.close
30  }));
31};

💡 Pro Tips

  • • TALib functions return arrays with NaN for the first length-1 bars (warmup period)
  • • Always use bars.map(b => b.close) to extract price arrays — don't pass the bars array directly
  • • Crossover/crossunder return boolean[] — use them to generate discrete signals
  • • You can combine multiple TALib functions to build complex indicators (MACD, Stochastic, etc.)

3. Custom Rendering

For standard lines, you don't need this. But if you want to draw shapes, bands, or text (like arrows for buy/sell signals), provide a render function. It gives you direct access to the HTML5 Canvas Context and a lib helper object.

Available Render Helpers (lib)

lib.drawArrowUp(ctx, x, y, color, size)
lib.drawArrowDown(ctx, x, y, color, size)
lib.drawCircle(ctx, x, y, color, radius)
lib.drawText(ctx, x, y, text, color, font)

Example: Drawing Arrows on Crossover

javascript
1// 1. Calculate logic with signals
2const calculate = (bars, inputs, lib) => {
3  const close = bars.map(b => b.close);
4  const fast = lib.sma(close, 10);
5  const slow = lib.sma(close, 20);
6  const buySignal = lib.crossover(fast, slow);
7  const sellSignal = lib.crossunder(fast, slow);
8
9  return bars.map((b, i) => ({
10    timestamp: b.timestamp,
11    value: fast[i],
12    // Pass signal data to renderer
13    signal: buySignal[i] ? 'buy' : sellSignal[i] ? 'sell' : null,
14    price: b.close
15  }));
16};
17
18// 2. Render arrows based on signals using helper lib
19const render = (ctx, { bars, scale, values }, lib) => {
20  ctx.save();
21  
22  values.forEach(v => {
23    if (!v.signal) return;
24
25    // Find X coordinate (bar index)
26    const barIndex = bars.findIndex(b => b.timestamp === v.timestamp);
27    const x = scale.x(barIndex);
28    
29    // Find Y coordinate (price)
30    const y = scale.y(v.price);
31
32    if (v.signal === 'buy') {
33      // Draw Up Arrow (Green) below the bar
34      lib.drawArrowUp(ctx, x, y + 20, '#00ff00');
35    } else if (v.signal === 'sell') {
36      // Draw Down Arrow (Red) above the bar
37      lib.drawArrowDown(ctx, x, y - 20, '#ff0000');
38    }
39  });
40
41  ctx.restore();
42};

Putting it all together

Register your indicator once, and it's available forever.

javascript
1chart.registerCustomIndicator({
2  config: config,
3  calculate: calculate,
4  render: render // Optional
5});

Drawing Tools

Professional charting requires the ability to annotate and analyze. TickerFlow includes a comprehensive suite of drawing tools that persist across sessions and can be exported/imported.

📏 Lines & Rays

  • Trendline — Connect two price points to identify trend direction
  • Horizontal Line — Mark support/resistance levels
  • Vertical Line — Mark important time events
  • Ray — Extends infinitely in one direction
  • Extended Line — Extends infinitely in both directions

📐 Fibonacci Tools

  • Retracement — Find pullback levels (23.6%, 38.2%, 50%, 61.8%)
  • Extension — Project price targets beyond the swing
  • Fan — Diagonal support/resistance from a pivot
  • Time Zones — Vertical lines at Fib intervals

🔷 Shapes

  • Rectangle — Highlight price ranges or zones
  • Circle — Mark key reversal points
  • Triangle — Identify chart patterns
  • Parallel Channel — Define trading channels

💬 Annotations

  • Text — Add notes anywhere on the chart
  • Callout — Text with arrow pointer
  • Price Label — Shows exact price at a point
  • Arrow — Point to specific bars or patterns

📊 Position ToolsPro+

Visualize and plan trades with built-in Long and Short position calculators. Instantly see your Risk:Reward ratio, potential P&L, and live position tracking.

📈 Long Position

Plan bullish trades with visual entry, target, and stop levels.

  • Entry Price — Your planned buy price
  • Take Profit (TP) — Target exit for profit (green zone)
  • Stop Loss (SL) — Exit level to limit loss (red zone)
  • Quantity — Number of shares (default: 100)
  • R:R Ratio — Auto-calculated risk-to-reward

📉 Short Position

Plan bearish trades with inverted profit/loss zones.

  • Entry Price — Your planned short entry
  • Take Profit (TP) — Target below entry (green zone)
  • Stop Loss (SL) — Exit above entry (red zone)
  • Quantity — Number of shares (default: 100)
  • R:R Ratio — Auto-calculated risk-to-reward

Real-Time P&L Display

Profit Zone
Shows potential profit % and $ amount at Take Profit level
Loss Zone
Shows potential loss % and $ amount at Stop Loss level
Live P&L Badge
Tracks current unrealized P&L based on live price
javascript
1// Programmatically add a Long Position
2chart.addDrawing('longPosition', {
3  entryPrice: 150.00,
4  takeProfit: 165.00,    // +10% target
5  stopLoss: 142.50,      // -5% stop
6  quantity: 200,         // 200 shares
7  color: '#26a69a'
8});
9
10// Add a Short Position
11chart.addDrawing('shortPosition', {
12  entryPrice: 150.00,
13  takeProfit: 135.00,    // -10% target (profit for short)
14  stopLoss: 157.50,      // +5% stop (loss for short)
15  quantity: 100
16});
17
18// Position tools auto-calculate:
19// - Risk:Reward ratio (R:R)
20// - Profit amount: (TP - Entry) × Qty
21// - Loss amount: (Entry - SL) × Qty
22// - Profit/Loss percentages
23// - Current P&L with live price tracking

User Interaction

Drawing tools are accessible via the toolbar on the left side of the chart. Users can:

  • Click + Drag to create drawings
  • Click to select existing drawings
  • Drag handles to resize or reposition
  • Right-click to access properties or delete
  • Double-click text to edit

Programmatic Control

Save user drawings to your database and restore them on page load:

javascript
1// Export all drawings as JSON (save to your backend)
2const savedDrawings = chart.exportDrawings();
3await fetch('/api/save-drawings', {
4  method: 'POST',
5  body: JSON.stringify({ symbol: 'AAPL', drawings: savedDrawings })
6});
7
8// Import drawings (restore from your backend)
9const response = await fetch('/api/drawings?symbol=AAPL');
10const { drawings } = await response.json();
11chart.importDrawings(drawings);
12
13// Clear all drawings
14chart.clearDrawings();
15
16// Programmatically add a horizontal line
17chart.addDrawing('horizontal_line', {
18  price: 150.00,
19  color: '#ef4444',
20  lineWidth: 2,
21  label: 'Stop Loss'
22});

Note: Basic drawing tools (lines, rectangles, text) are available on all plans. Advanced tools (Fibonacci, channels, complex shapes) require a Pro license or higher.

Price Alerts

Pro+

Never miss a trading opportunity. TickerFlow's built-in alert system notifies you when price reaches your target levels via browser notifications, sound alerts, Telegram, and webhook integrations.

Available Alert Conditions

Crosses Above

Triggers when price moves above your level

Crosses Below

Triggers when price moves below your level

Greater Than

Triggers while price is above level

Less Than

Triggers while price is below level

%

Percent Change

Triggers on % move from reference price

Δ

Price Change

Triggers on absolute $ move

Creating Alerts via UI

Users can create alerts directly from the chart:

  1. Right-click on any price level on the chart
  2. Select "Create Alert" from the context menu
  3. Configure the alert condition and notification preferences
  4. Click "Save" — the alert line appears on chart

Programmatic Alerts

javascript
1import { PriceAlertManager, ALERT_CONDITIONS } from 'tickerflow';
2
3const alerts = PriceAlertManager.getInstance();
4
5// Create a simple price alert
6alerts.createAlert({
7  symbol: 'AAPL',
8  condition: ALERT_CONDITIONS.CROSSES_ABOVE,
9  value: 190.00,
10  repeatMode: 'ONCE', // 'ONCE' | 'EVERY_TIME' | 'ONCE_PER_BAR'
11  message: 'AAPL broke $190!' // Custom notification message
12});
13
14// Create alert with webhook (for Slack, Discord, etc.)
15alerts.createAlert({
16  symbol: 'BTCUSD',
17  condition: ALERT_CONDITIONS.PERCENT_CHANGE,
18  value: 5, // 5% move
19  repeatMode: 'ONCE_PER_BAR',
20  webhookUrl: 'https://hooks.slack.com/services/XXX/YYY/ZZZ',
21  webhookPayload: {
22    text: '🚨 BTC moved 5%! Current price: {{price}}'
23  }
24});
25
26// List all active alerts
27const activeAlerts = alerts.getAlerts();
28
29// Remove an alert
30alerts.removeAlert(alertId);
31
32// Clear all alerts for a symbol
33alerts.clearAlerts('AAPL');

📱 Telegram Notifications

Send alerts directly to Telegram using a bot token and chat ID.

  1. Create a bot with @BotFather and copy the bot token.
  2. Send your bot a message (e.g. /start), then visit https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates and read message.chat.id as the chat ID.
  3. Set notificationSettings.telegram when creating the widget.
javascript
1const chart = new StockChartWidget({
2  ticker: 'AAPL',
3  notificationSettings: {
4    telegram: {
5      enabled: true,
6      botToken: '123456789:ABCDEF...',
7      chatId: '123456789'
8    }
9  }
10});

Security note: storing a bot token in a browser app makes it visible to users. For production, send alerts to your backend via webhooks and have your server send Telegram messages.

🔗 Webhook Integration

Connect alerts to your trading bots, notification systems, or automation workflows. Webhooks send a POST request with alert data when triggered.

javascript
1// Webhook payload sent to your endpoint:
2{
3  "alert_id": "abc123",
4  "symbol": "AAPL",
5  "condition": "CROSSES_ABOVE",
6  "trigger_price": 190.00,
7  "current_price": 190.25,
8  "triggered_at": "2025-01-05T14:30:00Z",
9  "custom_payload": { ... } // Your custom data
10}

Configuration Options

Customize every aspect of your chart. All options can be passed when creating the widget or updated dynamically at runtime.

Required Options

OptionTypeDescription
tickerstringSymbol to display (e.g., "AAPL", "BTC/USDT", "EUR_USD"). Use "XXXX" for simulated demo data.
licenseKeystringYour TickerFlow license key from the dashboard. Features are enabled based on your plan.

Data Connection

OptionTypeDefaultDescription
connectorstring"alpaca""alpaca" | "massive" | "yahoo" — stocks/index connector
apiKeystringAPI key for Alpaca/Massive (stocks/index)
secretKeystringSecret key (Alpaca only)
cryptoConnectorstring"binance"Crypto connector (currently: "binance")
binanceobjectBinance config: restBaseUrl, wsBaseUrl, defaultQuoteAsset
forexConnectorstring"oanda"Forex connector (currently: "oanda")
oandaobjectOANDA config: accessToken, accountId, environment. (Optional: falls back to Massive/Yahoo if missing)
proxyUrlstringcorsproxy.ioCORS proxy URL for Yahoo connector
dataProviderDataProviderCustom data provider object (overrides connector)

Display & Appearance

OptionTypeDefaultDescription
themestring"dark""dark" | "light" — color scheme
defaultTimeframestring"15m""1m" | "5m" | "15m" | "1h" | "4h" | "1d" | "1w"
widthnumberautoChart width in pixels (auto-fills container if not set)
heightnumberautoChart height in pixels (auto-fills container if not set)
tickerWatermarkOpacitynumber0.03Controls ticker watermark opacity in the chart background (0–0.2)
debugbooleanfalseEnable verbose console logging

Callbacks & AI

OptionTypeDescription
onPriceUpdate(price, symbol) => voidCalled when the latest price updates
onTickerChange(ticker, name?) => voidCalled when the user selects a new ticker
notificationSettingsPartial<PriceAlertSettings>Default alert preferences (sound, channels, etc.)
openAIApiKeystringAPI key for on‑chart AI analysis
openAIModelstringModel name for AI analysis
openAIEndpointstringCustom AI endpoint (server proxy)
onAiAnalysis(args) => Promise<ChartAnalysisJson>Handle AI analysis requests yourself

Complete Example

javascript
1const chart = new StockChartWidget({
2  // Required
3  ticker: 'AAPL',
4  licenseKey: process.env.TICKERFLOW_KEY,
5  
6  // Stocks / index
7  connector: 'alpaca',
8  apiKey: process.env.ALPACA_KEY,
9  secretKey: process.env.ALPACA_SECRET,
10
11  // Crypto (Binance)
12  // cryptoConnector: 'binance',
13  // binance: { defaultQuoteAsset: 'USDT' },
14
15  // Forex (OANDA)
16  // forexConnector: 'oanda',
17  // oanda: { accessToken: process.env.OANDA_TOKEN, accountId: process.env.OANDA_ACCOUNT_ID, environment: 'practice' },
18  
19  // Display
20  theme: 'dark',
21  defaultTimeframe: '15m',
22  width: 1200,
23  height: 800,
24  tickerWatermarkOpacity: 0.03,
25  debug: false,
26});
27
28chart.mount(document.getElementById('chart'));

Workspaces & Multi‑Chart Layouts

A workspace lets end users organize multiple charts into a single view. Each workspace can contain different tickers, timeframes, and chart types, and can be saved and recalled from the Workspaces menu.

Create a workspace

  1. Open the Workspaces menu in the chart header.
  2. Choose a grid layout (2‑chart, 3‑chart, 4‑chart, etc.).
  3. Set each chart’s ticker and timeframe.
  4. Save the workspace with a name.

Manage workspaces

  • Load saved workspaces from the same menu.
  • Update a workspace after changing layouts or indicators.
  • Delete unused workspaces to keep things tidy.

Data Connectors

TickerFlow supports multiple data sources out of the box. Each connector handles authentication, data fetching, and real-time streaming automatically. Stocks/index use connector, while crypto/forex use dedicated connector props.

Quick Comparison

FeatureAlpacaMassiveYahooBinanceOANDA
Real-time Streaming✓ WebSocket✓ WebSocket✓ WebSocket✓ Streaming HTTP
API Key RequiredYesYesNoNoYes
Stocks
Crypto
Forex
Best ForUS Stocks, Real-timeGlobal marketsQuick demos, EODCrypto bars + streamingForex candles + quotes

AlpacaDefaultRecommended

Direct connection to Alpaca Markets API. Best choice for US stocks with real-time WebSocket streaming. Supports both IEX and full SIP data feeds.

Alpaca Data Plans

  • IEX (Basic)

    IEX exchange data, 200 API calls/min, 30 streaming symbols

  • Algo Trader Plus

    Full SIP (all US exchanges), unlimited calls, unlimited streaming

Get API Keys
javascript
1const chart = new StockChartWidget({
2  ticker: 'AAPL',
3  connector: 'alpaca', // Default, can be omitted
4  apiKey: 'YOUR_ALPACA_KEY',
5  secretKey: 'YOUR_ALPACA_SECRET',
6  licenseKey: 'YOUR_TICKERFLOW_KEY'
7});

Massive Data

Global market data provider with extensive historical data. Good choice for international stocks and when you need 10+ years of history.

Massive Data Plans

  • Basic (Free): 5 calls/min, 2y history, EOD data
  • Starter ($29/mo): Unlimited calls, 5y history, 15m delayed
  • Developer ($79/mo): Unlimited calls, 10y history, 15m delayed
  • Advanced ($199/mo): Unlimited calls, 20y+ history, Real-time
javascript
1const chart = new StockChartWidget({
2  ticker: 'AAPL',
3  connector: 'massive',
4  apiKey: 'YOUR_MASSIVE_KEY',
5  // No secretKey needed for Massive
6  licenseKey: 'YOUR_TICKERFLOW_KEY'
7});

Yahoo FinanceNo API Key

Uses Yahoo Finance data via a CORS proxy. Perfect for quick demos, development, or when you don't need real-time data. No API key required.

Note: Yahoo connector doesn't support real-time streaming. Data is fetched on load and on timeframe change. For live charts, use Alpaca or Massive.

javascript
1const chart = new StockChartWidget({
2  ticker: 'AAPL',
3  connector: 'yahoo',
4  // No API key needed!
5  // Optional: Use your own proxy for better reliability
6  // proxyUrl: 'https://your-cors-proxy.com/?url=',
7  licenseKey: 'YOUR_TICKERFLOW_KEY'
8});

BinanceCrypto

Crypto historical data + live bars via Binance. No API key required.

javascript
1const chart = new StockChartWidget({
2  ticker: 'BTC/USDT',
3  cryptoConnector: 'binance',
4  binance: {
5    // Optional overrides
6    restBaseUrl: 'https://api.binance.com',
7    wsBaseUrl: 'wss://stream.binance.com:9443',
8    defaultQuoteAsset: 'USDT',
9  },
10  licenseKey: 'YOUR_TICKERFLOW_KEY'
11});

OANDAForex

High-fidelity Forex candles + live quotes via OANDA. Requires an access token and account id. If these are not provided, the library will automatically attempt to fetch Forex data via Massive, Yahoo Finance, or Alpaca.

javascript
1const chart = new StockChartWidget({
2  ticker: 'EUR_USD',
3  forexConnector: 'oanda',
4  oanda: {
5    accessToken: 'YOUR_OANDA_ACCESS_TOKEN',
6    accountId: 'YOUR_OANDA_ACCOUNT_ID',
7    environment: 'practice', // or 'live'
8  },
9  licenseKey: 'YOUR_TICKERFLOW_KEY'
10});

Custom Data ProviderAdvanced

Implement your own data provider for full control. Connect to your own backend, proprietary data feeds, or any third-party API.

DataProvider Interface

Your provider must implement these methods:

  • getBars(symbol, timeframe, from, to) — Fetch historical OHLCV data
  • subscribe(symbol, timeframe, onBar) — Start real-time updates
  • unsubscribe() — Cleanup streaming connection
javascript
1// Custom data provider implementation
2const myDataProvider = {
3  // Fetch historical bars
4  getBars: async (symbol, timeframe, from, to) => {
5    const response = await fetch(
6      `/api/bars?symbol=${symbol}&tf=${timeframe}&from=${from}&to=${to}`
7    );
8    const data = await response.json();
9    
10    // Return array of Bar objects
11    return data.map(bar => ({
12      timestamp: new Date(bar.time).getTime(),
13      open: bar.o,
14      high: bar.h,
15      low: bar.l,
16      close: bar.c,
17      volume: bar.v
18    }));
19  },
20  
21  // Subscribe to real-time updates
22  subscribe: (symbol, timeframe, onBar) => {
23    const ws = new WebSocket(`wss://your-api.com/stream?symbol=${symbol}`);
24    
25    ws.onmessage = (event) => {
26      const bar = JSON.parse(event.data);
27      onBar({
28        timestamp: bar.timestamp,
29        open: bar.open,
30        high: bar.high,
31        low: bar.low,
32        close: bar.close,
33        volume: bar.volume
34      });
35    };
36    
37    // Store reference for cleanup
38    this._ws = ws;
39  },
40  
41  // Cleanup
42  unsubscribe: () => {
43    if (this._ws) {
44      this._ws.close();
45      this._ws = null;
46    }
47  }
48};
49
50// Use your custom provider
51const chart = new StockChartWidget({
52  ticker: 'CUSTOM_SYMBOL',
53  dataProvider: myDataProvider,
54  licenseKey: 'YOUR_TICKERFLOW_KEY'
55});