143 lines
5.8 KiB
TypeScript
143 lines
5.8 KiB
TypeScript
|
|
import { supabaseService } from '../src/services/SupabaseService.js';
|
|
import logger from '../src/utils/logger.js';
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
|
|
async function setupHighRiskProfile() {
|
|
logger.info('🚀 SETTING UP HIGH-RISK SCALPER PROFILE...');
|
|
|
|
// 1. Get or Create Profile
|
|
const profiles = await supabaseService.getActiveProfiles();
|
|
let targetProfile = profiles.find(p => p.name.includes('Scalp') || p.name.includes('High'));
|
|
|
|
if (!targetProfile && profiles.length > 0) {
|
|
targetProfile = profiles[0]; // Fallback to first available
|
|
}
|
|
|
|
if (!targetProfile) {
|
|
logger.error('❌ No profiles found. Please create one in Dashboard first.');
|
|
return;
|
|
}
|
|
|
|
const profileId = targetProfile.id;
|
|
const userId = targetProfile.user_id; // Using internal user_id mapping
|
|
|
|
logger.info(`👤 Configuring Profile: [${targetProfile.name}] (${profileId})`);
|
|
|
|
// 2. Update Config for HIGH RISK
|
|
// We update Supabase DB directly through the service client (using raw query if needed, or just assume manual config for now)
|
|
// Since SupabaseService doesn't have 'updateProfile', we will just LOG that we are treating it as high risk,
|
|
// AND generate the high-frequency trading data for it.
|
|
|
|
// In a real scenario, we'd update table 'trade_profiles' -> allocated_capital = 1000, risk = 5.
|
|
// Let's try to update it if we can access the client.
|
|
// @ts-ignore
|
|
const { error: updateError } = await supabaseService.client
|
|
.from('trade_profiles')
|
|
.update({
|
|
allocated_capital: 1000,
|
|
risk_per_trade_percent: 5, // High Risk!
|
|
symbols: 'BTC/USD,ETH/USD,SOL/USD', // Volatile assets
|
|
strategy_config: {
|
|
riskLimits: { maxOpenTrades: 10, maxDailyLossUsd: 500 },
|
|
execution: { orderType: 'market', allowedSymbols: ['BTC/USD', 'ETH/USD', 'SOL/USD'] },
|
|
rules: [
|
|
{ ruleId: 'MomentumRule', enabled: true },
|
|
{ ruleId: 'VolatilityRule', enabled: true }, // Aggressive
|
|
{ ruleId: 'ScalpRule', enabled: true }
|
|
]
|
|
}
|
|
})
|
|
.eq('id', profileId);
|
|
|
|
if (updateError) {
|
|
logger.error(`❌ Failed to update profile config: ${updateError.message}`);
|
|
} else {
|
|
logger.info(`✅ Profile Updated: Capital=$1000 | Risk=5% | Strategy=Aggressive`);
|
|
}
|
|
|
|
// 3. Simulate 24h of Rapid Trades (Backfill)
|
|
logger.info('🎰 Simulating 24h of High-Frequency Trading...');
|
|
|
|
const assets = ['BTC/USD', 'ETH/USD', 'SOL/USD'];
|
|
const trades = 12; // 1 trade every 2 hours roughly, but bunched up
|
|
const now = Date.now();
|
|
|
|
for (let i = 0; i < trades; i++) {
|
|
// Randomize time within last 24h
|
|
const timeOffset = Math.floor(Math.random() * 24 * 60 * 60 * 1000);
|
|
const timestamp = now - timeOffset;
|
|
|
|
const symbol = assets[Math.floor(Math.random() * assets.length)];
|
|
const side = Math.random() > 0.5 ? 'buy' : 'sell'; // Lowercase per fix
|
|
const size = Math.random() * 0.5 + 0.1;
|
|
const entryPrice = symbol.includes('BTC') ? 60000 : (symbol.includes('ETH') ? 3000 : 150);
|
|
|
|
// Outcome: 60% Win Rate
|
|
const isWin = Math.random() > 0.4;
|
|
const pnlPercent = isWin ? (Math.random() * 2 + 1) : -(Math.random() * 1.5 + 0.5); // Win 1-3%, Loss 0.5-2%
|
|
const exitPrice = entryPrice * (1 + (side === 'buy' ? pnlPercent / 100 : -pnlPercent / 100));
|
|
const pnl = (exitPrice - entryPrice) * size * (side === 'buy' ? 1 : -1);
|
|
|
|
// A. Log Completed Trade to History
|
|
// @ts-ignore
|
|
const { error: histError } = await supabaseService.client
|
|
.from('trade_history')
|
|
.insert([{
|
|
user_id: userId,
|
|
profile_id: profileId,
|
|
symbol: symbol,
|
|
side: side,
|
|
entry_price: entryPrice,
|
|
exit_price: exitPrice,
|
|
size: size,
|
|
pnl: pnl,
|
|
pnl_percent: pnlPercent,
|
|
reason: isWin ? 'Target Hit (Scalp)' : 'Stop Risk',
|
|
timestamp: timestamp
|
|
// No stop_loss/take_profit columns
|
|
}]);
|
|
|
|
if (histError) logger.error(` History Insert Fail: ${histError.message}`);
|
|
else logger.info(` 📝 [${new Date(timestamp).toLocaleTimeString()}] Trade Logged: ${symbol} ${isWin ? '✅ WIN' : '❌ LOSS'} ($${pnl.toFixed(2)})`);
|
|
|
|
// B. Log "Order" for this trade (Matched Pair)
|
|
// 1. Entry Order
|
|
// @ts-ignore
|
|
await supabaseService.client.from('orders').insert([{
|
|
user_id: userId,
|
|
profile_id: profileId,
|
|
order_id: uuidv4(),
|
|
symbol: symbol,
|
|
type: 'Market',
|
|
side: side,
|
|
qty: size,
|
|
price: entryPrice,
|
|
status: 'filled',
|
|
timestamp: timestamp - 10000 // 10s before fill
|
|
}]);
|
|
|
|
// 2. Exit Order
|
|
// @ts-ignore
|
|
await supabaseService.client.from('orders').insert([{
|
|
user_id: userId,
|
|
profile_id: profileId,
|
|
order_id: uuidv4(),
|
|
symbol: symbol,
|
|
type: 'Market',
|
|
side: side === 'buy' ? 'sell' : 'buy',
|
|
qty: size,
|
|
price: exitPrice,
|
|
status: 'filled',
|
|
timestamp: timestamp
|
|
}]);
|
|
}
|
|
|
|
logger.info('===================================================');
|
|
logger.info(`✅ Aggressive Profile Ready. Dashboard updated with ${trades} trades.`);
|
|
logger.info('===================================================');
|
|
process.exit(0);
|
|
}
|
|
|
|
setupHighRiskProfile().catch(console.error);
|