Mở đầu: Khi đối thủ đã có dữ liệu 3 tháng, bạn mới bắt đầu cào

Tôi vẫn nhớ rõ buổi sáng tháng 3/2024, khi team quant của mình nhận được thông báo từ khách hàng: "Đối thủ của chúng tôi vừa backtest chiến lược arbitrage với độ trễ chỉ 2ms, họ có data từ tháng 1." Trong khi đó, dự án của chúng tôi mới triển khai hệ thống thu thập dữ liệu Hyperliquid được 2 tuần — và mới chỉ có đúng 14 ngày dữ liệu.

Vấn đề không nằm ở công nghệ hay chiến lược giao dịch. Đó là chiến tranh dữ liệu: ai sở hữu lịch sử order book dài hơn, người đó có lợi thế backtest và tối ưu hóa chiến lược vượt trội.

Hyperliquid là một trong những Layer 2 perp DEX tăng trưởng nóng nhất 2024 với khối lượng giao dịch hàng tỷ USD mỗi ngày. Tuy nhiên, việc lấy historical order book data từ Hyperliquid không hề đơn giản như Binance hay Coinbase. Đây là lý do tôi viết bài hướng dẫn này — tổng hợp toàn bộ giải pháp đã được thực chiến trong hơn 6 tháng.

Hyperliquid và Tardis: Tại sao cần kết hợp cả hai?

Tại sao không lấy trực tiếp từ Hyperliquid?

Hyperliquid cung cấp WebSocket API miễn phí cho dữ liệu realtime. Nhưng đây là những hạn chế nghiêm trọng:

Tại sao chọn Tardis.dev?

Tardis (tardis.dev) là dịch vụ cung cấp normalized historical market data từ hơn 50 sàn giao dịch, bao gồm cả Hyperliquid.Ưu điểm nổi bật:

Cài đặt môi trường và dependencies

Trước khi bắt đầu, đảm bảo bạn đã cài đặt Node.js 18+ và npm/yarn. Tôi sử dụng TypeScript để đảm bảo type safety trong production environment.

# Khởi tạo project
mkdir hyperliquid-tardis && cd hyperliquid-tardis
npm init -y

Cài đặt dependencies

npm install axios dotenv

Cài đặt dev dependencies cho TypeScript

npm install -D typescript @types/node @types/axios ts-node

Khởi tạo TypeScript config

npx tsc --init

API Credentials Setup

# .env file - Lưu ý: Không commit file này lên git!
TARDIS_API_KEY=your_tardis_api_key_here

Tardis Free tier: 100,000 credits/tháng, đủ cho 1 project demo

Tardis Pro: $49/tháng cho 5 triệu credits

Hyperliquid WebSocket endpoint (miễn phí, không cần API key)

HYPERLIQUID_WS_URL=wss://stream.hyperliquid.xyz/info

Phần 1: Lấy Historical Order Book từ Tardis

Đây là cách tôi thường xuyên lấy order book data cho các dự án backtesting. Tardis cung cấp endpoint chuyên biệt cho order book với độ chi tiết cao.

import axios from 'axios';
import * as dotenv from 'dotenv';

dotenv.config();

// Tardis API Configuration
const TARDIS_BASE_URL = 'https://api.tardis.dev/v1';
const API_KEY = process.env.TARDIS_API_KEY;

// Hyperliquid perpetual markets mapping
const HYPERLIQUID_MARKETS = {
  'BTC-PERP': 'HYPE:BTC-PERP',
  'ETH-PERP': 'HYPE:ETH-PERP',
  'SOL-PERP': 'HYPE:SOL-PERP',
  'ARBITRUM-PERP': 'HYPE:ARB-PERP',
};

// Type definitions cho order book data
interface OrderBookLevel {
  price: number;
  size: number;
  count?: number;
}

interface OrderBookSnapshot {
  exchange: string;
  symbol: string;
  timestamp: number;
  asks: OrderBookLevel[];
  bids: OrderBookLevel[];
  localTimestamp: number;
}

interface TardisOrderBookResponse {
  data: OrderBookSnapshot[];
  hasMore: boolean;
  nextCursor: string | null;
}

/**
 * Lấy historical order book snapshot từ Tardis
 * @param symbol - Symbol theo định dạng Tardis (vd: HYPE:BTC-PERP)
 * @param from - Start timestamp (ms)
 * @param to - End timestamp (ms)
 * @param limit - Số lượng snapshots (max 1000/request)
 */
