Skip to main content

Overview

VibeTrader supports multiple data sources for fetching market data. Currently, the platform integrates with Binance for cryptocurrency data and Yahoo Finance for stocks, indices, and other traditional financial instruments.

Supported Data Sources

Yahoo Finance

Access stocks, ETFs, indices, commodities, and currencies from global markets.

Binance

Real-time and historical cryptocurrency trading data with high precision.

Data Source Selection

The platform uses an enum-based system for selecting data sources:
enum Source {
    yfinance,  // Yahoo Finance
    binance    // Binance
}
The data source is typically selected during chart initialization based on the symbol type or user preference.

Binance Data Source

Overview

Binance integration provides access to cryptocurrency market data through the Binance API, powered by the PineTS provider.

Features

Fetch the latest candlestick data with minimal delay.
Access extensive historical data for backtesting and analysis.
Support for various timeframes from 1-minute to monthly charts.

Fetching Binance Data

const source = Source.binance
const ticker = "BTCUSDT"  // Bitcoin to USDT pair
const tframe = TFrame.parse("1h")  // 1-hour timeframe
const tzone = "UTC"
const limit = 500  // Number of candles to fetch

await fetchData(source, baseSer, ticker, tframe, tzone, undefined, limit)

Data Structure

Binance returns kline (candlestick) data with these fields:
openTime
number
Candle open time in milliseconds (Unix timestamp)
open
number
Opening price
high
number
Highest price during the period
low
number
Lowest price during the period
close
number
Closing price
volume
number
Trading volume during the period
closeTime
number
Candle close time in milliseconds

Symbol List

Fetch available Binance trading pairs:
const symbols = await fetchSymbolList(
  Source.binance,
  "BTC",  // Filter text (shows pairs containing "BTC")
  init    // RequestInit object
)
// Returns: [{ ticker: "BTCUSDT" }, { ticker: "BTCETH" }, ...]
Use the filter parameter to narrow down results when searching for specific trading pairs.

Yahoo Finance Data Source

Overview

Yahoo Finance integration provides access to a vast array of financial instruments including stocks, ETFs, indices, commodities, currencies, and more.

Features

Access data from stock exchanges worldwide.
Stocks, ETFs, indices, forex, commodities, and cryptocurrencies.
Extensive historical data going back many years.
Corporate actions (splits, dividends) are reflected in the data.

Fetching Yahoo Finance Data

const source = Source.yfinance
const ticker = "AAPL"  // Apple Inc.
const tframe = TFrame.parse("1D")  // Daily timeframe
const tzone = "America/New_York"
const limit = 300  // Number of periods to fetch

await fetchData(source, baseSer, ticker, tframe, tzone, undefined, limit)

Time Handling

Yahoo Finance API requires Unix timestamps in seconds, not milliseconds. The VibeTrader implementation automatically converts:
startTime = Math.floor(startTime / 1000)  // Convert ms to seconds
endTime = Math.floor(Date.now() / 1000)

Symbol Examples

"AAPL"   // Apple Inc.
"MSFT"   // Microsoft
"GOOGL"  // Alphabet (Google)
"TSLA"   // Tesla
const symbols = await fetchSymbolList(
  Source.yfinance,
  "AAPL",  // Search query
  init
)

Unified Data Fetching

The fetchData function provides a unified interface for both data sources:

Function Signature

fetchData(
  source: Source,        // yfinance or binance
  baseSer: TSer,        // Time series object to populate
  ticker: string,       // Symbol/ticker to fetch
  tframe: TFrame,       // Timeframe (1m, 5m, 1h, 1D, etc.)
  tzone: string,        // Timezone (e.g., "UTC", "America/New_York")
  startTime?: number,   // Optional start time (milliseconds)
  limit?: number        // Optional limit on number of candles
): Promise<number>      // Returns latest candle timestamp

Parameters

source
Source
required
The data source to use (Source.yfinance or Source.binance)
baseSer
TSer
required
The time series object where data will be stored
ticker
string
required
The symbol/ticker identifier for the instrument
tframe
TFrame
required
The timeframe for the data (e.g., TFrame.parse("1h") for hourly)
tzone
string
required
The timezone for timestamp interpretation
startTime
number
Optional start time in milliseconds. If not provided, calculated based on limit
limit
number
Optional maximum number of candles to fetch. Default varies by implementation

