Skip to content

feat(stellar): implement Stellar Route Performance Forecasting Engine (Closes #530)#670

Merged
mijinummi merged 1 commit into
MDTechLabs:mainfrom
EmeditWeb:Implement-Stellar-Route
Jun 26, 2026
Merged

feat(stellar): implement Stellar Route Performance Forecasting Engine (Closes #530)#670
mijinummi merged 1 commit into
MDTechLabs:mainfrom
EmeditWeb:Implement-Stellar-Route

Conversation

@EmeditWeb

Copy link
Copy Markdown
Contributor

Description

Closes #530.

Adds a real Stellar Route Performance Forecasting Engine under src/forecasting/routes/stellar/ that replaces the existing Math.random() placeholder. The engine ingests historical route metrics, projects forward-looking latency using an exponential moving average, and projects reliability (success rate) using windowed proportions. It also classifies each prediction as improving, stable, or declining and emits a 95% confidence interval plus a composite 0–100 confidence score that grows with sample size and tightens with smaller prediction intervals.

Concept

Users lack visibility into expected future route behavior. This PR introduces an engine that analyzes historical Stellar route metrics and forecasts two key performance dimensions:

  • Latency — the expected transfer duration, in milliseconds, for upcoming transfers on a given route.
  • Reliability — the expected success rate, on [0, 1], for upcoming transfers on a given route.

Both predictions are accompanied by a trend direction and a confidence interval so downstream code (intelligence engines, dashboards, decision engines) can reason about expected behavior rather than relying on instantaneous probes.

Problem

Today there is no contract for predicting Stellar route performance from history. The existing service under src/forecasting/routes/stellar/ returns Math.random() — useless for any consumer wanting to compare routes by future expected behavior.

Changes Made

src/forecasting/routes/stellar/forecasting.service.ts

  • Replaced the Math.random() placeholder with a real NestJS-injectable forecasting engine, StellarRouteForecastingService.
  • Introduced the RouteMetricSample ingestion interface ({ routeId, timestamp, durationMs, success }) and per-route storage capped at maxSamples (default 10 000), with chronological ordering.
  • analyzeHistoricalMetrics(routeId, metrics) now:
    • validates routeId and the input array,
    • silently drops invalid entries (NaN, negative durationMs, invalid timestamp, null elements),
    • sorts chronologically, trims to maxSamples,
    • returns the aggregate RouteHistoricalAnalysis (avg latency, success rate, p95, standard deviation, oldest/newest sample), or null when every sample was invalid.
  • predictLatencyTrends(routeId) returns a LatencyTrendForecast with:
    • point forecast = EMA over the full history (configurable emaAlpha, default 0.3),
    • recent vs historical averages compared to classify the trend,
    • 95% confidence interval derived from the standard deviation,
    • trend: 'improving' | 'stable' | 'declining' (positive trendDelta ⇒ latency decreased ⇒ improving).
  • predictReliabilityTrends(routeId) returns a ReliabilityTrendForecast with:
    • point forecast = windowed success proportion over the recent window,
    • 95% binomial confidence interval, clamped to [0, 1],
    • trend classification comparing recent vs historical success.
  • Both predictors share a unified recentWindowSize() helper so latency and reliability compare against the same lookback.
  • generateForecast(routeId) composes a RouteForecast:
    • legacy fields predictedLatency, predictedReliability, confidenceScore (0–100) kept for backwards compatibility,
    • new full breakdown: latency, reliability, historical.
    • confidenceScore combines a log-shaped sample-count component with inversely-scaled interval widths so denser, tighter data earns higher confidence.
  • Utility methods: reset() and getStoredSamples(routeId) (returns a defensive copy).
  • Constructor validates emaAlpha ∈ (0, 1], trendThreshold ≥ 0, and recentWindowRatio ∈ (0, 1).

src/forecasting/routes/stellar/forecasting.service.spec.ts

  • Replaced the placeholder spec with a comprehensive 28-test suite covering:
    • constructor validation for every option,
    • sanitization of NaN, negative, invalid-timestamp, and null samples,
    • chronological sorting, empty routeId, non-array input, all-invalid returning null,
    • latency trends: improving (downward), declining (upward), stable (flat), 95% CI bounds, EMA alpha sensitivity,
    • reliability trends: improving, declining, stable, CI clamped to [0, 1],
    • generateForecast zero-confidence contract on empty data, complete forecast when data is present,
    • confidence score rises with both larger samples and tighter intervals,
    • reset() and defensive-copy semantics on getStoredSamples().

src/forecasting/routes/stellar/index.ts

  • Unchanged — already re-exports the service via export * from './forecasting.service', so the new types are picked up automatically.

Algorithms

Metric Point forecast Confidence interval Trend signal
Latency EMA(α) over chronological durationMs series EMV ± 1.96·σ/√n (historical − recent) / historical > 0
Reliability Recent-window success proportion p ± 1.96·√(p(1−p)/n) clamped to [0, 1] recent − historical

Both trends normalize so positive trendDelta corresponds to improving (latency down, success up).

Acceptance Criteria Met

  • Forecasting engine implemented. StellarRouteForecastingService is a real, deterministic forecaster — no Math.random().
  • Forecasts generated successfully.
    • 28/28 jest tests pass (npx jest src/forecasting).
    • The new service typechecks clean against the project tsconfig.
    • generateForecast(routeId) produces a typed RouteForecast with confidence intervals and a confidence score when historical data is present, and a non-throwing zero-confidence result otherwise.

How to Use

import { StellarRouteForecastingService } from 'src/forecasting/routes/stellar';

const engine = new StellarRouteForecastingService();
engine.analyzeHistoricalMetrics('route-x', [
  { routeId: 'route-x', timestamp: new Date(Date.now() - 60_000), durationMs: 240, success: true },
  { routeId: 'route-x', timestamp: new Date(),                     durationMs: 180, success: true },
  // …more samples
]);

const latency = engine.predictLatencyTrends('route-x');
//   { predictedLatencyMs, trend: 'improving', confidenceIntervalMs: [low, high], … }

const reliability = engine.predictReliabilityTrends('route-x');
//   { predictedReliability, trend: 'stable', confidenceInterval: [low, high], … }

const forecast = engine.generateForecast('route-x');
//   composite RouteForecast with confidenceScore and historical summary

Out of Scope (intentionally)

  • Time-of-day / seasonal bucketing (potential follow-up).
  • Persistence of historical samples across process restarts (currently in-memory).
  • Live wiring into the apps/api NestJS module and an HTTP endpoint (potential follow-up).
  • UI/dashboard visualization of forecasts (potential follow-up).

@drips-wave

drips-wave Bot commented Jun 26, 2026

Copy link
Copy Markdown

@EmeditWeb Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@mijinummi mijinummi merged commit 04ea93b into MDTechLabs:main Jun 26, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Stellar Route Performance Forecasting

2 participants