← Blog
Jul 25, 2024

Crypto-Sight: Building a Real-Time Analytics Platform

Architecture and development of Crypto-Sight - a real-time cryptocurrency analytics platform with streaming data, complex visualization, and multi-source aggregation.

cryptoanalyticsreal-timedevelopmentdata-visualization

Real-time data is unforgiving. You’re either fast enough, or you’re wrong.

Crypto-Sight was built to handle the chaos of cryptocurrency markets—thousands of price updates per second, from dozens of sources, visualized instantly.

The Challenge

Cryptocurrency markets are uniquely demanding:

Architecture

Crypto-Sight Architecture
├── Data Ingestion
│   ├── Exchange WebSockets (20+ sources)
│   ├── Price Aggregator
│   ├── Volume Calculator
│   └── Event Detector
├── Processing Layer
│   ├── Stream Processing (Python)
│   ├── Indicator Calculation
│   ├── Alert Engine
│   └── Anomaly Detection
├── Storage
│   ├── Time-series DB (Timescale)
│   ├── Cache (Redis)
│   └── Analytics DB (PostgreSQL)
├── API Layer
│   ├── REST API (FastAPI)
│   ├── WebSocket API
│   └── GraphQL
└── Frontend
    ├── React + TypeScript
    ├── Real-time Charts
    ├── Custom Visualizations
    └── Alert Dashboard

Technology Stack

Data Pipeline

Exchange Connections

class ExchangeConnector:
    async def connect(self, exchange: str):
        ws = await websocket_connect(EXCHANGE_WS_URLS[exchange])
        
        # Subscribe to relevant channels
        await ws.send(json.dumps({
            "action": "subscribe",
            "channels": ["ticker", "trades", "orderbook"]
        }))
        
        # Process messages
        async for msg in ws:
            await self.process_message(exchange, msg)
    
    async def process_message(self, exchange: str, raw: str):
        data = parse_exchange_format(exchange, raw)
        
        # Normalize to common schema
        normalized = self.normalize(exchange, data)
        
        # Publish to internal stream
        await self.stream.publish(normalized)

Price Aggregation

Multiple exchanges → single price:

class PriceAggregator:
    def aggregate(self, prices: Dict[str, float], 
                  volumes: Dict[str, float]) -> float:
        """
        Volume-weighted average price across exchanges
        """
        total_volume = sum(volumes.values())
        if total_volume == 0:
            return simple_average(prices.values())
        
        weighted_sum = sum(
            prices[ex] * volumes[ex] 
            for ex in prices
        )
        return weighted_sum / total_volume

Indicator Calculation

Real-time technical indicators:

All calculated incrementally, not recalculated from scratch.

Real-Time Visualization

Streaming Charts

class StreamingChart {
  private buffer: DataPoint[] = [];
  private chart: Chart;
  
  onData(point: DataPoint) {
    // Add to buffer
    this.buffer.push(point);
    
    // Batch updates for performance
    if (this.buffer.length >= 10 || this.lastUpdate > 100ms) {
      this.flush();
    }
  }
  
  flush() {
    // Update chart with all buffered points
    this.chart.addPoints(this.buffer);
    this.buffer = [];
    this.lastUpdate = now();
  }
}

Custom Visualizations

Beyond standard charts:

Alert System

Alert Configuration

interface Alert {
  type: 'price' | 'volume' | 'change' | 'indicator';
  
  // Condition
  symbol: string;
  operator: '>' | '<' | '>=' | '<=';
  value: number;
  
  // Notification
  channels: ('email' | 'sms' | 'push' | 'webhook')[];
  cooldown: number;  // Prevent spam
  
  // State
  triggered: boolean;
  lastTriggered: Date | null;
}

Alert Examples

Performance Optimization

Latency Targets

Path Target Achieved
Exchange → Backend <50ms 35ms
Backend → Client <100ms 80ms
End-to-end <200ms 150ms

Optimization Techniques

Batching: Combine multiple updates into single transmissions

Compression: Delta encoding for time-series data

Caching: Hot data in Redis, queries cached aggressively

CDN: Static assets and historical data served from edge

WebSocket Pooling: Reuse connections across clients

Analytics Features

Historical Analysis

Query any time range:

SELECT 
  time_bucket('1 hour', timestamp) as hour,
  first(price, timestamp) as open,
  max(price) as high,
  min(price) as low,
  last(price, timestamp) as close,
  sum(volume) as volume
FROM trades
WHERE symbol = 'BTC/USD'
  AND timestamp > now() - interval '7 days'
GROUP BY hour
ORDER BY hour;

Correlation Analysis

Find relationships between assets:

Anomaly Detection

Machine learning-based detection:

Lessons Learned

1. Backpressure Is Critical

When data arrives faster than you can process, you need strategies:

2. Time Synchronization Matters

Different exchanges have different clock skews. Normalize timestamps carefully.

3. Visualization Performance

D3.js is flexible but slow for real-time. Custom canvas rendering is necessary.

4. User Expectations Are High

Users expect sub-second updates. Anything slower feels broken.

Hackathon Potential

Crypto-Sight was identified as a strong hackathon candidate for:


Crypto-Sight demonstrates real-time data handling at scale. For related analytics work, see n8n Automation.

All posts Work with me