4ffde8cc06
- Database migration 018 with 13 tables for trading engine state - Trading engine service (services/trading/) with 12 pure computation modules: position sizer, stop-loss manager, reserve pool, circuit breaker, risk tier controller, correlation matrix, tax lots, trading window, gradual entry, notifications, micro-trading, backtester - Core TradingEngine with pre-trade evaluation pipeline and integration wiring - FastAPI HTTP service with 14 endpoints (health, config, decisions, metrics, backtest) - Performance tracker with Sharpe ratio, drawdown, profit factor computation - 194 Python tests (165 property-based + 29 integration) - Frontend: 13 TanStack Query hooks, 7 dashboard panels, tabbed Trading Engine page - Helm chart entry, network policy, nginx proxy, ingress for trading-engine - Shared infrastructure: enums, Redis keys, TradingConfig in AppConfig
83 lines
2.1 KiB
TypeScript
83 lines
2.1 KiB
TypeScript
/**
|
|
* Shared API client targeting Query API, Symbol Registry, and Risk Engine.
|
|
* Base URLs are configurable via env vars (VITE_*).
|
|
*/
|
|
|
|
const QUERY_API_BASE = import.meta.env.VITE_QUERY_API_URL || '';
|
|
const SYMBOL_REGISTRY_BASE = import.meta.env.VITE_SYMBOL_REGISTRY_URL || '/registry';
|
|
const RISK_ENGINE_BASE = import.meta.env.VITE_RISK_ENGINE_URL || '/risk';
|
|
const TRADING_ENGINE_BASE = import.meta.env.VITE_TRADING_ENGINE_URL || '/trading';
|
|
|
|
export type ApiBase = 'query' | 'registry' | 'risk' | 'trading';
|
|
|
|
function baseUrl(api: ApiBase): string {
|
|
switch (api) {
|
|
case 'query':
|
|
return QUERY_API_BASE;
|
|
case 'registry':
|
|
return SYMBOL_REGISTRY_BASE;
|
|
case 'risk':
|
|
return RISK_ENGINE_BASE;
|
|
case 'trading':
|
|
return TRADING_ENGINE_BASE;
|
|
}
|
|
}
|
|
|
|
export class ApiError extends Error {
|
|
status: number;
|
|
body: unknown;
|
|
|
|
constructor(status: number, body: unknown) {
|
|
super(`API error ${status}`);
|
|
this.name = 'ApiError';
|
|
this.status = status;
|
|
this.body = body;
|
|
}
|
|
}
|
|
|
|
export async function apiFetch<T>(
|
|
api: ApiBase,
|
|
path: string,
|
|
init?: RequestInit,
|
|
): Promise<T> {
|
|
const url = `${baseUrl(api)}${path}`;
|
|
const res = await fetch(url, {
|
|
...init,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
...init?.headers,
|
|
},
|
|
});
|
|
if (!res.ok) {
|
|
const body = await res.json().catch(() => null);
|
|
throw new ApiError(res.status, body);
|
|
}
|
|
return res.json() as Promise<T>;
|
|
}
|
|
|
|
/** Convenience GET */
|
|
export function apiGet<T>(api: ApiBase, path: string): Promise<T> {
|
|
return apiFetch<T>(api, path);
|
|
}
|
|
|
|
/** Convenience POST */
|
|
export function apiPost<T>(api: ApiBase, path: string, body: unknown): Promise<T> {
|
|
return apiFetch<T>(api, path, {
|
|
method: 'POST',
|
|
body: JSON.stringify(body),
|
|
});
|
|
}
|
|
|
|
/** Convenience PUT */
|
|
export function apiPut<T>(api: ApiBase, path: string, body: unknown): Promise<T> {
|
|
return apiFetch<T>(api, path, {
|
|
method: 'PUT',
|
|
body: JSON.stringify(body),
|
|
});
|
|
}
|
|
|
|
/** Convenience DELETE */
|
|
export function apiDelete<T>(api: ApiBase, path: string): Promise<T> {
|
|
return apiFetch<T>(api, path, { method: 'DELETE' });
|
|
}
|