Return Value

Returns a Promise<number> containing the timestamp of the most recent candle, or undefined if no data was fetched.

Timeframe Support

Common Timeframes

  • 1m - 1 minute
  • 5m - 5 minutes
  • 15m - 15 minutes
  • 30m - 30 minutes
  • 1h - 1 hour
  • 4h - 4 hours

Timeframe Conversion

Binance uses PineTS provider timeframe notation. The implementation handles automatic conversion:
const pinets_tframe = Binance.timeframe_to_pinetsProvider[tframe.shortName] 
  || tframe.shortName

Data Processing

Automatic Deduplication

Both data sources implement automatic deduplication:
// Sort by time to ensure chronological order
binanceKline.sort((a, b) => a.openTime - b.openTime)

// Remove duplicates based on openTime
const uniqueKlines = binanceKline.filter(
  (kline, index, self) => 
    index === self.findIndex((k) => k.openTime === kline.openTime)
)

Kline Object Creation

Data from both sources is converted to a unified Kline object:
const kline = new Kline(
  openTime,   // Open time
  open,       // Open price
  high,       // High price
  low,        // Low price
  close,      // Close price
  volume,     // Volume
  openTime,   // Begin time (same as openTime)
  closeTime,  // End time
  true        // Is occurred (data exists)
)

baseSer.addToVar(KVAR_NAME, kline)

Fallback Mechanism

If API fetching fails, the system falls back to local data:
// If API returns undefined, try loading local klines.json
return fetch("./klines.json")
  .then(r => r.json())
  .then(json => {
    for (const k of json) {
      const time = Date.parse(k.Date)
      const kline = new Kline(time, k.Open, k.High, k.Low, k.Close, k.Volume, time, time, true)
      baseSer.addToVar(KVAR_NAME, kline)
    }
  })
Local data should be in JSON format with fields: Date, Open, High, Low, Close, Volume

Time Range Calculation

When startTime is not provided, it’s calculated based on limit:
const endTime = new Date().getTime()
const backLimitTime = tframe.timeBeforeNTimeframes(endTime, limit, tzone)
startTime = startTime || backLimitTime
This ensures you get the most recent limit number of candles.

Error Handling

If the API request fails due to network issues, the promise rejects and should be caught by your error handler.
Invalid symbols may return empty data or error responses. Always validate symbol format before fetching.
Both APIs have rate limits. Implement request throttling for production use.
Some symbols or timeframes may not have complete historical data. Handle cases where fewer candles than requested are returned.

Best Practices

Cache Data

Cache fetched data locally to reduce API calls and improve load times.

Use Appropriate Limits

Request only the data you need. Smaller limits mean faster responses.

Handle Timezones

Always specify the correct timezone for your symbols to ensure accurate timestamps.

Validate Symbols

Use symbol search to validate symbols before fetching data.

Example: Complete Data Fetching Flow

import { fetchData, Source } from './lib/domain/DataFecther'
import { TFrame } from './lib/timeseris/TFrame'
import { TSer } from './lib/timeseris/TSer'

// Initialize time series
const baseSer = new TSer()

// Configure request
const source = Source.binance
const ticker = "ETHUSDT"
const tframe = TFrame.parse("1h")
const tzone = "UTC"
const limit = 500

try {
  // Fetch data
  const latestTime = await fetchData(
    source,
    baseSer,
    ticker,
    tframe,
    tzone,
    undefined,
    limit
  )
  
  console.log(`Fetched ${baseSer.size()} candles`)
  console.log(`Latest candle time: ${new Date(latestTime)}`)
  
  // Now baseSer contains all the kline data
  // Ready to display on charts
  
} catch (error) {
  console.error('Failed to fetch data:', error)
  // Handle error appropriately
}
For real-time updates, implement periodic refetching with a timestamp-based approach to only fetch new candles since the last update.

Build docs developers (and LLMs) love