async function getHistoricalOrderBook(
  symbol: string,
  from: number,
  to: number,
  limit: number = 100
): Promise<TardisOrderBookResponse> {
  try {
    const response = await axios.get(${TARDIS_BASE_URL}/orderbook-snapshots, {
      params: {
        exchange: 'hyperliquid',
        symbol: symbol,
        from: from,
        to: to,
        limit: limit,
      },
      headers: {
        'Authorization': Bearer ${API_KEY},
        'Content-Type': 'application/json',
      },
    });

    return response.data;
  } catch (error) {
    if (axios.isAxiosError(error)) {
      console.error(Tardis API Error [${error.response?.status}]:, error.response?.data);
      throw new Error(Failed to fetch order book: ${error.message});
    }
    throw error;
  }
}

// Ví dụ: Lấy order book BTC-PERP trong 1 giờ
async function fetchBTCOrderBookExample() {
  const now = Date.now();
  const oneHourAgo = now - 60 * 60 * 1000; // 1 giờ trước

  console.log('Fetching BTC-PERP order book from Tardis...');
  console.log(Time range: ${new Date(oneHourAgo).toISOString()} to ${new Date(now).toISOString()});

  const result = await getHistoricalOrderBook(
    HYPERLIQUID_MARKETS['BTC-PERP'],
    oneHourAgo,
    now,
    100
  );

  console.log(\nFetched ${result.data.length} order book snapshots);
  console.log(Has more data: ${result.hasMore});

  if (result.data.length > 0) {
    const firstSnapshot = result.data[0];
    console.log('\nSample snapshot:');
    console.log(  Exchange: ${firstSnapshot.exchange});
    console.log(  Symbol: ${firstSnapshot.symbol});
    console.log(  Timestamp: ${new Date(firstSnapshot.timestamp).toISOString()});
    console.log(  Top 3 Asks:, firstSnapshot.asks.slice(0, 3));
    console.log(  Top 3 Bids:, firstSnapshot.bids.slice(0, 3));
    console.log(  Spread: ${(firstSnapshot.asks[0].price - firstSnapshot.bids[0].price).toFixed(2)});
  }

  return result;
}

// Chạy ví dụ
// fetchBTCOrderBookExample();

Phần 2: Lấy Historical Trades với Candlestick Aggregation

Đối với chiến lược mean reversion hoặc momentum, tôi cần OHLCV data. Tardis cung cấp endpoint chuyên cho aggregation từ raw trades.

import axios from 'axios';

// Tardis Aggregation API
const TARDIS_AGG_BASE_URL = 'https://api.tardis.dev/v1/agg';

interface Trade {
  id: string;
  price: number;
  size: number;
  side: 'buy' | 'sell';
  timestamp: number;
  tradeAttributes?: Record<string, any>;
}

interface OHLCV {
  timestamp: number;
  open: number;
  high: number;
  low: number;
  close: number;
  volume: number;
}

/**
 * Lấy OHLCV data (candlestick) từ Tardis
 * @param symbol - Symbol format: exchange:symbol
 * @param interval - Timeframe: '1m', '5m', '15m', '1h', '4h', '1d'
 * @param from - Start timestamp (ms)
 * @param to - End timestamp (ms)
 */
async function getOHLCV(
  symbol: string,
  interval: string,
  from: number,
  to: number
): Promise<OHLCV[]> {
  const response = await axios.get(${TARDIS_AGG_BASE_URL}/candles, {
    params: {
      exchange: 'hyperliquid',
      symbol: symbol.split(':')[1], // Remove exchange prefix
      interval: interval,
      from: from,
      to: to,
    },
    headers: {
      'Authorization': Bearer ${process.env.TARDIS_API_KEY},
    },
  });

  return response.data.map((candle: any) => ({
    timestamp: candle.timestamp,
    open: parseFloat(candle.open),
    high: parseFloat(candle.high),
    low: parseFloat(candle.low),
    close: parseFloat(candle.close),
    volume: parseFloat(candle.volume),
  }));
}

/**
 * Tính toán order book imbalance từ snapshots
 * @param asks Array of ask levels
 * @param bids Array of bid levels
 * @param depth Số lượng levels để tính (default: 10)
 */
