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
5c309bc
docs: add six-dimension platform optimization roadmap
rogerdigital May 7, 2026
63cdd49
chore: enable TypeScript strict mode and add structured error codes
rogerdigital May 7, 2026
563ad25
test(trading-engine): add unit tests for risk, core, and market modules
rogerdigital May 7, 2026
5df28be
ci: add Vitest coverage reporting and coverage job to CI
rogerdigital May 7, 2026
4833806
feat(api): add versioned API routing with /api/v1 prefix
rogerdigital May 7, 2026
51ceb6e
feat(api): add in-memory LRU cache with TTL for hot endpoints
rogerdigital May 7, 2026
56e56a4
feat(trading-engine): add advanced slippage and commission models
rogerdigital May 7, 2026
7313f44
feat(execution): add algo order strategies and order lifecycle state …
rogerdigital May 7, 2026
b0a23cb
feat(execution): add retry handler and smart order router
rogerdigital May 7, 2026
a919176
feat(execution): wire algo order strategies into ExecutionPage UI
rogerdigital May 7, 2026
05b2b3d
feat(risk): enhance VaR engine with parametric/Monte Carlo methods, s…
rogerdigital May 7, 2026
486ba28
feat(risk): add portfolio risk analytics panels to RiskPage
rogerdigital May 7, 2026
f6d0484
feat(market): add feed manager and bar aggregator for real-time data
rogerdigital May 7, 2026
107667b
feat(market): add Level 2 order book and depth chart to MarketPage
rogerdigital May 7, 2026
b5a34b2
feat(notifications): add multi-channel notification delivery system
rogerdigital May 7, 2026
8908341
feat(auth): add registration, refresh tokens, password reset, and tea…
rogerdigital May 8, 2026
84776e3
feat(auth): add MFA enrollment, verification, and challenge endpoints
rogerdigital May 8, 2026
d20f8c0
feat(web): create @quantpilot/ui component library package
rogerdigital May 8, 2026
7674dc7
feat(ui): build atomic components (Button, Input, Select, Modal, Tabl…
rogerdigital May 8, 2026
bfda6ea
feat(web): enhance charts with technical indicators and depth visuali…
rogerdigital May 8, 2026
cbf03df
feat(web): implement dark/light theme system
rogerdigital May 8, 2026
b3755fb
feat(web): add responsive breakpoints and mobile layout shell
rogerdigital May 8, 2026
204124d
feat(web): optimize core pages for mobile viewing
rogerdigital May 8, 2026
4a34ce1
feat(web): implement global keyboard shortcut system
rogerdigital May 8, 2026
1c346a2
feat(ui): add skeleton loading components and page-level skeletons
rogerdigital May 8, 2026
8810f7b
feat(trading): add persistent quick order bar to trading page
rogerdigital May 8, 2026
24a6353
feat(ui): add real-time data feedback animations (PriceFlash, PnLAnim…
rogerdigital May 8, 2026
1654f2c
feat(layout): add resizable split pane and configurable trading works…
rogerdigital May 8, 2026
ea47b98
feat(ui): enhance empty states with contextual guidance and action CTAs
rogerdigital May 8, 2026
c61cf17
feat(ui): add inline error handling (ErrorBanner, FormValidationError…
rogerdigital May 8, 2026
b0d5ccd
feat(ui): enhance command palette with recent actions, fuzzy matching…
rogerdigital May 8, 2026
b571895
feat(onboarding): add step-by-step setup wizard for new users
rogerdigital May 8, 2026
f40702f
feat(strategies): add strategy marketplace with browse, search, and fork
rogerdigital May 8, 2026
66977fd
feat(trading): add paper trading performance journal and promotion cr…
rogerdigital May 8, 2026
75252d6
feat(trading-engine): add multi-asset support with options pricing an…
rogerdigital May 8, 2026
c25c611
feat(strategies): add strategy sharing and team collaboration
rogerdigital May 8, 2026
0ec1d63
feat(analytics): add performance analytics and reporting page
rogerdigital May 8, 2026
62ef3cb
feat(api): add data export and interactive API documentation
rogerdigital May 8, 2026
bad1663
fix: resolve biome lint errors in new components
rogerdigital May 8, 2026
93f3d32
fix(api): replace controlPlaneRuntime.getStore() with proper context …
rogerdigital May 8, 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
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ VITE_MARKET_DATA_HTTP_URL=
VITE_BROKER_PROVIDER=simulated
VITE_BROKER_HTTP_URL=

VITE_ALPACA_PROXY_BASE=/api/alpaca
VITE_ALPACA_PROXY_BASE=/api/v1/alpaca

# Gateway
GATEWAY_PORT=8787
Expand Down
25 changes: 24 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,30 @@ jobs:
- run: npm ci
- run: npm run test:${{ matrix.suite }}

# ── 4. Build ──────────────────────────────────────────────────────────────
# ── 4. Coverage ───────────────────────────────────────────────────────────
coverage:
name: Coverage
runs-on: ubuntu-latest
needs: [test]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: npm
- name: Install build tools (for native addons)
run: sudo apt-get install -y python3 make g++
- run: npm ci
- name: Generate web coverage
run: npm run test:web -- --coverage
- name: Upload coverage report
uses: actions/upload-artifact@v4
with:
name: coverage-lcov
path: apps/web/coverage/lcov.info
retention-days: 14

# ── 5. Build ──────────────────────────────────────────────────────────────
build:
name: build
runs-on: ubuntu-latest
Expand Down
10 changes: 10 additions & 0 deletions apps/api/src/app/routes/platform-routes.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
// @ts-nocheck

import { handleAgentRoutes } from './routers/agent-router.js';
import { handleAnalyticsRoutes } from './routers/analytics-router.js';
import { handleAuthRoutes } from './routers/auth-router.js';
import { handleBacktestRoutes } from './routers/backtest-router.js';
import { handleCollaborationRoutes } from './routers/collaboration-router.js';
import { handleDocsRoutes } from './routers/docs-router.js';
import { handleExecutionRoutes } from './routers/execution-router.js';
import { handleExportRoutes } from './routers/export-router.js';
import { handleHealthRoutes } from './routers/health-router.js';
import { handleMarketRoutes } from './routers/market-router.js';
import { handleMarketplaceRoutes } from './routers/marketplace-router.js';
import { handleMonitoringRoutes } from './routers/monitoring-router.js';
import { handleOperationsRoutes } from './routers/operations-router.js';
import { handleResearchRoutes } from './routers/research-router.js';
Expand All @@ -28,6 +33,11 @@ const routers = [
handleExecutionRoutes,
handleTradingRoutes,
handleMarketRoutes,
handleMarketplaceRoutes,
handleCollaborationRoutes,
handleAnalyticsRoutes,
handleExportRoutes,
handleDocsRoutes,
];

export async function handlePlatformRoutes(context) {
Expand Down
128 changes: 128 additions & 0 deletions apps/api/src/app/routes/routers/analytics-router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// @ts-nocheck

function generateDemoPerformanceData(range) {
const daysMap = { '1M': 22, '3M': 66, '6M': 126, '1Y': 252, ALL: 504 };
const days = daysMap[range] || 252;

// Generate equity curve with realistic random walk
const equityCurve = [100000];
for (let i = 1; i < days; i++) {
const drift = 0.0003;
const volatility = 0.015;
const change = drift + volatility * (Math.random() * 2 - 1);
equityCurve.push(equityCurve[i - 1] * (1 + change));
}

const finalEquity = equityCurve[equityCurve.length - 1];
const totalReturn = (finalEquity - equityCurve[0]) / equityCurve[0];
const years = days / 252;
const cagr = (1 + totalReturn) ** (1 / years) - 1;

// Generate daily returns
const dailyReturns = [];
for (let i = 1; i < equityCurve.length; i++) {
dailyReturns.push((equityCurve[i] - equityCurve[i - 1]) / equityCurve[i - 1]);
}

const mean = dailyReturns.reduce((s, r) => s + r, 0) / dailyReturns.length;
const variance = dailyReturns.reduce((s, r) => s + (r - mean) ** 2, 0) / dailyReturns.length;
const std = Math.sqrt(variance);
const sharpe = std > 0 ? (mean / std) * Math.sqrt(252) : 0;

const negReturns = dailyReturns.filter((r) => r < 0);
const downVar =
negReturns.length > 0 ? negReturns.reduce((s, r) => s + r * r, 0) / negReturns.length : 0;
const sortino =
downVar > 0 ? (mean / Math.sqrt(downVar)) * Math.sqrt(252) : sharpe > 0 ? Infinity : 0;

// Max drawdown
let peak = equityCurve[0];
let maxDd = 0;
const drawdownSeries = equityCurve.map((eq) => {
if (eq > peak) peak = eq;
const dd = peak > 0 ? (eq - peak) / peak : 0;
if (dd < maxDd) maxDd = dd;
return dd;
});

// Trade metrics
const totalTrades = Math.floor(days * 0.3);
const tradePnLs = Array.from({ length: totalTrades }, () => (Math.random() * 2 - 0.4) * 2000);
const wins = tradePnLs.filter((p) => p > 0);
const losses = tradePnLs.filter((p) => p < 0);
const winRate = wins.length / totalTrades;
const grossProfit = wins.reduce((s, p) => s + p, 0);
const grossLoss = Math.abs(losses.reduce((s, p) => s + p, 0));
const profitFactor = grossLoss > 0 ? grossProfit / grossLoss : grossProfit > 0 ? Infinity : 0;

// Monthly returns
const monthlyReturns = {};
let monthStart = equityCurve[0];
let currentMonth = 0;
for (let i = 0; i < equityCurve.length; i++) {
const month = Math.floor(i / 22);
if (month !== currentMonth) {
const year = 2024 + Math.floor(currentMonth / 12);
const m = String((currentMonth % 12) + 1).padStart(2, '0');
if (!monthlyReturns[year]) monthlyReturns[year] = {};
monthlyReturns[year][m] = monthStart > 0 ? (equityCurve[i - 1] - monthStart) / monthStart : 0;
monthStart = equityCurve[i];
currentMonth = month;
}
}
// Final month
const year = 2024 + Math.floor(currentMonth / 12);
const m = String((currentMonth % 12) + 1).padStart(2, '0');
if (!monthlyReturns[year]) monthlyReturns[year] = {};
monthlyReturns[year][m] =
monthStart > 0 ? (equityCurve[equityCurve.length - 1] - monthStart) / monthStart : 0;

// Trade distribution
const buckets = [
{ range: '< -5%', min: -Infinity, max: -0.05 },
{ range: '-5% ~ -3%', min: -0.05, max: -0.03 },
{ range: '-3% ~ -1%', min: -0.03, max: -0.01 },
{ range: '-1% ~ 0%', min: -0.01, max: 0 },
{ range: '0% ~ 1%', min: 0, max: 0.01 },
{ range: '1% ~ 3%', min: 0.01, max: 0.03 },
{ range: '3% ~ 5%', min: 0.03, max: 0.05 },
{ range: '> 5%', min: 0.05, max: Infinity },
];
const tradeDistribution = buckets.map((b) => ({
range: b.range,
count: tradePnLs.filter((p) => {
const pct = p / 100000;
return pct >= b.min && pct < b.max;
}).length,
}));

return {
summary: {
totalReturn,
cagr,
sharpe,
sortino,
maxDrawdown: Math.abs(maxDd),
winRate,
profitFactor,
tradingDays: days,
totalTrades,
},
equityCurve: equityCurve.slice(-252),
drawdownSeries: drawdownSeries.slice(-252),
monthlyReturns,
tradeDistribution,
};
}

export async function handleAnalyticsRoutes({ req, reqUrl, res, writeJson }) {
// GET /api/analytics/performance
if (req.method === 'GET' && reqUrl.pathname === '/api/analytics/performance') {
const range = reqUrl.searchParams.get('range') || '1Y';
const data = generateDemoPerformanceData(range);
writeJson(res, 200, { ok: true, data });
return true;
}

return false;
}
Loading
Loading