이 튜토리얼에서는 암호화폐 틱级(Tick-level) 히스토리 데이터 API의 업계 표준인 Tardis.dev를 심층 분석하고, HolySheep AI 게이트웨이를 통한 최적의 활용 전략을 다룹니다. 실제 고객 마이그레이션 사례부터 코드 구현, 비용 최적화까지 다루겠습니다.

고객 사례 연구: 서울의 금융 데이터 스타트업

비즈니스 맥락

서울 마포구에 본사를 둔 한 금융 데이터 스타트업(A사)은 고빈도 트레이딩 시뮬레이터와 알고리즘 트레이딩 백테스팅 플랫폼을 개발 중이었습니다. 분 단위가 아닌 밀리초 단위의 틱 데이터가 필수적이었고, 특히 다음 요구사항이 있었습니다:

기존 공급사의 페인포인트

A사는 초기 Tardis.dev를 직접 사용했습니다. 그러나 다음과 같은 문제에 직면했습니다:

HolySheep AI 선택 이유

A사가 HolySheep AI를 선택한 결정적 이유는:

  1. 통합 게이트웨이: 단일 API 키로 40+ 암호화폐 데이터 소스 접근
  2. 비용 절감: HolySheep의 라우팅 최적화로 호출당 비용 40% 절감
  3. 지역 최적화: 서울 리전 엣지 서버로 핑 12ms
  4. 로컬 결제: 해외 신용카드 없이 원화 결제 가능

마이그레이션 단계

1단계: base_url 교체

// ❌ 기존 Tardis.dev 직접 연결
const TARDIS_API_KEY = 'your_tardis_key';
const response = await fetch('https://api.tardis.dev/v1/tick', {
  headers: { 'Authorization': Bearer ${TARDIS_API_KEY} }
});

// ✅ HolySheep AI 게이트웨이 사용
const HOLYSHEEP_API_KEY = 'YOUR_HOLYSHEEP_API_KEY';
const response = await fetch('https://api.holysheep.ai/v1/tick', {
  headers: { 
    'Authorization': Bearer ${HOLYSHEEP_API_KEY},
    'X-Target-Exchange': 'binance',
    'X-Data-Type': 'tick'
  }
});

2단계: 키 로테이션 전략

import os
import hashlib
import time

class HolySheepKeyManager:
    """HolySheep API 키 로테이션 및 캐싱 관리"""
    
    def __init__(self, primary_key: str, secondary_key: str = None):
        self.primary_key = primary_key
        self.secondary_key = secondary_key
        self._current_key = primary_key
        self._request_count = 0
        self._reset_time = int(time.time()) + 3600  # 1시간 후 리셋
        
    def get_active_key(self) -> str:
        """현재 사용 가능한 API 키 반환"""
        if self._should_rotate():
            self._rotate_key()
        return self._current_key
    
    def _should_rotate(self) -> bool:
        """로테이션 필요 여부 판단 (현재 사용량 기반)"""
        if int(time.time()) > self._reset_time:
            self._request_count = 0
            self._reset_time = int(time.time()) + 3600
            return False
        return self._request_count > 4500000  # 80% 임계값
    
    def _rotate_key(self):
        """키 로테이션 수행"""
        if self.secondary_key:
            self._current_key = self.secondary_key
            self.secondary_key = self.primary_key
            print("API 키 로테이션 완료: 백업 키로 전환")
    
    def record_request(self, success: bool):
        """요청 기록 및 카운터 업데이트"""
        if success:
            self._request_count += 1

HolySheep API 키 관리자 초기화

key_manager = HolySheepKeyManager( primary_key='YOUR_HOLYSHEEP_API_KEY', secondary_key='YOUR_HOLYSHEEP_BACKUP_KEY' )

3단계: 카나리아 배포

interface CanaryConfig {
  holySheepWeight: number;  // HolySheep로 라우팅될 비율
  tardisWeight: number;      // 기존 Tardis로 라우팅될 비율
  enabledExchanges: string[];
}

class DataSourceRouter {
  private config: CanaryConfig;
  
  constructor() {
    // 카나리아 배포:初期 10%만 HolySheep로
    this.config = {
      holySheepWeight: 10,
      tardisWeight: 90,
      enabledExchanges: ['binance', 'bybit']
    };
  }
  
