Aaryan041124/Heat_Map_Server
0
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
- Accepts Excel workbook content via GraphQL mutation (
fileBase64). - Parses stock rows from the first sheet.
- Fetches real-time quotes from Finnhub (primary) and Yahoo Finance (fallback).
- Builds weighted sector and market summary data.
- 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.javasrc/main/java/com/stockheatmap/service/YahooFinanceService.javasrc/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:
Equity Symbol(required)Equity DescriptionCurrency(ignored)Cost Basis(ignored)Asset Class(used as fallback forindustry)Quantity(used asweight, optional, defaults to1)Sector(optional; auto-enriched from market data provider when missing)
Also supported (legacy format):
ticker(required)companysector(optional; auto-enriched from market data provider when missing)industryweight(optional; defaults to1)
Notes:
- Row
0is treated as header. - Blank
tickerrows are skipped. - Blank
sector/industryare enriched from Finnhub first, then Yahoo fallback. If unresolved, values remainOther.
GraphQL API
Endpoint: http://localhost:8080/graphql GraphiQL: http://localhost:8080/graphiql
Mutation
mutation ImportWorkbook($fileName: String!, $fileBase64: String!) {
importWorkbook(fileName: $fileName, fileBase64: $fileBase64) {
batchId
importedRows
invalidRows
message
}
}Queries
query LatestBatch {
latestBatchId
}query HeatMap($batchId: String) {
heatMap(batchId: $batchId) {
batchId
asOf
marketChangePercent
sectors {
sector
changePercent
totalWeight
stocks {
ticker
company
industry
weight
price
changePercent
weightedValue
}
}
}
}Behavior:
- If
batchIdisnull/blank, default preset isSP100(for initial load). - If
batchIdis an uploaded id, that personal portfolio snapshot is returned. batchIdalso accepts preset aliases:SP100,SP500,PERSONAL.
query HeatMapPreset($preset: String!) {
heatMapPreset(preset: $preset) {
batchId
asOf
marketChangePercent
sectors {
sector
changePercent
totalWeight
stocks {
ticker
changePercent
}
}
}
}Preset mapping:
SP100->SP100_US_Stocks.xlsxSP500->SP500_US_Stocks.xlsxPERSONAL-> latest uploaded workbook snapshot
Build and Run
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:runPackage jar:
mvn clean package
java -jar target/stock-heat-map-server-0.0.1-SNAPSHOT.jarLogging and Debugging
Configured in application.yml:
com.stockheatmap: DEBUGorg.springframework.graphql: INFOreactor.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_KEYis 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(default10)FINNHUB_MIN_REQUEST_INTERVAL_MS(default1100)- If a quote is missing, stock values default to
0and count towardinvalidRows. - CORS is controlled by
APP_CORS_ALLOWED_ORIGINS(comma-separated; supports patterns via SpringallowedOriginPatterns).
Hugging Face Deployment (Docker Space)
This repo now includes a Dockerfile for Hugging Face Spaces.
Required Space Settings
SDK:DockerPORT: app listens on7860(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=10FINNHUB_MIN_REQUEST_INTERVAL_MS=1100
Deploy
- Create a new Hugging Face Space for the server with
SDK = Docker. - Push this repository contents to that Space.
- Add
FINNHUB_API_KEYinSettings -> Secrets. - Add
APP_CORS_ALLOWED_ORIGINSinSettings -> Variables. - Restart the Space.
Extending Provider Support
To use Finnhub or another provider:
- Replace/extend
YahooFinanceServicewith a new quote provider service. - Keep return contract as
Map<String, StockQuote>soHeatMapServiceremains unchanged.
