Technical Internals
A complete reference for engineering leads evaluating the architecture — stack choices, algorithmic design, data pipeline, and known trade-offs. No marketing language.
Every technology in production, with exact versions and rationale.
| Layer | Technology | Version | Rationale |
|---|---|---|---|
| Backend | |||
| Framework | Spring Boot | 3.5.0 | Latest LTS; virtual threads, reactive support, actuator built-in |
| Primary Language | Java | 21 LTS | Virtual threads (Project Loom) for scheduler/IO concurrency |
| Secondary Language | Kotlin | 2.2.0 | Data classes for entities, extension functions in calculation services |
| ORM | Spring Data JPA / Hibernate | 3.5.x | UPSERT via native queries; batch inserts at 50 records/chunk |
| Technical Analysis | TA4J | 0.22.1 | Moving averages, candlestick patterns; avoids reimplementing financial math |
| HTTP Client | OkHttp3 | 5.1.0 | External API calls (Polygon, Yahoo Finance); connection pooling |
| Object Storage | MinIO SDK | 8.6.0 | S3-compatible flat file ingestion from Massive EOD data provider |
| AI Framework | Spring AI | 1.0.0-SNAPSHOT | Unified ChatClient abstraction over Ollama (local) + Azure AI Foundry (cloud); multimodal image support |
| Local LLM | Ollama | — | mistral-small default; vision models (llava) for chart image analysis; 8k context window |
| Real-time | Spring WebSocket / STOMP | 3.5.x | Server-push for live price updates; SockJS fallback for proxies |
| Boilerplate | Lombok | 1.18.38 | @Data, @Builder, @RequiredArgsConstructor on Java entities |
| Frontend | |||
| Framework | Angular | 20.3.7 | Standalone components (v17+); hybrid migration from NgModules in progress |
| UI Library | Angular Material | 20.2.10 | Tables, dialogs, select, autocomplete — consistent Material Design |
| Charting | D3.js | 7.9.0 | Custom candlestick renderer, volume bars, RS overlay lines |
| Reactive | RxJS | 7.8.1 | Observable chains for WebSocket streams, HTTP, and component state |
| WebSocket Client | @stomp/stompjs + SockJS | 7.3.0 / 1.6.1 | STOMP protocol over WebSocket with auto-reconnect |
| Language | TypeScript | 5.8.3 | Strict mode; 257 component/service files |
| Data & Infrastructure | |||
| Database | PostgreSQL | 15 / driver 42.7.9 | Window functions (LAG, STDDEV_POP, AVG OVER) for analytics; 57 entities |
| Deployment | Azure App Service | — | JAR deployment via GitHub Actions; no containerisation |
| CI/CD | GitHub Actions | — | mvn clean install → artifact upload → Azure webapps-deploy |
Two AI surfaces built on Spring AI 1.0.0-SNAPSHOT. Local inference via Ollama; cloud fallback to Azure AI Foundry. No vendor lock-in — only a property change to switch providers.
Context-aware assistant embedded inside every stock chart. System prompt is assembled at runtime from stored ticker, sector, description, and any cached company analysis.
ByteArrayResource + MimeTypeUtils.IMAGE_PNG — requires a vision model (e.g. llava)
Single endpoint triggers end-to-end pipeline: SEC EDGAR fetch → XBRL Company Facts API → financial table → LLM prompt → persist. DB connection is not held during inference.
// 1. Fetch 10-Q (auto-downloads from SEC EDGAR if missing) SecReport report = secReportService.getLatestReport(ticker); // 2. Company Facts API — structured XBRL JSON (not raw XML) // GET data.sec.gov/api/xbrl/companyfacts/CIK{cik}.json JsonNode facts = secReportService.fetchCompanyFacts(ticker); // 3. Build table: 12 concepts × last 6 quarters String table = buildFinancialTable(facts); // Revenue, NetIncomeLoss, EPS, OperatingCF, LongTermDebt… // 4. LLM call — no DB transaction here String analysis = chatClient.prompt() .user(buildPrompt(ticker, report, table)) .call().content(); // 5. Short @Transactional persist return persist(ticker, analysis); // → company_analysis table
ChatClient.Builderapp.ai.provider=foundryapplication.properties. ChatClient.Builder is injected; the implementation is resolved at startup by Spring AI auto-configuration.