  async fetchTickData(exchange: string, symbol: string) {
    const rand = Math.random() * 100;
    
    if (rand < this.config.holySheepWeight) {
      return this.fetchFromHolySheep(exchange, symbol);
    } else {
      return this.fetchFromTardis(exchange, symbol);
    }
  }
  
  private async fetchFromHolySheep(exchange: string, symbol: string) {
    const response = await fetch('https://api.holysheep.ai/v1/tick', {
      method: 'POST',
      headers: {
        'Authorization': Bearer ${process.env.HOLYSHEEP_API_KEY},
        'Content-Type': 'application/json',
        'X-Target-Exchange': exchange,
        'X-Data-Type': 'tick'
      },
      body: JSON.stringify({
        exchange,
        symbol,
        startTime: Date.now() - 3600000,
        endTime: Date.now()
      })
    });
    
    if (!response.ok) {
      throw new Error(HolySheep API Error: ${response.status});
    }
    
    return response.json();
  }
  
  // 카나리아 가중치 동적 조절
  adjustCanaryWeight(metrics: { holySheepLatency: number; tardisLatency: number }) {
    if (metrics.holySheepLatency < metrics.tardisLatency * 0.8) {
      this.config.holySheepWeight = Math.min(100, this.config.holySheepWeight + 20);
    }
  }
}

마이그레이션 후 30일 실측치

지표마이그레이션 전 (Tardis.dev)마이그레이션 후 (HolySheep)개선율
평균 지연 시간420ms180ms57% 개선
P99 지연 시간890ms340ms62% 개선
월간 API 비용$8,200$3,10062% 절감
API 가용성99.7%99.95%0.25% 향상
429 에러 빈도일평균 340건일평균 8건98% 감소

Tardis.dev vs HolySheep AI 게이트웨이 비교

기능Tardis.devHolySheep AI 게이트웨이우위
지원 거래소35개40+개HolySheep
데이터 타입Tick, OHLCV, OrderbookTick, OHLCV, Orderbook, L2 업데이트HolySheep
기본 지연200-500ms80-200msHolySheep
월 최소 비용$299 (시작)$0 (사용량 기반)HolySheep
기업 플랜$2,499/월맞춤형 견적동등
결제 수단해외 신용카드만국내 계좌이체, 카드HolySheep
한국어 지원제한적전체 지원HolySheep
멀티 소스 통합별도 키 필요단일 키로 통합HolySheep

이런 팀에 적합 / 비적합

✅ HolySheep AI 게이트웨이가 적합한 팀

❌ HolySheep AI 게이트웨이가 비적합한 팀

가격과 ROI

비용 구조 비교

플랜Tardis.devHolySheep AI
스타터$299/월사용량 기반 (약 $0.001/요청)
프로$799/월$199/월 + 사용량
엔터프라이즈$2,499/월맞춤형 (연동 할인 적용)
데이터 볼륨월 5억 틱 포함월 10억 틱 포함 (엔터프라이즈)

ROI 계산 사례

위 A사 사례 기준으로 실제 ROI를 계산하면:

Tardis.dev Tick 데이터 API 구현 완전 가이드

Python으로 HolySheep 게이트웨이 통해 Tardis 데이터 접근

import asyncio
import aiohttp
import json
from datetime import datetime, timedelta
from typing import List, Dict, Optional

