Crypto market heatmap development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Crypto market heatmap development
Medium
~3-5 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1214
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Crypto Market Heatmap Development

A heatmap of the cryptocurrency market is a visualization of price changes across the entire market simultaneously. Each asset is represented as a rectangle whose size is proportional to market cap, with color reflecting percentage change over a period. An indispensable tool for quickly understanding market structure.

Treemap Layout Algorithm

The foundation of a heatmap is the Treemap algorithm, which optimally packs rectangles of different sizes:

interface HeatmapCell {
  symbol: string;
  marketCap: number;
  changePercent: number;
  price: number;
  volume24h: number;
  x: number;      // computed by algorithm
  y: number;
  width: number;
  height: number;
}

class SquarifiedTreemap {
  layout(
    data: HeatmapCell[],
    bounds: {x: number; y: number; width: number; height: number}
  ): HeatmapCell[] {
    // Sort by decreasing size (capitalization)
    const sorted = [...data].sort((a, b) => b.marketCap - a.marketCap);
    const totalMarketCap = sorted.reduce((sum, d) => sum + d.marketCap, 0);

    return this.squarify(sorted, bounds, totalMarketCap);
  }

  private squarify(items: HeatmapCell[], bounds: Bounds, total: number): HeatmapCell[] {
    if (items.length === 0) return [];

    const isHorizontal = bounds.width >= bounds.height;
    const result: HeatmapCell[] = [];
    let row: HeatmapCell[] = [];
    let rowArea = 0;
    let offset = 0;

    for (const item of items) {
      const itemArea = (item.marketCap / total) * (bounds.width * bounds.height);
      const testRow = [...row, item];
      const testArea = rowArea + itemArea;

      if (this.wouldImproveAspectRatio(testRow, testArea, bounds, isHorizontal)) {
        row.push(item);
        rowArea = testArea;
      } else {
        // Finalize current row
        result.push(...this.layoutRow(row, rowArea, bounds, isHorizontal, offset, total));
        const rowThickness = rowArea / (isHorizontal ? bounds.width : bounds.height);
        offset += rowThickness;

        row = [item];
        rowArea = itemArea;
      }
    }

    if (row.length > 0) {
      result.push(...this.layoutRow(row, rowArea, bounds, isHorizontal, offset, total));
    }

    return result;
  }
}

Data Fetching

import httpx
import asyncio

class MarketDataProvider:
    COINGECKO_URL = "https://api.coingecko.com/api/v3"

    async def get_heatmap_data(
        self,
        vs_currency: str = 'usd',
        top_n: int = 100
    ) -> list[dict]:
        async with httpx.AsyncClient() as client:
            response = await client.get(
                f"{self.COINGECKO_URL}/coins/markets",
                params={
                    "vs_currency": vs_currency,
                    "order": "market_cap_desc",
                    "per_page": top_n,
                    "page": 1,
                    "sparkline": False,
                    "price_change_percentage": "1h,24h,7d"
                }
            )

        coins = response.json()
        return [
            {
                "symbol": c["symbol"].upper(),
                "name": c["name"],
                "market_cap": c["market_cap"] or 0,
                "change_1h": c.get("price_change_percentage_1h_in_currency", 0) or 0,
                "change_24h": c.get("price_change_percentage_24h", 0) or 0,
                "change_7d": c.get("price_change_percentage_7d_in_currency", 0) or 0,
                "volume_24h": c.get("total_volume", 0) or 0,
                "price": c["current_price"],
                "image": c["image"]
            }
            for c in coins if c["market_cap"]
        ]

We cache data: CoinGecko free API is 10-30 requests/min. Update every 60 seconds:

async def get_cached_data(self) -> list[dict]:
    cache_key = "heatmap_data"
    cached = await self.redis.get(cache_key)

    if cached:
        return json.loads(cached)

    data = await self.get_heatmap_data()
    await self.redis.setex(cache_key, 60, json.dumps(data))
    return data

React Visualization

import React, { useMemo } from 'react';

const getColor = (changePercent: number): string => {
  const intensity = Math.min(Math.abs(changePercent) / 10, 1);
  if (changePercent > 0) {
    const green = Math.floor(180 * intensity + 60);
    return `rgb(0, ${green}, 0)`;
  } else {
    const red = Math.floor(180 * intensity + 60);
    return `rgb(${red}, 0, 0)`;
  }
};

const HeatmapCell: React.FC<{cell: HeatmapCell; period: '1h'|'24h'|'7d'}> = ({cell, period}) => {
  const change = period === '1h' ? cell.change1h : period === '24h' ? cell.change24h : cell.change7d;
  const bgColor = getColor(change);

  return (
    <div
      style={{
        position: 'absolute',
        left: cell.x,
        top: cell.y,
        width: cell.width - 2,
        height: cell.height - 2,
        backgroundColor: bgColor,
        border: '1px solid rgba(0,0,0,0.3)',
        overflow: 'hidden',
        cursor: 'pointer'
      }}
      title={`${cell.symbol}: ${change > 0 ? '+' : ''}${change.toFixed(2)}%`}
    >
      {cell.width > 40 && (
        <div className="p-1 text-white">
          <div className="font-bold text-xs">{cell.symbol}</div>
          {cell.height > 30 && (
            <div className={`text-xs ${change > 0 ? 'text-green-200' : 'text-red-200'}`}>
              {change > 0 ? '+' : ''}{change.toFixed(2)}%
            </div>
          )}
        </div>
      )}
    </div>
  );
};

const CryptoHeatmap: React.FC = () => {
  const [data, setData] = useState<HeatmapCell[]>([]);
  const [period, setPeriod] = useState<'1h'|'24h'|'7d'>('24h');
  const containerRef = useRef<HTMLDivElement>(null);
  const [dimensions, setDimensions] = useState({width: 1200, height: 700});

  const layoutData = useMemo(() => {
    const treemap = new SquarifiedTreemap();
    return treemap.layout(data, {x: 0, y: 0, ...dimensions});
  }, [data, dimensions]);

  return (
    <div>
      <div className="flex gap-2 mb-4">
        {(['1h', '24h', '7d'] as const).map(p => (
          <button key={p} onClick={() => setPeriod(p)}
            className={`px-3 py-1 rounded ${period === p ? 'bg-blue-600' : 'bg-gray-700'}`}>
            {p}
          </button>
        ))}
      </div>
      <div ref={containerRef} className="relative bg-gray-900"
           style={{width: dimensions.width, height: dimensions.height}}>
        {layoutData.map(cell => (
          <HeatmapCell key={cell.symbol} cell={cell} period={period} />
        ))}
      </div>
    </div>
  );
};

A heatmap is a killer feature for a crypto platform. Users return to it daily to monitor the market. A good implementation includes: filtering by sectors (DeFi, Layer1, GameFi), zooming into individual sectors, and clickthrough to the trading pair.