function calculateOrderBookImbalance(
  asks: OrderBookLevel[],
  bids: OrderBookLevel[],
  depth: number = 10
): number {
  const askDepth = asks.slice(0, depth)
    .reduce((sum, level) => sum + level.size, 0);
  
  const bidDepth = bids.slice(0, depth)
    .reduce((sum, level) => sum + level.size, 0);
  
  const total = askDepth + bidDepth;
  
  if (total === 0) return 0;
  
  // Positive = more bids (bullish), Negative = more asks (bearish)
  return (bidDepth - askDepth) / total;
}

/**
 * Phân tích volatility từ OHLCV data
 * @param candles OHLCV array
 * @param window Rolling window size
 */
function analyzeVolatility(candles: OHLCV[], window: number = 20): {
  avgRange: number;
  currentRange: number;
  volatilityRatio: number;
} {
  const ranges = candles.map(c => c.high - c.low);
  
  const windowRanges = ranges.slice(-window);
  const avgRange = windowRanges.reduce((a, b) => a + b, 0) / windowRanges.length;
  const currentRange = ranges[ranges.length - 1] || 0;
  
  return {
    avgRange,
    currentRange,
    volatilityRatio: currentRange / avgRange,
  };
}

// Ví dụ sử dụng
async function tradingAnalysisExample() {
  const now = Date.now();
  const oneDayAgo = now - 24 * 60 * 60 * 1000;

  // Lấy 1 ngày data 15 phút
  const candles = await getOHLCV('HYPE:BTC-PERP', '15m', oneDayAgo, now);
  
  console.log(Fetched ${candles.length} candles);
  
  // Phân tích volatility
  const volAnalysis = analyzeVolatility(candles);
  console.log('\nVolatility Analysis:');
  console.log(  Average Range: ${volAnalysis.avgRange.toFixed(2)});
  console.log(  Current Range: ${volAnalysis.currentRange.toFixed(2)});
  console.log(  Volatility Ratio: ${volAnalysis.volatilityRatio.toFixed(2)}x);

  // Tính momentum
  const recentCandles = candles.slice(-4); // Last hour
  const momentum = recentCandles.reduce((sum, c) => sum + (c.close - c.open), 0);
  console.log(\n1h Momentum: ${momentum > 0 ? '+' : ''}${momentum.toFixed(2)});

  return { candles, volAnalysis, momentum };
}

Phần 3: Kết hợp với AI cho Signal Generation

Đây là phần tôi sử dụng HolySheep AI để xử lý order book data và generate trading signals. Với chi phí chỉ $0.42/1M tokens cho DeepSeek V3.2, việc phân tích hàng triệu order book snapshots trở nên kinh tế hơn rất nhiều so với việc dùng GPT-4.1 ($8/1M tokens).

import axios from 'axios';
import * as fs from 'fs';

// HolySheep AI API - Tiết kiệm 85%+ so với OpenAI
const HOLYSHEEP_BASE_URL = 'https://api.holysheep.ai/v1';
const HOLYSHEEP_API_KEY = process.env.HOLYSHEEP_API_KEY;

interface TradingSignal {
  action: 'long' | 'short' | 'neutral';
  confidence: number;
  reasoning: string;
  keyLevels: {
    support: number[];
    resistance: number[];
  };
  riskReward: number;
}

/**
 * Phân tích order book data với AI để generate signal
 * Sử dụng HolySheep AI - chi phí chỉ $0.42/1M tokens với DeepSeek V3.2
 */