class HolySheepTickClient:
    """HolySheep AI 게이트웨이 기반 Tick 데이터 클라이언트"""
    
    BASE_URL = "https://api.holysheep.ai/v1"
    
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.session: Optional[aiohttp.ClientSession] = None
        
    async def __aenter__(self):
        self.session = aiohttp.ClientSession(
            headers={
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            },
            timeout=aiohttp.ClientTimeout(total=30)
        )
        return self
        
    async def __aexit__(self, *args):
        if self.session:
            await self.session.close()
            
    async def fetch_tick_history(
        self,
        exchange: str,
        symbols: List[str],
        start_time: datetime,
        end_time: datetime
    ) -> List[Dict]:
        """
        틱 히스토리 데이터 조회
        
        Args:
            exchange: 거래소명 (binance, bybit, okx, etc.)
            symbols: 심볼 목록 ['BTCUSDT', 'ETHUSDT']
            start_time: 시작 시간
            end_time: 종료 시간
            
        Returns:
            틱 데이터 리스트
        """
        url = f"{self.BASE_URL}/tick"
        
        payloads = []
        for symbol in symbols:
            payload = {
                "exchange": exchange,
                "symbol": symbol,
                "startTime": int(start_time.timestamp() * 1000),
                "endTime": int(end_time.timestamp() * 1000),
                "limit": 100000  # 최대 10만 건 per 요청
            }
            payloads.append(payload)
            
        results = []
        for payload in payloads:
            try:
                async with self.session.post(url, json=payload) as response:
                    if response.status == 429:
                        # Rate limit 핸들링: 지수 백오프
                        await asyncio.sleep(2 ** 2)  # 4초 대기
                        continue
                    elif response.status != 200:
                        error_text = await response.text()
                        print(f"API Error {response.status}: {error_text}")
                        continue
                        
                    data = await response.json()
                    results.extend(data.get('ticks', []))
                    
            except aiohttp.ClientError as e:
                print(f"Connection error: {e}")
                continue
                
        return results
    
    async def stream_realtime_tick(
        self,
        exchange: str,
        symbol: str,
        callback
    ):
        """
        실시간 틱 스트리밍 (WebSocket)
        
        Args:
            exchange: 거래소명
            symbol: 심볼
            callback: 틱 수신 시 호출될 콜백 함수
        """
        ws_url = f"{self.BASE_URL}/tick/stream"
        
        params = {
            "exchange": exchange,
            "symbol": symbol
        }
        
        async with self.session.ws_connect(
            ws_url, 
            params=params,
            headers={"Authorization": f"Bearer {self.api_key}"}
        ) as ws:
            print(f"WebSocket 연결됨: {exchange}/{symbol}")
            
            async for msg in ws:
                if msg.type == aiohttp.WSMsgType.TEXT:
                    tick_data = json.loads(msg.data)
                    await callback(tick_data)
                elif msg.type == aiohttp.WSMsgType.ERROR:
                    print(f"WebSocket 오류: {msg.data}")
                    break

사용 예시

async def main(): async with HolySheepTickClient("YOUR_HOLYSHEEP_API_KEY") as client: # 최근 1시간 틱 데이터 조회 end_time = datetime.now() start_time = end_time - timedelta(hours=1) ticks = await client.fetch_tick_history( exchange="binance", symbols=["BTCUSDT", "ETHUSDT"], start_time=start_time, end_time=end_time ) print(f"수신된 틱 데이터: {len(ticks)}건") # 실시간 스트리밍 예시 def on_tick(tick): print(f"[{tick['timestamp']}] {tick['symbol']}: " f"price={tick['price']}, volume={tick['volume']}") await client.stream_realtime_tick("binance", "BTCUSDT", on_tick) if __name__ == "__main__": asyncio.run(main())

Node.js로 실시간 틱 데이터 대시보드 구축

const WebSocket = require('ws');
const axios = require('axios');

