Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
498d95e
Hardening Pass 3 Phase A: persist live execution state
pipsandtits Aug 19, 2026
4fcd6d2
Hardening Pass 3 Phase B: add fill and funding accounting
pipsandtits Aug 19, 2026
eb818e8
Hardening Pass 3: close reconciliation and funding gaps
pipsandtits Aug 19, 2026
314ea72
Hardening Pass 3: restore funding coverage resolution
pipsandtits Aug 19, 2026
3cf3533
Hardening Pass 4A: add fee and funding conversion
pipsandtits Aug 19, 2026
c4319ff
Merge pull request #1 from pipsandtits/devin/1787144788-hardening-pass-3
pipsandtits Aug 19, 2026
cff7303
Hardening Pass 4B: close conversion and cache gaps
pipsandtits Aug 19, 2026
ab5d3ce
Hardening Pass 4C: add parity and failure fixtures
pipsandtits Aug 19, 2026
67cd4ba
Hardening Pass 4C: rework observed parity fixtures
pipsandtits Aug 19, 2026
47393dc
Hardening Pass 4D: secure and cover route surfaces
pipsandtits Aug 19, 2026
6f9c3c1
Hardening Pass 4E: classify legacy gaps and measure indicators
pipsandtits Aug 19, 2026
d36f01b
Correct Pass 4E indicator cost measurement
pipsandtits Aug 19, 2026
6076e01
Note model-performance in the Pass 4D route summary
pipsandtits Aug 19, 2026
d1dcea9
Pass 5 Batch 1: cover read-mostly routes
pipsandtits Aug 19, 2026
a30072c
Pass 5 Batch 2: cover agent routes
pipsandtits Aug 19, 2026
c3b41f1
Pass 5 Batch 3: cover backtest routes
pipsandtits Aug 19, 2026
1ce9f66
Pass 5 Batch 4a: cover strategies, signal generation, and symbol univ…
pipsandtits Aug 19, 2026
30bb8f3
Pass 5 Batch 4b: cover user settings and gateway
pipsandtits Aug 19, 2026
263bbfa
Pass 5 Batch 4c: restore read-only gateway compatibility
pipsandtits Aug 19, 2026
be34bbc
Pass 5 Batch 4d: restore safe legacy strategy routes
pipsandtits Aug 19, 2026
11e756f
Pass 5 Batch 4d: cover strategy result reads
pipsandtits Aug 19, 2026
c02fc8f
Track 2 T1: fix verified runtime type defects
pipsandtits Aug 19, 2026
74dda04
Track 2 T2: narrow server route parameters
pipsandtits Aug 19, 2026
dc5c888
Track 2 T3: finish type baseline
pipsandtits Aug 19, 2026
117c91e
Track 2 T3: align ML consensus response shape
pipsandtits Aug 19, 2026
f6827b8
Document Pass 5 readiness status
pipsandtits Aug 19, 2026
0754d51
Merge pull request #2 from pipsandtits/devin/1787147929-hardening-pass-4
pipsandtits Aug 19, 2026
45a4af6
Fix review findings for cache funding and route guards
pipsandtits Aug 19, 2026
4726133
Refuse ambiguous funding ledger attribution
pipsandtits Aug 19, 2026
520ee58
Operator-gate model history pruning
pipsandtits Aug 19, 2026
49b5f37
Apply suggestion for server/routes/strategies-compat.ts
pipsandtits Aug 19, 2026
d2dafbc
Apply suggestion for server/routes/api-docs.ts
pipsandtits Aug 19, 2026
e9ec702
Apply suggestion for server/routes/api-docs.ts
pipsandtits Aug 19, 2026
0ee12ce
Fix reviewed route boundary defects
pipsandtits Aug 19, 2026
0e2b8c7
Add shared API access identity stopgap
pipsandtits Aug 19, 2026
f7d1409
Harden route parameter error responses
pipsandtits Aug 19, 2026
8762a44
Keep chart and MDL data paths lazy
pipsandtits Aug 19, 2026
c2659d0
Drop redundant barSeries pass-through
pipsandtits Aug 19, 2026
4e020e4
Restore chart data API without native rendering
pipsandtits Aug 19, 2026
d525eba
Merge pull request #3 from pipsandtits
pipsandtits Aug 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
786 changes: 762 additions & 24 deletions PRODUCTION_READINESS.md

