Skip to main content

Market Data (Candles)

JT-LIB provides a powerful system for working with market data, including historical candle retrieval, data buffering, and market analysis. The system is built around CandlesBuffer for efficient data management and getHistory for historical data retrieval.

Getting Candles - Historical Data

getHistory Function

getHistory is the main function for retrieving historical candle data.

getHistory(symbol: string, timeframe: TimeFrame, startTime: number, limit?: number): Promise<OHLC[]>

Parameters:

  • symbol — trading symbol (e.g., 'BTC/USDT')
  • timeframe — candle timeframe ('1m', '5m', '15m', '1h', '4h', '1d', '1w', '1M')
  • startTime — start time in milliseconds
  • limit — number of candles (default: maximum available)

Returns: Array of candles in format [timestamp, open, high, low, close, volume]

Usage Examples

// Get last 100 candles for 1 hour
const timeFrom = tms() - 1000 * 60 * 60 * 24 * 7; // 7 days ago
const candles = await getHistory('BTC/USDT', '1h', timeFrom, 100);

// Get daily candles for last month
const monthAgo = Date.now() - 30 * 24 * 60 * 60 * 1000;
const dailyCandles = await getHistory('ETH/USDT', '1d', monthAgo, 30);

// Get minute candles for analysis
const minuteCandles = await getHistory('BTC/USDT', '1m', Date.now() - 60 * 60 * 1000, 60);

Candle Data Format

// Each candle is represented as an array:
type OHLC = [number, number, number, number, number, number];
// [timestamp, open, high, low, close, volume]

// Example:
const candle = [1614556800000, 50000, 51000, 49000, 50500, 1000];
// timestamp: 1614556800000 (candle open time)
// open: 50000 (open price)
// high: 51000 (maximum price)
// low: 49000 (minimum price)
// close: 50500 (close price)
// volume: 1000 (trading volume)

CandlesBuffer - Data Buffering

CandlesBuffer is a class for efficient candle buffer management with automatic updates. In JT-LIB, buffers are managed through the global CandlesBufferService, which prevents creating duplicate buffers for the same symbol and timeframe combinations.

Key Features

  • Global Caching — one buffer per symbol+timeframe combination
  • Automatic Updates — subscription to onTick events for data updates
  • Data Preloading — automatic historical data loading on initialization
  • Buffer Size Management — limiting maximum buffer size
  • OHLC Data Access — methods for getting open, high, low, close, volume

Getting Buffer Through Global Service

// Get buffer through global service (recommended way)
const buffer = await globals.candlesBufferService.getBuffer({
symbol: 'BTC/USDT',
timeframe: '1h',
preloadCandlesCount: 250, // number of candles to preload
maxBufferLength: 1000 // maximum buffer size
});

// Buffer is automatically initialized and cached
// On repeated request with same parameters, existing buffer is returned

CandlesBufferOptions Parameters

interface CandlesBufferOptions {
symbol: string; // trading symbol
timeframe: string | number; // timeframe
preloadCandlesCount?: number; // number of candles to preload (default: 250)
maxBufferLength?: number; // maximum buffer size (default: 1000)
}

How Caching Works

The CandlesBufferService creates a unique key for each buffer: ${symbol}-${timeframe}. On first request, a new buffer is created; on repeated requests with the same parameters, the existing buffer is returned.

CandlesBuffer Methods

// Get all candles
const candles = buffer.getCandles();

// Get specific candle (shift = 0 - last candle)
const lastCandle = buffer.getCandle(0);
const prevCandle = buffer.getCandle(1);

// Get OHLC data of last candle
const close = buffer.close();
const high = buffer.high();
const low = buffer.low();
const open = buffer.open();
const volume = buffer.volume();
const timestamp = buffer.tms();

// Clear buffer
buffer.clear();

// Get last update time
const lastUpdate = buffer.getLastTimeUpdated();

Time Intervals - Working with Timeframes

Supported Timeframes

JT-LIB supports the following timeframes:

TimeframeMinutesDescription
'1m'11 minute
'5m'55 minutes
'15m'1515 minutes
'1h'601 hour
'4h'2404 hours
'1d'14401 day
'1w'100801 week
'1M'432001 month

Timeframe Conversion

import { convertTimeframeToString, convertTimeframeToNumber } from 'jt-lib';

// Convert to string
const tfString = convertTimeframeToString(60); // '1h'
const tfString2 = convertTimeframeToString('m60'); // '1h'

// Convert to number (minutes)
const tfNumber = convertTimeframeToNumber('1h'); // 60
const tfNumber2 = convertTimeframeToNumber('1d'); // 1440

Time Rounding by Timeframe

import { roundTimeByTimeframe } from 'jt-lib';

const timestamp = Date.now();
const roundedTime = roundTimeByTimeframe(timestamp, '1h');
// Rounds time to start of hour

Market Data Processing - How to Analyze Market

CandlesBufferService - Global Buffer Management

CandlesBufferService is a global service for managing candle buffers. The service is automatically created in BaseScript and accessible through globals.candlesBufferService.

// Get buffer through global service
const buffer = await globals.candlesBufferService.getBuffer({
symbol: 'BTC/USDT',
timeframe: '1h',
preloadCandlesCount: 500
});

// Service automatically manages buffer caching
// Buffers are created by key: `${symbol}-${timeframe}`
// On repeated request with same parameters, existing buffer is returned

Integration with Indicators

CandlesBuffer integrates with the indicator system:

import { BaseIndicator } from 'jt-lib';

class MyIndicator extends BaseIndicator {
constructor(symbol: string, timeframe: TimeFrame, buffer: CandlesBuffer) {
super(symbol, timeframe, buffer);
}

calculate() {
const candles = this.candlesBuffer.getCandles();
// Indicator calculation logic
}
}