class TickDashboard {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://api.holysheep.ai/v1';
    this.subscriptions = new Map();
    this.priceHistory = new Map();
    this.maxHistorySize = 100;
  }

  async startRealTimeFeed(exchanges) {
    // HolySheep WebSocket 게이트웨이
    const wsUrl = wss://api.holysheep.ai/v1/tick/stream?key=${this.apiKey};
    const ws = new WebSocket(wsUrl);

    ws.on('open', () => {
      console.log('HolySheep WebSocket 연결 성공');
      
      // 다중 거래소 구독
      exchanges.forEach(({ exchange, symbol }) => {
        const subscribeMsg = JSON.stringify({
          action: 'subscribe',
          exchange,
          symbol,
          channels: ['tick', 'orderbook']
        });
        ws.send(subscribeMsg);
        console.log(구독 등록: ${exchange}/${symbol});
      });
    });

    ws.on('message', (data) => {
      const message = JSON.parse(data);
      this.processTick(message);
    });

    ws.on('error', (error) => {
      console.error('WebSocket 오류:', error.message);
    });

    ws.on('close', () => {
      console.log('연결 종료, 5초 후 재연결...');
      setTimeout(() => this.startRealTimeFeed(exchanges), 5000);
    });

    return ws;
  }

  processTick(tickData) {
    const key = ${tickData.exchange}:${tickData.symbol};
    
    // 가격 히스토리 업데이트
    if (!this.priceHistory.has(key)) {
      this.priceHistory.set(key, []);
    }
    
    const history = this.priceHistory.get(key);
    history.push({
      price: parseFloat(tickData.price),
      volume: parseFloat(tickData.volume),
      timestamp: tickData.timestamp
    });
    
    // 최대 히스토리 크기 유지
    if (history.length > this.maxHistorySize) {
      history.shift();
    }
    
    // 대시보드 업데이트
    this.renderDashboard(key, tickData);
  }

  renderDashboard(key, tick) {
    const history = this.priceHistory.get(key);
    const prices = history.map(h => h.price);
    
    // 기술적 지표 계산
    const currentPrice = prices[prices.length - 1];
    const priceChange = ((currentPrice - prices[0]) / prices[0] * 100).toFixed(2);
    const avgPrice = (prices.reduce((a, b) => a + b, 0) / prices.length).toFixed(2);
    const maxPrice = Math.max(...prices).toFixed(2);
    const minPrice = Math.min(...prices).toFixed(2);
    
    // 콘솔 대시보드 렌더링
    console.clear();
    console.log(\n╔══════════════════════════════════════════════════════════╗);
    console.log(║         HolySheep Tick Real-Time Dashboard              ║);
    console.log(╠══════════════════════════════════════════════════════════╣);
    console.log(║ ${key.padEnd(55)} ║);
    console.log(╠══════════════════════════════════════════════════════════╣);
    console.log(║  현재가: $${currentPrice.toString().padEnd(25)} ║);
    console.log(║  변동률: ${priceChange > 0 ? '+' : ''}${priceChange}%.padEnd(56) + '║');
    console.log(║  평균가: $${avgPrice.padEnd(25)} ║);
    console.log(║  최고가: $${maxPrice.padEnd(25)} ║);
    console.log(║  최저가: $${minPrice.padEnd(25)} ║);
    console.log(║  데이터 포인트: ${history.length}/${this.maxHistorySize}.padEnd(56) + '║');
    console.log(╚══════════════════════════════════════════════════════════╝);
  }
}

// 사용 예시
const dashboard = new TickDashboard('YOUR_HOLYSHEEP_API_KEY');

dashboard.startRealTimeFeed([
  { exchange: 'binance', symbol: 'BTCUSDT' },
  { exchange: 'bybit', symbol: 'BTCUSDT' },
  { exchange: 'okx', symbol: 'BTC-USDT' }
]).then(ws => {
  console.log('대시보드 시작됨. Ctrl+C로 종료.');
});

자주 발생하는 오류와 해결책

오류 1: 401 Unauthorized - API 키 인증 실패

{
  "error": "401 Unauthorized",
  "message": "Invalid API key or key has been revoked",
  "code": "AUTH_INVALID_KEY"
}

원인:

  • 만료된 API 키 사용
  • 키 복사 시 공백 또는 잘못된 문자 포함
  • HolySheep 대시보드에서 키 비활성화됨

해결 코드:

import os

❌ 잘못된 방식: 환경변수에 공백이 포함될 수 있음

api_key = os.environ.get('HOLYSHEEP_API_KEY ') # 끝에 공백!

✅ 올바른 방식: strip()으로 공백 제거

api_key = os.environ.get('HOLYSHEEP_API_KEY', '').strip() if not api_key: raise ValueError("HOLYSHEEP_API_KEY 환경변수가 설정되지 않았습니다.") if len(api_key) < 32: raise ValueError("유효하지 않은 API 키 형식입니다.")

키 유효성 검증

def validate_api_key(key: str) -> bool: """API 키 형식 검증""" # HolySheep 키 형식: sk_hs_... (44자) return key.startswith('sk_hs_') and len(key) >= 40 if not validate_api_key(api_key): raise ValueError(f"API 키 유효성 검증 실패: {api_key[:8]}...") print("API 키 검증 완료")

오류 2: 429 Too Many Requests - Rate Limit 초과

{
  "error": "429 Too Many Requests",
  "message": "Rate limit exceeded. Retry after 60 seconds.",
  "retryAfter": 60,
  "currentUsage": 4950,
  "limit": 5000
}
원인:

  • 초과 호출로 인한 Rate Limit 도달
  • 대량 데이터 배치 요청 시 한도 초과
  • 짧은 시간 내 과도한 동시 요청

해결 코드:

import asyncio
import time
from collections import deque
from typing import Callable, Any