async function analyzeWithAI(
  symbol: string,
  orderBook: OrderBookSnapshot,
  recentTrades: Trade[]
): Promise<TradingSignal> {
  // Chuẩn bị context cho AI
  const topAsks = orderBook.asks.slice(0, 5);
  const topBids = orderBook.bids.slice(0, 5);
  const midPrice = (orderBook.asks[0].price + orderBook.bids[0].price) / 2;
  
  const bidVolume = topBids.reduce((sum, l) => sum + l.size, 0);
  const askVolume = topAsks.reduce((sum, l) => sum + l.size, 0);
  const imbalance = (bidVolume - askVolume) / (bidVolume + askVolume);
  
  // Recent trades summary
  const buyVolume = recentTrades
    .filter(t => t.side === 'buy')
    .reduce((sum, t) => sum + t.size, 0);
  const sellVolume = recentTrades
    .filter(t => t.side === 'sell')
    .reduce((sum, t) => sum + t.size, 0);
  const tradeImbalance = (buyVolume - sellVolume) / (buyVolume + sellVolume);

  const prompt = `Bạn là chuyên gia phân tích kỹ thuật DeFi. Phân tích data sau và đưa ra trading signal:

Symbol: ${symbol}
Mid Price: $${midPrice.toFixed(2)}
Timestamp: ${new Date(orderBook.timestamp).toISOString()}

Top 5 Asks (price, size):
${topAsks.map(a =>   $${a.price} x ${a.size}).join('\n')}

Top 5 Bids (price, size):
${topBids.map(b =>   $${b.price} x ${b.size}).join('\n')}

Order Book Imbalance: ${imbalance.toFixed(4)} (positive = more bids)
Trade Imbalance: ${tradeImbalance.toFixed(4)} (positive = more buys)

Hãy phản hồi JSON format:
{
  "action": "long|short|neutral",
  "confidence": 0.0-1.0,
  "reasoning": "giải thích ngắn",
  "keyLevels": {"support": [], "resistance": []},
  "riskReward": số
}`;

  try {
    // Sử dụng HolySheep AI với DeepSeek V3.2 - chi phí thấp nhất
    const response = await axios.post(
      ${HOLYSHEEP_BASE_URL}/chat/completions,
      {
        model: 'deepseek-chat',
        messages: [
          {
            role: 'system',
            content: 'Bạn là chuyên gia phân tích market data. Chỉ phản hồi JSON valid.'
          },
          {
            role: 'user',
            content: prompt
          }
        ],
        temperature: 0.3,
        max_tokens: 500,
      },
      {
        headers: {
          'Authorization': Bearer ${HOLYSHEEP_API_KEY},
          'Content-Type': 'application/json',
        },
      }
    );

    const content = response.data.choices[0].message.content;
    const usage = response.data.usage;

    console.log(\nAI Analysis (${usage.total_tokens} tokens used):);
    console.log(  Cost: $${(usage.total_tokens / 1_000_000 * 0.42).toFixed(4)});

    return JSON.parse(content);
  } catch (error) {
    console.error('AI Analysis Error:', error);
    return {
      action: 'neutral',
      confidence: 0,
      reasoning: 'AI analysis failed',
      keyLevels: { support: [], resistance: [] },
      riskReward: 0,
    };
  }
}

/**
 * Lưu data vào file để backtest sau
 */
function saveToFile(filename: string, data: any) {
  fs.writeFileSync(filename, JSON.stringify(data, null, 2));
  console.log(Data saved to ${filename});
}

// Ví dụ: Chạy analysis pipeline
async function runAnalysisPipeline() {
  // Lấy data từ Tardis (sử dụng functions từ phần trước)
  const now = Date.now();
  const oneMinuteAgo = now - 60 * 1000;

  const orderBooks = await getHistoricalOrderBook(
    'HYPE:BTC-PERP',
    oneMinuteAgo,
    now,
    1
  );

  if (orderBooks.data.length === 0) {
    console.log('No order book data available');
    return;
  }

  const latestOrderBook = orderBooks.data[0];
  
  // Mock recent trades (trong thực tế lấy từ Tardis trades API)
  const recentTrades: Trade[] = [
    { id: '1', price: latestOrderBook.asks[0].price, size: 0.5, side: 'buy', timestamp: now - 1000 },
    { id: '2', price: latestOrderBook.bids[0].price, size: 0.3, side: 'sell', timestamp: now - 500 },
  ];

  // Phân tích với AI
  const signal = await analyzeWithAI('BTC-PERP', latestOrderBook, recentTrades);
  
  console.log('\nTrading Signal:');
  console.log(JSON.stringify(signal, null, 2));

  // Lưu kết quả
  saveToFile('signal-output.json', {
    timestamp: now,
    orderBook: latestOrderBook,
    signal: signal,
  });

  return signal;
}

Chi phí thực tế và Performance Benchmark

Qua 6 tháng sử dụng thực tế, đây là breakdown chi phí và performance của hệ thống:

So sánh chi phí AI APIs (2026)