Practical Analysis Examples

Simple Trend Analysis

class Script extends BaseScript {
private buffer: CandlesBuffer;

async onInit() {
// Get buffer through global service
this.buffer = await globals.candlesBufferService.getBuffer({
symbol: this.symbols[0],
timeframe: '1h',
preloadCandlesCount: 100
});
}

async onTick() {
const candles = this.buffer.getCandles();

if (candles.length < 20) return;

// Trend analysis on last 20 candles
const recentCandles = candles.slice(-20);
const avgHigh = recentCandles.reduce((sum, c) => sum + c.high, 0) / 20;
const avgLow = recentCandles.reduce((sum, c) => sum + c.low, 0) / 20;

const currentPrice = this.buffer.close();

if (currentPrice > avgHigh) {
log('TrendAnalysis', 'Uptrend', { currentPrice, avgHigh, avgLow }, true);
} else if (currentPrice < avgLow) {
log('TrendAnalysis', 'Downtrend', { currentPrice, avgHigh, avgLow }, true);
} else {
log('TrendAnalysis', 'Sideways movement', { currentPrice, avgHigh, avgLow }, true);
}
}
}

Volatility Analysis

class Script extends BaseScript {
private buffer: CandlesBuffer;

async onInit() {
// Get buffer through global service
this.buffer = await globals.candlesBufferService.getBuffer({
symbol: this.symbols[0],
timeframe: '4h',
preloadCandlesCount: 50
});
}

async onTick() {
const candles = this.buffer.getCandles();

if (candles.length < 10) return;

// Volatility calculation
const recentCandles = candles.slice(-10);
const volatilities = recentCandles.map(candle =>
(candle.high - candle.low) / candle.close
);

const avgVolatility = volatilities.reduce((sum, v) => sum + v, 0) / 10;

log('VolatilityAnalysis', `Average volatility: ${(avgVolatility * 100).toFixed(2)}%`, { avgVolatility }, true);

if (avgVolatility > 0.05) {
log('VolatilityAnalysis', 'High volatility', { avgVolatility }, true);
} else if (avgVolatility < 0.02) {
log('VolatilityAnalysis', 'Low volatility', { avgVolatility }, true);
}
}
}

Support and Resistance

class Script extends BaseScript {
private buffer: CandlesBuffer;

async onInit() {
// Get buffer through global service
this.buffer = await globals.candlesBufferService.getBuffer({
symbol: this.symbols[0],
timeframe: '1d',
preloadCandlesCount: 100
});
}

async onTick() {
const candles = this.buffer.getCandles();

if (candles.length < 50) return;

// Find support and resistance levels
const highs = candles.map(c => c.high);
const lows = candles.map(c => c.low);

const resistance = Math.max(...highs.slice(-20));
const support = Math.min(...lows.slice(-20));

const currentPrice = this.buffer.close();

log('SupportResistance', `Support: ${support}, Resistance: ${resistance}`, { support, resistance, currentPrice }, true);

if (currentPrice > resistance * 0.99) {
log('SupportResistance', 'Resistance breakout', { currentPrice, resistance }, true);
} else if (currentPrice < support * 1.01) {
log('SupportResistance', 'Support breakout', { currentPrice, support }, true);
}
}
}

Performance Optimization

Buffer Size Management

// For long-term analysis use large buffers
const longTermBuffer = await globals.candlesBufferService.getBuffer({
symbol: 'BTC/USDT',
timeframe: '1d',
preloadCandlesCount: 1000,
maxBufferLength: 2000
});

// For short-term analysis - smaller buffers
const shortTermBuffer = await globals.candlesBufferService.getBuffer({
symbol: 'BTC/USDT',
timeframe: '1m',
preloadCandlesCount: 100,
maxBufferLength: 500
});

Automatic Buffer Caching

class Script extends BaseScript {
private hourlyBuffer: CandlesBuffer;
private dailyBuffer: CandlesBuffer;

async onInit() {
// Buffers are automatically cached through global service
// On repeated request with same parameters, existing buffer is returned
this.hourlyBuffer = await globals.candlesBufferService.getBuffer({
symbol: this.symbols[0],
timeframe: '1h'
});

this.dailyBuffer = await globals.candlesBufferService.getBuffer({
symbol: this.symbols[0],
timeframe: '1d'
});
}
}

Integration with Other Components

BaseScript + CandlesBuffer

class Script extends BaseScript {
private buffer: CandlesBuffer;

async onInit() {
// Get buffer through global service
this.buffer = await globals.candlesBufferService.getBuffer({
symbol: this.symbols[0],
timeframe: getArgString('timeframe', '1h'),
preloadCandlesCount: getArgNumber('candlesCount', 250)
});
}

async onTick() {
// Market data analysis
const trend = this.analyzeTrend();
const volatility = this.calculateVolatility();

// Trading decisions based on analysis
if (trend === 'bullish' && volatility < 0.03) {
// Buy logic
}
}
}

OrdersBasket + Market Data

class Script extends BaseScript {
private basket: OrdersBasket;
private buffer: CandlesBuffer;

async onInit() {
this.basket = new OrdersBasket({
symbol: this.symbols[0],
connectionName: this.connectionName
});
await this.basket.init();

// Get buffer through global service
this.buffer = await globals.candlesBufferService.getBuffer({
symbol: this.symbols[0],
timeframe: '1h'
});
}

async onTick() {
const currentPrice = this.basket.close();
const bufferPrice = this.buffer.close();

// Compare data from different sources
if (Math.abs(currentPrice - bufferPrice) > currentPrice * 0.001) {
warning('PriceValidation', 'Price discrepancy between sources', { currentPrice, bufferPrice, difference: Math.abs(currentPrice - bufferPrice) });
}
}
}

Next Steps