class RateLimitedClient:
    """Rate Limit을 자동 처리하는 HolySheep API 클라이언트"""
    
    def __init__(self, requests_per_minute: int = 3000):
        self.rpm_limit = requests_per_minute
        self.request_times = deque(maxlen=requests_per_minute)
        self.retry_after = 60
        
    async def throttled_request(
        self,
        request_func: Callable,
        *args,
        **kwargs
    ) -> Any:
        """Rate Limit을 고려한 요청 실행"""
        max_retries = 5
        retry_count = 0
        
        while retry_count < max_retries:
            # Rate Limit 체크
            await self._wait_if_needed()
            
            try:
                result = await request_func(*args, **kwargs)
                self.request_times.append(time.time())
                return result
                
            except Exception as e:
                if '429' in str(e) or 'rate limit' in str(e).lower():
                    retry_count += 1
                    wait_time = self.retry_after * (2 ** retry_count)
                    print(f"Rate Limit 도달. {wait_time}초 후 재시도... ({retry_count}/{max_retries})")
                    await asyncio.sleep(wait_time)
                else:
                    raise
                    
        raise Exception(f"최대 재시도 횟수 초과: {max_retries}")
        
    async def _wait_if_needed(self):
        """Rate Limit에 도달하지 않도록 대기"""
        now = time.time()
        
        # 1분 이내 요청 수 확인
        recent_requests = [
            t for t in self.request_times 
            if now - t < 60
        ]
        
        if len(recent_requests) >= self.rpm_limit:
            oldest = min(recent_requests)
            wait_time = 60 - (now - oldest) + 1
            print(f"Rate Limit 방지를 위해 {wait_time:.1f}초 대기")
            await asyncio.sleep(wait_time)

사용 예시

async def main(): client = RateLimitedClient(requests_per_minute=3000) # 각 요청이 자동으로 Rate Limit 처리됨 for symbol in ['BTCUSDT', 'ETHUSDT', 'BNBUSDT']: result = await client.throttled_request( fetch_tick_data, exchange='binance', symbol=symbol ) print(f"{symbol} 데이터 수신 완료")

오류 3: 데이터 불일치 - 거래소별 심볼 형식 오류

{
  "error": "400 Bad Request",
  "message": "Invalid symbol format for exchange 'okx'",
  "details": "OKX requires '-' separator, e.g., 'BTC-USDT' not 'BTCUSDT'"
}

원인:

  • 거래소마다 심볼 형식이 다름 (예: Binance: BTCUSDT, OKX: BTC-USDT)
  • 하이픈/언더스코어 혼용
  • 소문자/대문자 불일치

해결 코드:

class SymbolNormalizer:
    """거래소별 심볼 형식 정규화"""
    
    SYMBOL_FORMATS = {
        'binance': {
            'pattern': '{base}{quote}',  # BTCUSDT
            'separator': ''
        },
        'bybit': {
            'pattern': '{base}{quote}',  # BTCUSDT
            'separator': ''
        },
        'okx': {
            'pattern': '{base}-{quote}',  # BTC-USDT
            'separator': '-'
        },
        'huobi': {
            'pattern': '{base}{quote}',  # btcusdt
            'separator': '',
            'lowercase': True
        },
        'kraken': {
            'pattern': '{base}{quote}',  # XBT/USDT
            'separator': '/',
            'prefix': {'BTC': 'XBT', 'ETH': 'XETH'}
        }
    }
    
    # 공통 거래소 심볼 매핑
    COMMON_SYMBOLS = {
        'BTCUSDT': {'base': 'BTC', 'quote': 'USDT'},
        'ETHUSDT': {'base': 'ETH', 'quote': 'USDT'},
        'BNBUSDT': {'base': 'BNB', 'quote': 'USDT'},
    }
    
    @classmethod
    def normalize(cls, symbol: str, exchange: str) -> str:
        """HolySheep API 호환 심볼 형식으로 변환"""
        
        # 이미 HolySheep 형식인 경우 그대로 반환
        if ':' in symbol:
            return symbol
            
        # 심볼 파싱
        base, quote = cls._parse_symbol(symbol)
        
        # 거래소별 형식으로 변환
        if exchange in cls.SYMBOL_FORMATS:
            config = cls.SYMBOL_FORMATS[exchange]
            normalized = config['pattern'].format(base=base, quote=quote)
            
            if config.get('lowercase'):
                normalized = normalized.lower()
                
            if config.get('prefix') and base in config['prefix']:
                normalized = normalized.replace(base, config['prefix'][base])
                
            return normalized
            
        # 알 수 없는 거래소는 원본 반환
        return symbol
    
    @classmethod
    def _parse_symbol(cls, symbol: str) -> tuple:
        """심볼을 base/quote로 파싱"""
        
        # COMMON_SYMBOLS에서 먼저查找
        if symbol in cls.COMMON_SYMBOLS:
            info = cls.COMMON_SYMBOLS[symbol]
            return info['base'], info['quote']
        
        # 공통 퀴트 탐지
        quotes = ['USDT', 'USDC', 'BUSD', 'USD', 'BTC', 'ETH', 'BNB']
        for quote in quotes:
            if symbol.endswith(quote):
                base = symbol[:-len(quote)]
                if base and len(base) >= 2:
                    return base, quote
        
        # 파싱 실패 시 원본 반환
        return symbol[:3], symbol[3:]