Dịch vụ Model Giá/1M tokens Latency trung bình Đánh giá
HolySheep AI DeepSeek V3.2 $0.42 <50ms ⭐⭐⭐⭐⭐ Tiết kiệm 85%+
OpenAI GPT-4.1 $8.00 ~200ms ⭐⭐ Đắt cho production
Anthropic Claude Sonnet 4.5 $15.00 ~180ms ⭐⭐ Quá đắt
Google Gemini 2.5 Flash $2.50 ~100ms ⭐⭐⭐ Cân bằng

Tardis API Usage thực tế

Loại data Credits/1K records Free tier/month Pro tier ($49/tháng)
Order Book Snapshots 10 credits 10 triệu records 500 triệu records
Trades 1 credit 100 triệu records 5 tỷ records
OHLCV Candles 0.5 credits 200 triệu records 10 tỷ records

Lỗi thường gặp và cách khắc phục

Lỗi 1: Tardis API 403 Forbidden - Invalid API Key

// ❌ Sai: Key không đúng format hoặc hết hạn
const API_KEY = 'my-api-key'; // Lỗi: Thiếu Bearer prefix trong header

// ✅ Đúng: Kiểm tra và validate API key
async function validateTardisKey(apiKey: string): Promise<boolean> {
  try {
    const response = await axios.get(${TARDIS_BASE_URL}/user/credits, {
      headers: {
        'Authorization': Bearer ${apiKey},
      },
    });
    
    console.log(Credits remaining: ${response.data.credits});
    return true;
  } catch (error) {
    if (axios.isAxiosError(error)) {
      if (error.response?.status === 403) {
        console.error('Lỗi: API key không hợp lệ hoặc đã hết hạn');
        console.error('Giải pháp: Kiểm tra API key tại https://docs.tardis.dev/api');
      } else if (error.response?.status === 401) {
        console.error('Lỗi: Chưa đăng nhập hoặc key không đúng');
      }
    }
    return false;
  }
}

Lỗi 2: Order Book Data Trống - Exchange Not Supported

// ❌ Sai: Symbol format không đúng cho Hyperliquid
const symbol = 'BTCUSDT'; // Lỗi: Format sai cho Tardis

// ✅ Đúng: Format phải là exchange:symbol
const CORRECT_SYMBOLS = {
  'hyperliquid': {
    'BTC-PERP': 'HYPE:BTC-PERP',
    'ETH-PERP': 'HYPE:ETH-PERP',
    'SOL-PERP': 'HYPE:SOL-PERP',
  }
};

// Function kiểm tra exchange support trước khi request
async function checkExchangeSupport(exchange: string): Promise<boolean> {
  try {
    const response = await axios.get(${TARDIS_BASE_URL}/exchanges, {
      headers: {
        'Authorization': Bearer ${API_KEY},
      },
    });
    
    const supportedExchanges = response.data.map((e: any) => e.code);
    const isSupported = supportedExchanges.includes(exchange.toLowerCase());
    
    if (!isSupported) {
      console.error(Exchange "${exchange}" không được hỗ trợ.);
      console.error('Danh sách supported:', supportedExchanges.join(', '));
    }
    
    return isSupported;
  } catch (error) {
    console.error('Không thể kiểm tra exchange support:', error);
    return false;
  }
}

// Wrapper function an toàn cho order book fetch
async function safeGetOrderBook(symbol: string, from: number, to: number) {
  // Kiểm tra format
  if (!symbol.includes(':')) {
    console.error(Symbol "${symbol}" phải format: "exchange:symbol" (vd: "HYPE:BTC-PERP"));
    return null;
  }
  
  const [exchange] = symbol.split(':');
  
  // Kiểm tra support
  const isSupported = await checkExchangeSupport(exchange);
  if (!isSupported) {
    return null;
  }
  
  return getHistoricalOrderBook(symbol, from, to);
}

Lỗi 3: WebSocket Disconnect - Mất kết nối realtime

// ❌ Sai: Không handle reconnect, mất data khi disconnect
const ws = new WebSocket(HYPERLIQUID_WS_URL);
ws.onmessage = (event) => {
  processOrderBook(event.data);
};
// Lỗi tiềm ẩn: Khi mất kết nối, không reconnect được

// ✅ Đúng: Implement reconnection logic với exponential backoff
class HyperliquidWebSocket {
  private ws: WebSocket | null = null;
  private reconnectAttempts = 0;
  private maxReconnectAttempts = 10;
  private reconnectDelay = 1000;
  private subscriptions: Set<string> = new Set();

