How to Build a Real-Time Forex Dashboard with WebSocket API

K

Katy Spark

Aug 10, 2025

5 min read 2,127 views

Building a real-time forex dashboard is one of the most practical applications of WebSocket technology in financial applications. In this comprehensive tutorial, we'll create a live dashboard that displays streaming currency prices, complete with visual indicators and responsive design.

Why WebSocket for Real-Time Data?

Traditional REST APIs require constant polling to fetch new data, which is inefficient and creates unnecessary server load. WebSocket connections provide several advantages:

  • Low latency: Data arrives instantly when prices change
  • Efficient: Single persistent connection instead of repeated requests
  • Bidirectional: Server can push data without client requests
  • Reduced overhead: No HTTP headers on each message

Prerequisites

Before we begin, make sure you have:

  • A PulseMarkets API key (get one from your dashboard)
  • Basic knowledge of JavaScript
  • Node.js installed (for the development server)

Step 1: Setting Up the Connection

First, let's establish a WebSocket connection to the PulseMarkets streaming API:

// Initialize WebSocket connection
const apiKey = 'your_api_key_here';
const ws = new WebSocket(`wss://api.pulse-markets.com?api_key=${apiKey}`);

ws.onopen = () => {
    console.log('Connected to PulseMarkets WebSocket');

    // Subscribe to currency pairs
    ws.send(JSON.stringify({
        action: 'subscribe',
        symbols: ['EURUSD', 'GBPUSD', 'USDJPY', 'XAUUSD']
    }));
};

ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    if (data.event === 'quote') {
        updateDashboard(data.data);
    }
};

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

ws.onclose = () => {
    console.log('Disconnected - attempting reconnect...');
    setTimeout(connectWebSocket, 5000);
};

Step 2: Building the Dashboard HTML

Create a responsive dashboard layout using modern CSS Grid:

<div class="dashboard">
    <header class="dashboard-header">
        <h1>Live Forex Dashboard</h1>
        <div id="connection-status" class="status-indicator">
            <span class="status-dot"></span>
            <span class="status-text">Connecting...</span>
        </div>
    </header>

    <div class="currency-grid" id="currency-grid">
        <!-- Currency cards will be inserted here -->
    </div>
</div>

Step 3: Creating Dynamic Currency Cards

Build a function to create and update currency pair cards:

function createCurrencyCard(symbol) {
    return `
        <div class="currency-card" id="card-${symbol}">
            <div class="card-header">
                <h3 class="symbol">${formatSymbol(symbol)}</h3>
                <span class="change-indicator" id="change-${symbol}"></span>
            </div>
            <div class="price-display">
                <span class="price" id="price-${symbol}">--</span>
            </div>
            <div class="card-footer">
                <div class="bid-ask">
                    <span>Bid: <span id="bid-${symbol}">--</span></span>
                    <span>Ask: <span id="ask-${symbol}">--</span></span>
                </div>
                <span class="timestamp" id="time-${symbol}">--</span>
            </div>
        </div>
    `;
}

function updateDashboard(quote) {
    const { symbol, price, bid, ask, timestamp } = quote;

    // Get previous price for comparison
    const prevPrice = priceCache[symbol] || price;
    priceCache[symbol] = price;

    // Update price display
    const priceEl = document.getElementById(`price-${symbol}`);
    priceEl.textContent = formatPrice(price, symbol);

    // Add flash animation based on price direction
    const card = document.getElementById(`card-${symbol}`);
    card.classList.remove('flash-up', 'flash-down');

    if (price > prevPrice) {
        card.classList.add('flash-up');
    } else if (price < prevPrice) {
        card.classList.add('flash-down');
    }

    // Update bid/ask
    document.getElementById(`bid-${symbol}`).textContent = formatPrice(bid, symbol);
    document.getElementById(`ask-${symbol}`).textContent = formatPrice(ask, symbol);

    // Update timestamp
    document.getElementById(`time-${symbol}`).textContent =
        new Date(timestamp).toLocaleTimeString();
}

Step 4: Adding Visual Feedback

CSS animations make price changes immediately visible to users:

.currency-card {
    background: white;
    border-radius: 12px;
    padding: 1.5rem;
    box-shadow: 0 2px 8px rgba(0,0,0,0.08);
    transition: all 0.3s ease;
}

.flash-up {
    animation: flashGreen 0.5s ease;
}

.flash-down {
    animation: flashRed 0.5s ease;
}

@keyframes flashGreen {
    0%, 100% { background: white; }
    50% { background: rgba(16, 185, 129, 0.1); }
}

@keyframes flashRed {
    0%, 100% { background: white; }
    50% { background: rgba(239, 68, 68, 0.1); }
}

.price {
    font-size: 2rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

Step 5: Handling Reconnection

Robust applications need to handle disconnections gracefully:

class WebSocketManager {
    constructor(apiKey) {
        this.apiKey = apiKey;
        this.ws = null;
        this.reconnectAttempts = 0;
        this.maxReconnectAttempts = 10;
        this.subscriptions = new Set();
    }

    connect() {
        this.ws = new WebSocket(
            `wss://api.pulse-markets.com?api_key=${this.apiKey}`
        );

        this.ws.onopen = () => {
            this.reconnectAttempts = 0;
            this.updateStatus('connected');
            this.resubscribe();
        };

        this.ws.onclose = () => {
            this.updateStatus('disconnected');
            this.scheduleReconnect();
        };
    }

    scheduleReconnect() {
        if (this.reconnectAttempts >= this.maxReconnectAttempts) {
            this.updateStatus('failed');
            return;
        }

        const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);
        this.reconnectAttempts++;

        setTimeout(() => this.connect(), delay);
    }

    resubscribe() {
        if (this.subscriptions.size > 0) {
            this.ws.send(JSON.stringify({
                action: 'subscribe',
                symbols: Array.from(this.subscriptions)
            }));
        }
    }
}

Complete Working Example

You can find the complete source code for this dashboard on our GitHub repository. The example includes:

  • Full WebSocket connection management
  • Responsive CSS grid layout
  • Price change animations
  • Connection status indicator
  • Error handling and reconnection logic

Next Steps

Now that you have a working real-time dashboard, consider these enhancements:

  • Add mini charts showing recent price history
  • Implement price alerts for specific levels
  • Store historical data in IndexedDB for offline viewing
  • Add sound notifications for significant price moves

Real-time data opens up endless possibilities for building powerful trading tools. Start with this foundation and expand based on your specific needs.

Tags: websocket api tutorial real-time data javascript dashboard
Share:
K

Katy Spark

Content Writer at PulseMarkets

Expert in forex trading, market analysis, and financial API integration. Helping traders and developers make better decisions with data.

Ready to Get Started?

Access professional-grade market data with our powerful API

Start Free Trial