feat: override trade tab — manual order entry with auto-registration
Backend: - OverrideOrderRequest/Response Pydantic models with ticker, quantity, price validators - POST /api/trading/override/order endpoint (enqueue to Redis broker queue) - auto_register_symbol() module for untracked ticker registration via Symbol Registry - Unit tests (17) and property-based tests (3 x 100 examples) Frontend: - OverrideTradePanel component (order form + positions display) - Override tab in TradingEngine page with URL search param navigation - Override Trade button on Trading Controls page - useSubmitOverrideOrder mutation hook - MSW handler and 13 component/integration tests Steering: - Updated steering docs for Ubuntu dev machine with nvm/Node 24
This commit is contained in:
@@ -336,3 +336,39 @@ export function useUpdateNotificationConfig() {
|
||||
onSuccess: () => qc.invalidateQueries({ queryKey: ['notification-config'] }),
|
||||
});
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Override Order (manual trade submission)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface OverrideOrderRequest {
|
||||
ticker: string;
|
||||
side: 'buy' | 'sell';
|
||||
quantity: number;
|
||||
order_type: 'market' | 'limit' | 'stop' | 'stop_limit';
|
||||
limit_price?: number;
|
||||
stop_price?: number;
|
||||
}
|
||||
|
||||
export interface OverrideOrderResponse {
|
||||
job_id: string;
|
||||
status: string;
|
||||
ticker: string;
|
||||
side: string;
|
||||
quantity: number;
|
||||
auto_registered: boolean;
|
||||
}
|
||||
|
||||
/** Submit a manual override order to the trading engine. */
|
||||
export function useSubmitOverrideOrder() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (body: OverrideOrderRequest) =>
|
||||
apiPost<OverrideOrderResponse>('trading', '/api/trading/override/order', body),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['orders'] });
|
||||
qc.invalidateQueries({ queryKey: ['positions'] });
|
||||
qc.invalidateQueries({ queryKey: ['companies'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user