Large diffs are not rendered by default.

25 changes: 20 additions & 5 deletions client/components/AutomatedTradingDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,22 @@ const AutomatedTradingDashboard: React.FC<{
const activeTradesQ = useActiveTrades();
const statsQ = useTradeStats();
const activeTrades = activeTradesQ.data?.trades || [];
const stats = statsQ.data?.stats || null;
const rawStats = statsQ.data?.stats;
const stats: TradeStatistics | null = rawStats ? {
totalTrades: rawStats.totalTrades ?? 0,
winningTrades: rawStats.winningTrades ?? 0,
losingTrades: rawStats.losingTrades ?? 0,
winRate: rawStats.winRate ?? 0,
averageProfitUSD: rawStats.averageProfitUSD ?? 0,
averageLossUSD: rawStats.averageLossUSD ?? 0,
profitFactor: rawStats.profitFactor ?? 0,
totalProfitLoss: rawStats.totalProfitLoss ?? 0,
largestWin: rawStats.largestWin ?? 0,
largestLoss: rawStats.largestLoss ?? 0,
maxConsecutiveWins: 0,
maxConsecutiveLosses: 0,
averageDurationMinutes: 0,
} : null;

// Calculate risk metrics
const riskMetrics: RiskMetrics = {
Expand Down Expand Up @@ -187,7 +202,7 @@ const AutomatedTradingDashboard: React.FC<{
<div className="bg-white rounded-lg border border-gray-200 p-4">
<p className="text-sm text-gray-600">Win Rate</p>
<p className="text-3xl font-bold text-indigo-600">
{stats ? `${(stats.winRate * 100).toFixed(0)}%` : 'N/A'}
{stats?.winRate !== undefined ? `${(stats.winRate * 100).toFixed(0)}%` : 'N/A'}
</p>
<p className="text-xs text-gray-500 mt-1">
{stats ? `${stats.winningTrades}W / ${stats.losingTrades}L` : 'No trades'}
Expand Down Expand Up @@ -258,14 +273,14 @@ const AutomatedTradingDashboard: React.FC<{
<td className="px-4 py-3 text-right">
<span
className={`px-2 py-1 rounded text-xs font-semibold ${
trade.confidence > 0.8
(trade.confidence ?? 0) > 0.8
? 'bg-blue-100 text-blue-700'
: trade.confidence > 0.6
: (trade.confidence ?? 0) > 0.6
? 'bg-yellow-100 text-yellow-700'
: 'bg-orange-100 text-orange-700'
}`}
>
{(trade.confidence * 100).toFixed(0)}%
{((trade.confidence ?? 0) * 100).toFixed(0)}%
</span>
</td>
<td className="px-4 py-3 text-center">
Expand Down
2 changes: 1 addition & 1 deletion client/components/BacktestResultsSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

import React, { useState, Suspense } from 'react';
import AreaChartCore from './charts/AreaChartCore';
import AreaChartCore from '@/components/charts/AreaChartCore';
import { useBacktestResults } from '@/lib/hooks';
const BacktestResultsChartsImpl = React.lazy(() => import('./BacktestResultsChartsImpl'));

Expand Down
24 changes: 16 additions & 8 deletions client/components/MLConsensusWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ interface TimeframeConfidence {
direction: string;
confidence: number;
strength: number;
probability: number;
price: number;
pricChangePct: number;
riskScore: number;
volatility: number;
riskLevel: string;
volatility: string;
regimeDuration: string;
weight: number;
}

Expand All @@ -40,7 +43,7 @@ interface MLConsensusData {
timeframes: TimeframeConfidence[];
aggregatedMetrics: {
avgRiskScore: number;
maxVolatility: number;
maxVolatility: string;
shortestRegimeDuration: string;
velocityConfidenceAvg: number;
};
Expand Down Expand Up @@ -121,12 +124,17 @@ export const MLConsensusWidget: React.FC<MLConsensusWidgetProps> = ({
}

const consensus = data.consensus;
const metrics = data.aggregatedMetrics;
const metrics = data.aggregatedMetrics ?? {
avgRiskScore: 0,
maxVolatility: 'unknown',
shortestRegimeDuration: 'unknown',
velocityConfidenceAvg: 0,
};
const directionColor = getDirectionColor(consensus.direction);
const riskLevel = getRiskLevel(metrics.avgRiskScore);

// Prepare timeframe data for chart
const timeframeChartData = data.timeframes.map((tf: TimeframeConfidence) => ({
const timeframeChartData = data.timeframes.map((tf) => ({
timeframe: tf.timeframe,
confidence: tf.confidence * 100,
strength: tf.strength,
Expand Down Expand Up @@ -263,7 +271,7 @@ export const MLConsensusWidget: React.FC<MLConsensusWidgetProps> = ({
</tr>
</thead>
<tbody>
{data.timeframes.map((tf: TimeframeConfidence) => (
{data.timeframes.map((tf) => (
<tr key={tf.timeframe} className="border-b border-gray-100 hover:bg-gray-50">
<td className="px-3 py-2 font-medium text-gray-800">{tf.timeframe}</td>
<td className="px-3 py-2">
Expand All @@ -286,7 +294,7 @@ export const MLConsensusWidget: React.FC<MLConsensusWidgetProps> = ({
</span>
</td>
<td className="px-3 py-2 text-right text-gray-700">
{(tf.volatility * 100).toFixed(1)}%
{tf.volatility}
</td>
<td className="px-3 py-2 text-right text-gray-700 font-medium">
{(tf.weight * 100).toFixed(0)}%
Expand All @@ -302,7 +310,7 @@ export const MLConsensusWidget: React.FC<MLConsensusWidgetProps> = ({
<div className="grid grid-cols-3 gap-4 p-4 bg-gray-50 rounded-lg border border-gray-200">
<div>
<p className="text-xs text-gray-600 font-semibold uppercase mb-1">Max Volatility</p>
<p className="text-lg font-bold text-gray-800">{(metrics.maxVolatility * 100).toFixed(1)}%</p>
<p className="text-lg font-bold text-gray-800">{metrics.maxVolatility}</p>
</div>
<div>
<p className="text-xs text-gray-600 font-semibold uppercase mb-1">Regime Duration</p>
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/AdaptiveHoldingPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Allows users to measure impact of regime-aware and flow-based holding strategies
*/

import React, { useState, lazy } from 'react';
import React, { useState, Suspense, lazy } from 'react';
import { TrendingUp, Clock, Users, Zap, CheckCircle2, AlertCircle, BarChart3, PieChart } from 'lucide-react';
import { BarChart, Bar, LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
const AdaptiveHoldingCharts = lazy(() => import('@/components/AdaptiveHoldingCharts'));
Expand Down
15 changes: 10 additions & 5 deletions client/src/components/AgentSignalHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,16 @@ export default function AgentSignalHistory({
<CardContent>
{chartData.length > 0 ? (
<div style={{ width: '100%', height: 300 }}>
<BarChartCore data={chartData} dataKey="BUY" height={300}>
<Bar dataKey="BUY" stackId="a" fill="#10b981" radius={[8, 8, 0, 0]} />
<Bar dataKey="HOLD" stackId="a" fill="#f59e0b" radius={[8, 8, 0, 0]} />
<Bar dataKey="SELL" stackId="a" fill="#ef4444" radius={[8, 8, 0, 0]} />
</BarChartCore>
<BarChartCore
data={chartData}
dataKey="BUY"
height={300}
barSeries={[
{ dataKey: 'BUY', stackId: 'a', fill: '#10b981', radius: [8, 8, 0, 0] },
{ dataKey: 'HOLD', stackId: 'a', fill: '#f59e0b', radius: [8, 8, 0, 0] },
{ dataKey: 'SELL', stackId: 'a', fill: '#ef4444', radius: [8, 8, 0, 0] },
]}
/>
</div>
) : (
<div className="h-64 flex items-center justify-center text-slate-400">
Expand Down
5 changes: 3 additions & 2 deletions client/src/components/BasicChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useState, useEffect } from 'react';
import { LineChartCore, BarChartCore } from './charts';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import type { ChartDataPoint } from '@/types/chart';
import { Bar } from 'recharts';

interface BasicChartProps {
symbol: string;
Expand Down Expand Up @@ -43,8 +44,8 @@ export function BasicChart({
);
}

const minPrice = Math.min(...data.map(d => d.price));
const maxPrice = Math.max(...data.map(d => d.price));
const minPrice = Math.min(...data.map(d => d.close));
const maxPrice = Math.max(...data.map(d => d.close));
const priceRange = maxPrice - minPrice;
const yAxisDomain = [
Math.max(0, minPrice - priceRange * 0.1),
Expand Down
13 changes: 12 additions & 1 deletion client/src/components/ComboNotifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,18 @@ export const ComboNotificationContainer: React.FC<ComboNotificationContainerProp
// append any new combos not already in toasts
setToasts(prev => {
const existing = new Set(prev.map((t) => t.id));
const incoming = combosData.filter((c: any) => !existing.has(c.id));
const incoming: ComboNotification[] = combosData
.filter((c) => !existing.has(c.id))
.map((c) => ({
id: c.id,
timestamp: c.timestamp,
comboName: c.comboName,
agents: c.agents,
bonusMultiplier: c.bonusMultiplier ?? 1,
description: c.description ?? '',
impact: c.impact ?? 0,
duration: c.duration ?? 0,
}));
return [...prev, ...incoming];
});
}, [combosData]);
Expand Down
10 changes: 8 additions & 2 deletions client/src/components/FeatureImportanceDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,14 @@ export function FeatureImportanceDashboard() {
}
});

const features = importanceQ.data?.data || [];
const features = (importanceQ.data?.data || []).map((feature) => ({
...feature,
correlationWithSuccess: feature.correlationWithSuccess ?? 0,
usageFrequency: feature.usageFrequency ?? 0,
avgContribution: feature.avgContribution ?? 0,
}));
const featureSets = featureSetsQ.data?.data || [];
const loadingSets = featureSetsQ.isLoading;

const topFeatures = features.slice(0, 15);
const lowFeatures = features.slice(-10).reverse();
Expand Down Expand Up @@ -264,7 +270,7 @@ export function FeatureImportanceDashboard() {
</div>
) : (
<div className="grid gap-4 md:grid-cols-2">
{featureSets.map((set: any) => (
{featureSets.map((set) => (
<Card key={set.id} data-testid={`ab-test-set-${set.id}`}>
<CardContent className="pt-4">
<div className="flex justify-between items-start mb-2">
Expand Down
29 changes: 22 additions & 7 deletions client/src/components/charts/AreaChartCoreImpl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,38 @@ import React from 'react';
import { ResponsiveContainer, AreaChart, Area, CartesianGrid, XAxis, YAxis, Tooltip, Legend, ReferenceLine } from 'recharts';

interface AreaChartCoreProps {
data: any[];
data: Record<string, unknown>[];
dataKey: string;
height?: number;
gradientId?: string;
stroke?: string;
fill?: string;
yFormatter?: (v: any) => string;
xFormatter?: (v: any) => string;
yFormatter?: (v: number) => string;
xFormatter?: (v: string | number) => string;
children?: React.ReactNode;
xDataKey?: string;
hideXAxis?: boolean;
hideYAxis?: boolean;
yDomain?: any;
referenceLines?: Array<any>;
yDomain?: [number | 'auto', number | 'auto'];
referenceLines?: Array<Record<string, unknown>>;
}

export default function AreaChartCoreImpl({ data, dataKey, height = 200, gradientId = 'areaGradient', stroke = '#3b82f6', fill = '#3b82f6', yFormatter, xFormatter, children }: AreaChartCoreProps) {
export default function AreaChartCoreImpl({
data,
dataKey,
height = 200,
gradientId = 'areaGradient',
stroke = '#3b82f6',
fill = '#3b82f6',
yFormatter,
xFormatter,
children,
xDataKey = 'timestamp',
hideXAxis,
hideYAxis,
yDomain,
referenceLines,
}: AreaChartCoreProps) {
return (
<ResponsiveContainer width="100%" height="100%">
<AreaChart data={data}>
Expand All @@ -29,7 +44,7 @@ export default function AreaChartCoreImpl({ data, dataKey, height = 200, gradien
</linearGradient>
</defs>
<CartesianGrid strokeDasharray="3 3" stroke="#334155" />
<XAxis dataKey={(xDataKey as any) || 'timestamp'} stroke="#94a3b8" tickFormatter={xFormatter} hide={hideXAxis} />
<XAxis dataKey={xDataKey} stroke="#94a3b8" tickFormatter={xFormatter} hide={hideXAxis} />
<YAxis stroke="#94a3b8" tickFormatter={yFormatter} hide={hideYAxis} domain={yDomain} />
<Tooltip />
<Area type="monotone" dataKey={dataKey} stroke={stroke} fill={`url(#${gradientId})`} />
Expand Down
48 changes: 37 additions & 11 deletions client/src/components/charts/BarChartCoreImpl.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,44 @@
import React from 'react';
import { ResponsiveContainer, BarChart, Bar, CartesianGrid, XAxis, YAxis, Tooltip, Legend, Cell } from 'recharts';

export interface BarSeries {
dataKey: string;
stackId?: string | number;
fill?: string;
radius?: number | [number, number, number, number];
}

interface BarChartCoreProps {
data: any[];
data: Record<string, unknown>[];
dataKey: string;
layout?: 'vertical' | 'horizontal';
height?: number;
children?: React.ReactNode;
barSeries?: BarSeries[];
cellColors?: string[];
barProps?: any;
xAxisProps?: any;
yAxisProps?: any;
gridProps?: any;
tooltipProps?: any;
legendProps?: any;
barProps?: Record<string, unknown>;
xAxisProps?: Record<string, unknown>;
yAxisProps?: Record<string, unknown>;
gridProps?: Record<string, unknown>;
tooltipProps?: Record<string, unknown>;
legendProps?: Record<string, unknown>;
}

export default function BarChartCoreImpl({ data, dataKey, layout = 'horizontal', height = 200, children, cellColors, barProps }: BarChartCoreProps) {
export default function BarChartCoreImpl({
data,
dataKey,
layout = 'horizontal',
height = 200,
children,
barSeries,
cellColors,
barProps,
xAxisProps,
yAxisProps,
gridProps,
tooltipProps,
legendProps,
}: BarChartCoreProps) {
return (
<ResponsiveContainer width="100%" height="100%">
<BarChart data={data} layout={layout}>
Expand All @@ -26,9 +48,13 @@ export default function BarChartCoreImpl({ data, dataKey, layout = 'horizontal',
<Tooltip {...(tooltipProps || {})} />
<Legend {...(legendProps || {})} />
{children ?? (
<Bar dataKey={dataKey} fill="#3b82f6" {...barProps}>
{cellColors && cellColors.length > 0 && cellColors.map((c, i) => <Cell key={i} fill={c} />)}
</Bar>
barSeries && barSeries.length > 0
? barSeries.map((series) => <Bar key={series.dataKey} {...series} />)
: (
<Bar dataKey={dataKey} fill="#3b82f6" {...barProps}>
{cellColors && cellColors.length > 0 && cellColors.map((c, i) => <Cell key={i} fill={c} />)}
</Bar>
)
)}
</BarChart>
</ResponsiveContainer>
Expand Down
Loading
Loading