- Call loadDynamicConfig() without dead supabaseService argument (Cosmos-backed). - Use getLegacySupabaseClient() for raw .from() queries in maintenance scripts. - manualOverrideCloseTrades: typed imports + legacy client for lifecycle SELECT. - verify_realtime: ESM .js imports and comment for subscribeToProfiles. - verifyTenantIsolation: comment for singleton monkey-patch. Made-with: Cursor
83 lines
3.2 KiB
TypeScript
83 lines
3.2 KiB
TypeScript
import { supabaseService } from '../src/services/SupabaseService.js';
|
|
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
|
|
import logger from '../src/utils/logger.js';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
async function applyStandardRiskProfiles() {
|
|
logger.info('🚀 APPLYING STANDARD RISK PROFILES (5 TO 1)...');
|
|
|
|
const legacyClient = getLegacySupabaseClient();
|
|
if (!legacyClient) {
|
|
logger.error('❌ Legacy Supabase client not configured.');
|
|
return;
|
|
}
|
|
|
|
// 1. Load Data
|
|
const proposedPath = path.resolve('schema/proposed_risk_profiles.json');
|
|
if (!fs.existsSync(proposedPath)) {
|
|
logger.error(`❌ missing proposed profiles file: ${proposedPath}`);
|
|
return;
|
|
}
|
|
const proposedProfiles = JSON.parse(fs.readFileSync(proposedPath, 'utf8'));
|
|
|
|
// 2. Get User
|
|
const users = await supabaseService.getActiveUsers();
|
|
if (users.length === 0) {
|
|
logger.error('❌ No active users found.');
|
|
return;
|
|
}
|
|
const user = users[0];
|
|
|
|
// 3. Clear Existing Data (TRUNCATE equivalents via DELETE)
|
|
logger.info('🧹 Wiping existing data for a fresh start...');
|
|
|
|
// @ts-ignore
|
|
await legacyClient.from('positions').delete().neq('id', '00000000-0000-0000-0000-000000000000');
|
|
// @ts-ignore
|
|
await legacyClient.from('orders').delete().neq('id', '00000000-0000-0000-0000-000000000000');
|
|
// @ts-ignore
|
|
await legacyClient.from('trade_history').delete().neq('id', '00000000-0000-0000-0000-000000000000');
|
|
// @ts-ignore
|
|
await legacyClient.from('alerts').delete().neq('id', '00000000-0000-0000-0000-000000000000');
|
|
// @ts-ignore
|
|
await legacyClient.from('operational_events').delete().neq('id', '00000000-0000-0000-0000-000000000000');
|
|
// @ts-ignore
|
|
await legacyClient.from('trade_profiles').delete().neq('user_id', '00000000-0000-0000-0000-000000000000');
|
|
|
|
// 4. Prepare & Insert Profiles
|
|
const insertPayload = Object.values(proposedProfiles).map((p: any) => {
|
|
// Calculate risk_per_trade_percent from the RiskManagementRule in strategy_config
|
|
const riskRule = p.strategy_config.rules.find((r: any) => r.ruleId === 'RiskManagementRule');
|
|
const riskPercent = riskRule?.params?.maxRisk || 1.0;
|
|
|
|
return {
|
|
user_id: user.user_id,
|
|
name: p.name,
|
|
allocated_capital: p.allocatedCapital,
|
|
risk_per_trade_percent: riskPercent,
|
|
symbols: "BTC/USDT,ETH/USDT,SOL/USDT", // Multi-pair trading enabled
|
|
is_active: true,
|
|
strategy_config: p.strategy_config
|
|
};
|
|
});
|
|
|
|
// @ts-ignore
|
|
const { data, error } = await legacyClient
|
|
.from('trade_profiles')
|
|
.insert(insertPayload);
|
|
|
|
if (error) {
|
|
logger.error(`❌ Failed to apply profiles: ${error.message}`);
|
|
} else {
|
|
logger.info('✅ 5 Standard Profiles applied successfully!');
|
|
insertPayload.forEach((p: any, idx: number) => {
|
|
logger.info(` ${idx + 1}. [${p.name}] Risk: ${p.risk_per_trade_percent}% | Capital: $${p.allocated_capital}`);
|
|
});
|
|
}
|
|
|
|
process.exit(0);
|
|
}
|
|
|
|
applyStandardRiskProfiles().catch(console.error);
|