MyMidas/frontend/src/api/predictions.ts
megaproxy 2940b120e0 ML predictions Phase 5: Monte Carlo contribution fix and milestone table
Fix contribution compounding: monthly contributions are now added to
asset values before each GBM step so they grow with market returns,
rather than being summed as a static lump at each period.

Add year-by-year milestone table below the fan chart showing P10/P50/P90
portfolio values at each annual checkpoint up to the selected horizon.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 11:02:41 +00:00

129 lines
3.1 KiB
TypeScript

import { api } from "./client";
export interface CategoryForecast {
category_id: string;
category_name: string;
monthly_avg: number;
algorithm: "sarima" | "holt_winters" | "average";
actuals: { date: string; amount: number }[];
forecast: { date: string; amount: number; lower: number; upper: number; lower_95: number; upper_95: number }[];
}
export interface SpendingForecastResponse {
categories: CategoryForecast[];
}
export interface NetWorthProjectionResponse {
history: { date: string; value: number }[];
projections: {
conservative: { date: string; value: number }[];
base: { date: string; value: number }[];
optimistic: { date: string; value: number }[];
};
insufficient_data: boolean;
}
export interface PercentilePath {
date: string;
value: number;
}
export interface MonteCarloMilestone {
year: number;
date: string;
p10: number;
p50: number;
p90: number;
}
export interface MonteCarloResponse {
dates: string[];
percentiles: {
p10: PercentilePath[];
p25: PercentilePath[];
p50: PercentilePath[];
p75: PercentilePath[];
p90: PercentilePath[];
};
current_value: number;
expected_value: number;
probability_of_gain: number;
milestones: MonteCarloMilestone[];
insufficient_data: boolean;
}
export interface BudgetForecastItem {
category_id: string;
category_name: string;
budget_amount: number;
spent_so_far: number;
forecast_month_total: number;
daily_velocity: number;
probability_overspend: number;
days_remaining: number;
}
export interface BudgetForecastResponse {
forecasts: BudgetForecastItem[];
message?: string;
}
export interface CashFlowDay {
date: string;
balance: number;
upper: number;
lower: number;
avg_inflow: number;
avg_outflow: number;
negative_risk: boolean;
}
export interface UpcomingPayment {
name: string;
date: string;
amount: number;
at_risk: boolean;
}
export interface CashFlowResponse {
current_balance: number;
avg_daily_inflow: number;
avg_daily_outflow: number;
forecast: CashFlowDay[];
negative_risk_days: string[];
upcoming_payments: UpcomingPayment[];
history_days: number;
}
export async function getSpendingForecast(): Promise<SpendingForecastResponse> {
const res = await api.get("/predictions/spending");
return res.data;
}
export async function getNetWorthProjection(years = 5): Promise<NetWorthProjectionResponse> {
const res = await api.get("/predictions/net-worth", { params: { years } });
return res.data;
}
export async function postMonteCarlo(params: {
years?: number;
n_simulations?: number;
annual_contribution?: number;
}): Promise<MonteCarloResponse> {
const res = await api.post("/predictions/monte-carlo", {
years: params.years ?? 5,
n_simulations: params.n_simulations ?? 1000,
annual_contribution: params.annual_contribution ?? 0,
});
return res.data;
}
export async function getBudgetForecast(): Promise<BudgetForecastResponse> {
const res = await api.get("/predictions/budget-forecast");
return res.data;
}
export async function getCashFlowForecast(): Promise<CashFlowResponse> {
const res = await api.get("/predictions/cashflow");
return res.data;
}