CoolFace
Apppublic

Aaryan041124/Heat_Map_Server

sourceHugging Faceupdated 7mo agoView on Hugging Face
0likes
App README

Stock Heat Map Server

Tech Stack

  • Java 17
  • Spring Boot 3.3.5
  • Spring GraphQL
  • Spring WebFlux (WebClient)
  • Apache POI (Excel parsing)
  • Maven

What This Service Does

  1. 1.Accepts Excel workbook content via GraphQL mutation (fileBase64).
  2. 2.Parses stock rows from the first sheet.
  3. 3.Fetches real-time quotes from Finnhub (primary) and Yahoo Finance (fallback).
  4. 4.Builds weighted sector and market summary data.
  5. 5.Stores snapshots in memory and serves them via GraphQL queries.

Project Structure

  • Entry point: src/main/java/com/stockheatmap/StockHeatMapServerApplication.java
  • GraphQL controller: src/main/java/com/stockheatmap/graphql/HeatMapGraphqlController.java
  • Core services:
  • src/main/java/com/stockheatmap/service/ExcelParserService.java
  • src/main/java/com/stockheatmap/service/YahooFinanceService.java
  • src/main/java/com/stockheatmap/service/HeatMapService.java
  • GraphQL schema: src/main/resources/graphql/schema.graphqls
  • Runtime config: src/main/resources/application.yml

Excel Input Contract

The service reads sheet index 0 and supports header-based parsing.

Preferred format:

  1. 1.Equity Symbol (required)
  2. 2.Equity Description
  3. 3.Currency (ignored)
  4. 4.Cost Basis (ignored)
  5. 5.Asset Class (used as fallback for industry)
  6. 6.Quantity (used as weight, optional, defaults to 1)
  7. 7.Sector (optional; auto-enriched from market data provider when missing)

Also supported (legacy format):

  1. 1.ticker (required)
  2. 2.company
  3. 3.sector (optional; auto-enriched from market data provider when missing)
  4. 4.industry
  5. 5.weight (optional; defaults to 1)

Notes:

  • Row 0 is treated as header.
  • Blank ticker rows are skipped.
  • Blank sector/industry are enriched from Finnhub first, then Yahoo fallback. If unresolved, values remain Other.

GraphQL API

Endpoint: http://localhost:8080/graphql GraphiQL: http://localhost:8080/graphiql

Mutation

graphql
mutation ImportWorkbook($fileName: String!, $fileBase64: String!) {
  importWorkbook(fileName: $fileName, fileBase64: $fileBase64) {
    batchId
    importedRows
    invalidRows
    message
  }
}

Queries

graphql
query LatestBatch {
  latestBatchId
}
graphql
query HeatMap($batchId: String) {
  heatMap(batchId: $batchId) {
    batchId
    asOf
    marketChangePercent
    sectors {
      sector
      changePercent
      totalWeight
      stocks {
        ticker
        company
        industry
        weight
        price
        changePercent
        weightedValue
      }
    }
  }
}

Behavior:

  • If batchId is null/blank, default preset is SP100 (for initial load).
  • If batchId is an uploaded id, that personal portfolio snapshot is returned.
  • batchId also accepts preset aliases: SP100, SP500, PERSONAL.
graphql
query HeatMapPreset($preset: String!) {
  heatMapPreset(preset: $preset) {
    batchId
    asOf
    marketChangePercent
    sectors {
      sector
      changePercent
      totalWeight
      stocks {
        ticker
        changePercent
      }
    }
  }
}

Preset mapping:

  • SP100 -> SP100_US_Stocks.xlsx
  • SP500 -> SP500_US_Stocks.xlsx
  • PERSONAL -> latest uploaded workbook snapshot

Build and Run

bash
cd /Users/aaryan/workspace/server/Stock_Heat_Map_Server
export FINNHUB_API_KEY=your_finnhub_api_key
export APP_CORS_ALLOWED_ORIGINS=http://localhost:4200
mvn clean spring-boot:run

Package jar:

bash
mvn clean package
java -jar target/stock-heat-map-server-0.0.1-SNAPSHOT.jar

Logging and Debugging

Configured in application.yml:

  • com.stockheatmap: DEBUG
  • org.springframework.graphql: INFO
  • reactor.netty.http.client: WARN

Important logs include:

  • workbook parse start/end and failures
  • Yahoo batch quote request failures
  • number of imported and unresolved rows
  • snapshot creation and query retrieval paths

Runtime Notes

  • Snapshot storage is in-memory only (lost on restart).
  • Quote provider order is Finnhub -> Yahoo fallback.
  • If FINNHUB_API_KEY is missing or Finnhub does not resolve a symbol, Yahoo is used as fallback.
  • To avoid Finnhub 429, only a configurable subset goes to Finnhub and the rest use Yahoo bulk:
  • FINNHUB_MAX_SYMBOLS_PER_LOOKUP (default 10)
  • FINNHUB_MIN_REQUEST_INTERVAL_MS (default 1100)
  • If a quote is missing, stock values default to 0 and count toward invalidRows.
  • CORS is controlled by APP_CORS_ALLOWED_ORIGINS (comma-separated; supports patterns via Spring allowedOriginPatterns).

Hugging Face Deployment (Docker Space)

This repo now includes a Dockerfile for Hugging Face Spaces.

Required Space Settings

  • SDK: Docker
  • PORT: app listens on 7860 (already configured)
  • Secrets:
  • FINNHUB_API_KEY=<your_finnhub_key>
  • Variables:
  • APP_CORS_ALLOWED_ORIGINS=https://<your-client-space>.hf.space
  • Optional:
  • FINNHUB_MAX_SYMBOLS_PER_LOOKUP=10
  • FINNHUB_MIN_REQUEST_INTERVAL_MS=1100

Deploy

  1. 1.Create a new Hugging Face Space for the server with SDK = Docker.
  2. 2.Push this repository contents to that Space.
  3. 3.Add FINNHUB_API_KEY in Settings -> Secrets.
  4. 4.Add APP_CORS_ALLOWED_ORIGINS in Settings -> Variables.
  5. 5.Restart the Space.

Extending Provider Support

To use Finnhub or another provider:

  • Replace/extend YahooFinanceService with a new quote provider service.
  • Keep return contract as Map<String, StockQuote> so HeatMapService remains unchanged.