  constructor(
    private url: string,
    private onMessage: (data: any) => void,
    private onError: (error: Error) => void
  ) {
    this.connect();
  }

  private connect() {
    try {
      this.ws = new WebSocket(this.url);

      this.ws.onopen = () => {
        console.log('WebSocket Connected');
        this.reconnectAttempts = 0;
        this.reconnectDelay = 1000;
        
        // Resubscribe all previous subscriptions
        this.subscriptions.forEach(sub => {
          this.sendSubscribe(sub);
        });
      };

      this.ws.onmessage = (event) => {
        try {
          const data = JSON.parse(event.data);
          this.onMessage(data);
        } catch (e) {
          console.error('Parse error:', e);
        }
      };

      this.ws.onerror = (error) => {
        this.onError(new Error('WebSocket error'));
        console.error('WebSocket Error:', error);
      };

      this.ws.onclose = () => {
        console.log('WebSocket Closed');
        this.scheduleReconnect();
      };
    } catch (error) {
      console.error('Connection failed:', error);
      this.scheduleReconnect();
    }
  }

  private scheduleReconnect() {
    if (this.reconnectAttempts >= this.maxReconnectAttempts) {
      console.error('Max reconnect attempts reached. Giving up.');
      return;
    }

    this.reconnectAttempts++;
    const delay = Math.min(
      this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1),
      30000 // Max 30 seconds
    );

    console.log(Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}));
    setTimeout(() => this.connect(), delay);
  }

  subscribe(channel: string, symbol: string) {
    this.subscriptions.add(${channel}:${symbol});
    
    if (this.ws?.readyState === WebSocket.OPEN) {
      this.sendSubscribe(${channel}:${symbol});
    }
  }

  private sendSubscribe(channel: string) {
    this.ws?.send(JSON.stringify({
      method: 'subscribe',
      subscription: { type: channel },
    }));
  }

  disconnect() {
    this.maxReconnectAttempts = 0; // Prevent reconnect
    this.ws?.close();
  }
}

// Sử dụng
const ws = new HyperliquidWebSocket(
  'wss://stream.hyperliquid.xyz/info',
  (data) => console.log('Received:', data),
  (error) => console.error('Error:', error)
);

ws.subscribe('book', 'BTC-PERP');

Lỗi 4: Memory Leak khi xử lý volume lớn

// ❌ Sai: Buffer không giới hạn, gây memory leak
const allData: any[] = [];

async function fetchAllData() {
  while (hasMore) {
    const chunk = await fetchChunk(nextCursor);
    allData.push(...chunk.data); // Lỗi: Mảng grow vô hạn
  }
}

// ✅ Đúng: Streaming processing với batch size giới hạn
async function* streamOrderBookData(
  symbol: string,
  from: number,
  to: number,
  batchSize: number = 100
) {
  let cursor: string | null = null;
  let hasMore = true;

  while (hasMore) {
    const response = await getHistoricalOrderBook(
      symbol,
      from,
      to,
      batchSize
    );

    yield response.data;

    hasMore = response.hasMore;
    cursor = response.nextCursor;
    
    // Respect rate limits - Tardis cho phép 10 requests/second
    await new Promise(resolve => setTimeout(resolve, 100));
  }
}

// Sử dụng với streaming để tránh memory leak
async function processLargeDataset() {
  let processedCount = 0;
  const startTime = Date.now();

  for await (const batch of streamOrderBookData(
    'HYPE:BTC-PERP',
    Date.now() - 7 * 24 * 60 * 60 * 1000, // 7 days
    Date.now(),
    500 // 500 records per batch
  )) {
    // Process batch
    for (const snapshot of batch) {
      // Analyze snapshot
      analyzeOrderBookSnapshot(snapshot);
      processedCount++;
    }

    console.log(Processed ${processedCount} records...);
    
    // Log memory usage
    const memUsage = process.memoryUsage();
    console.log(Memory: ${(memUsage.heapUsed / 1024 / 1024).toFixed(2)} MB);
  }

  console.log(\nTotal: ${processedCount} records in ${Date.now() - startTime}ms);
}

Best Practices từ kinh nghiệm thực chiến

Tài nguyên liên quan

Bài viết liên quan