trading-platform/apps/mcp-binance-connector/src/middleware/risk-check.ts
rckrdmrd c1b5081208 feat(ml): Complete FASE 11 - BTCUSD update and comprehensive documentation alignment
ML Engine Updates:
- Updated BTCUSD with Polygon API data (2024-2025): 215,699 new records
- Re-trained all ML models: Attention (R²: 0.223), Base, Metamodel (87.3% confidence)
- Backtest results: +176.71R profit with aggressive_filter strategy

Documentation Consolidation:
- Created docs/99-analisis/_MAP.md index with 13 new analysis documents
- Consolidated inventories: removed duplicates from orchestration/inventarios/
- Updated ML_INVENTORY.yml with BTCUSD metrics and training results
- Added execution reports: FASE11-BTCUSD, correction issues, alignment validation

Architecture & Integration:
- Updated all module documentation with NEXUS v3.4 frontmatter
- Fixed _MAP.md indexes across all folders
- Updated orchestration plans and traces

Files: 229 changed, 5064 insertions(+), 1872 deletions(-)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 09:31:29 -06:00

210 lines
5.7 KiB
TypeScript

/**
* Risk Check Middleware
*
* Pre-trade risk validation to ensure orders comply with risk limits.
*
* @version 1.0.0
* @author Trading Platform Trading Platform
*/
import { riskConfig } from '../config';
import { getBinanceClient } from '../services/binance-client';
import { logger } from '../utils/logger';
// ==========================================
// Types
// ==========================================
export interface RiskCheckParams {
symbol: string;
side: 'buy' | 'sell';
amount: number;
price?: number;
}
export interface RiskCheckResult {
allowed: boolean;
reason?: string;
warnings?: string[];
orderValue?: number;
}
// Daily volume tracking (in-memory, resets on restart)
let dailyVolume = 0;
let lastVolumeResetDate = new Date().toDateString();
// ==========================================
// Risk Check Functions
// ==========================================
/**
* Reset daily volume counter at midnight
*/
function checkAndResetDailyVolume(): void {
const today = new Date().toDateString();
if (today !== lastVolumeResetDate) {
dailyVolume = 0;
lastVolumeResetDate = today;
logger.info('Daily volume counter reset');
}
}
/**
* Get the quote asset from a symbol (e.g., USDT from BTCUSDT)
*/
function getQuoteAsset(symbol: string): string {
const stablecoins = ['USDT', 'BUSD', 'USDC', 'TUSD', 'DAI'];
for (const stable of stablecoins) {
if (symbol.endsWith(stable)) {
return stable;
}
}
return 'USDT';
}
/**
* Perform comprehensive risk check before order execution
*/
export async function performRiskCheck(params: RiskCheckParams): Promise<RiskCheckResult> {
const { symbol, side, amount, price } = params;
const warnings: string[] = [];
try {
checkAndResetDailyVolume();
const client = getBinanceClient();
// 1. Get current price if not provided
let orderPrice = price;
if (!orderPrice) {
try {
orderPrice = await client.getCurrentPrice(symbol);
} catch (error) {
logger.warn(`Could not fetch current price for ${symbol}, using amount as value estimate`);
orderPrice = 1; // Fallback
}
}
// 2. Calculate order value in quote currency (usually USDT)
const orderValue = amount * orderPrice;
// 3. Check maximum order value
if (orderValue > riskConfig.maxOrderValueUsdt) {
return {
allowed: false,
reason: `Order value ${orderValue.toFixed(2)} USDT exceeds maximum ${riskConfig.maxOrderValueUsdt} USDT`,
orderValue,
};
}
// 4. Check daily volume limit
if (dailyVolume + orderValue > riskConfig.maxDailyVolumeUsdt) {
return {
allowed: false,
reason: `Daily volume limit reached. Current: ${dailyVolume.toFixed(2)} USDT, Limit: ${riskConfig.maxDailyVolumeUsdt} USDT`,
orderValue,
};
}
// 5. Check if API keys are configured for trading
if (!client.isConfigured()) {
return {
allowed: false,
reason: 'Binance API keys are not configured. Cannot execute trades.',
orderValue,
};
}
// 6. Verify we can connect to Binance
const connected = await client.isConnected();
if (!connected) {
return {
allowed: false,
reason: 'Cannot connect to Binance. Please check your network and API configuration.',
orderValue,
};
}
// 7. Check balance for buy orders (if we have account access)
if (side === 'buy') {
try {
const account = await client.getAccount();
const quoteAsset = getQuoteAsset(symbol);
const quoteBalance = account.balances.find(b => b.asset === quoteAsset);
const available = quoteBalance?.free ?? 0;
if (available < orderValue) {
return {
allowed: false,
reason: `Insufficient ${quoteAsset} balance. Required: ${orderValue.toFixed(2)}, Available: ${available.toFixed(2)}`,
orderValue,
};
}
// Warning if using more than 50% of available balance
if (orderValue > available * 0.5) {
warnings.push(`This order uses ${((orderValue / available) * 100).toFixed(1)}% of your available ${quoteAsset}`);
}
} catch (error) {
warnings.push('Could not verify account balance');
logger.warn('Balance check failed', { error });
}
}
// 8. Check for large order warning
if (orderValue > riskConfig.maxOrderValueUsdt * 0.5) {
warnings.push(`Large order: ${orderValue.toFixed(2)} USDT (${((orderValue / riskConfig.maxOrderValueUsdt) * 100).toFixed(0)}% of max)`);
}
// All checks passed
return {
allowed: true,
orderValue,
warnings: warnings.length > 0 ? warnings : undefined,
};
} catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error';
logger.error('Risk check failed', { error, params });
return {
allowed: false,
reason: `Risk check error: ${message}`,
};
}
}
/**
* Record executed trade volume
*/
export function recordTradeVolume(orderValue: number): void {
checkAndResetDailyVolume();
dailyVolume += orderValue;
logger.info(`Trade recorded. Daily volume: ${dailyVolume.toFixed(2)} USDT`);
}
/**
* Get current daily volume
*/
export function getDailyVolume(): number {
checkAndResetDailyVolume();
return dailyVolume;
}
/**
* Get remaining daily volume allowance
*/
export function getRemainingDailyVolume(): number {
checkAndResetDailyVolume();
return Math.max(0, riskConfig.maxDailyVolumeUsdt - dailyVolume);
}
// ==========================================
// Exports
// ==========================================
export default {
performRiskCheck,
recordTradeVolume,
getDailyVolume,
getRemainingDailyVolume,
};