사용 예시

normalizer = SymbolNormalizer() test_cases = [ ('BTCUSDT', 'binance'), ('BTCUSDT', 'okx'), ('BTCUSDT', 'kraken'), ('ETH-USDT', 'binance'), ] for symbol, exchange in test_cases: normalized = normalizer.normalize(symbol, exchange) print(f"{exchange:10} | {symbol:12} → {normalized}")

추가 오류 4: WebSocket 연결 끊김과 자동 재연결

{
  "event": "websocket_disconnected",
  "code": 1006,
  "reason": "Connection lost",
  "reconnect_attempt": 1
}
해결 코드:

const WebSocket = require('ws');

class HolySheepWebSocketManager {
  constructor(apiKey, options = {}) {
    this.apiKey = apiKey;
    this.baseUrl = 'wss://api.holysheep.ai/v1/tick/stream';
    this.ws = null;
    this.reconnectAttempts = 0;
    this.maxReconnectAttempts = options.maxReconnectAttempts || 10;
    this.reconnectDelay = options.reconnectDelay || 1000;
    this.heartbeatInterval = options.heartbeatInterval || 30000;
    this.subscriptions = new Map();
    this.heartbeatTimer = null;
    this.isManualClose = false;
  }

  connect() {
    return new Promise((resolve, reject) => {
      const url = ${this.baseUrl}?key=${this.apiKey};
      this.ws = new WebSocket(url);

      this.ws.on('open', () => {
        console.log('HolySheep WebSocket 연결 성공');
        this.reconnectAttempts = 0;
        this.startHeartbeat();
        this.resubscribeAll();
        resolve();
      });

      this.ws.on('message', (data) => {
        const message = JSON.parse(data);
        this.handleMessage(message);
      });

      this.ws.on('close', (code, reason) => {
        console.log(WebSocket 닫힘: ${code} - ${reason});
        this.stopHeartbeat();
        
        if (!this.isManualClose) {
          this.scheduleReconnect();
        }
      });

      this.ws.on('error', (error) => {
        console.error('WebSocket 오류:', error.message);
        reject(error);
      });
    });
  }

  scheduleReconnect() {
    if (this.reconnectAttempts >= this.maxReconnectAttempts) {
      console.error('최대 재연결 시도 횟수 초과');
      return;
    }

    this.reconnectAttempts++;
    const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
    const cappedDelay = Math.min(delay, 60000); // 최대 60초

    console.log(${cappedDelay/1000}초 후 재연결 시도... (${this.reconnectAttempts}/${this.maxReconnectAttempts}));
    
    setTimeout(() => {
      this.connect().catch(err => {
        console.error('재연결 실패:', err.message);
      });
    }, cappedDelay);
  }

  startHeartbeat() {
    this.heartbeatTimer = setInterval(() => {
      if (this.ws && this.ws.readyState === WebSocket.OPEN) {
        this.ws.send(JSON.stringify({ type: 'ping' }));
      }
    }, this.heartbeatInterval);
  }

  stopHeartbeat() {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
      this.heartbeatTimer = null;
    }
  }

  subscribe(exchange, symbol, callback) {
    const key = ${exchange}:${symbol};
    this.subscriptions.set(key, callback);
    
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify({
        action: 'subscribe',
        exchange,
        symbol,
        channels: ['tick']
      }));
    }
  }

  resubscribeAll() {
    for (const [key, callback] of this.subscriptions) {