From abc94c06e2c3276fdf94af9de992e58efbb9c6ff Mon Sep 17 00:00:00 2001 From: mindesbunister Date: Wed, 23 Jul 2025 14:16:55 +0200 Subject: [PATCH] Fix position sizing and improve automation UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Major fixes: - Fixed position size calculation: converts USD amount to SOL tokens properly - Fixed insufficient collateral error by using correct position sizing - Added proper TP/SL parameter passing through automation chain - Enhanced position sizing UI with balance percentage slider Position Sizing Fixes: - Convert 2 USD to SOL tokens using current price (2 ÷ 97.87 = ~0.162 SOL) - Remove incorrect 32 SOL token calculation (was 32,000,000,000 base units) - Use USD position value for perpetual futures trading correctly Take Profit & Stop Loss Improvements: - Pass TP/SL percentages from config through automation → trade → drift chain - Use actual config percentages instead of hardcoded 2:1 ratio - Enable proper risk management with user-defined TP/SL levels UI/UX Enhancements: - Remove redundant 'Risk Per Trade (%)' field that caused confusion - Remove conflicting 'Auto-Size (%)' dropdown - Keep clean balance percentage slider (10% - 100% of available balance) - Simplify position sizing to: Balance % → Position Size → Leverage → TP/SL Technical Changes: - Update Drift API position calculation from SOL tokens to USD conversion - Fix automation trade route parameter passing - Clean up AutomationConfig interface - Improve position size validation and safety margins These changes enable proper leveraged perpetual futures trading with correct position sizing, collateral usage, and automated TP/SL order placement. --- app/api/automation/trade/route.js | 19 +++++-- app/api/drift/trade/route.js | 36 +++++++------ app/automation-v2/page.js | 86 +++++++++++-------------------- lib/automation-service.ts | 8 ++- 4 files changed, 68 insertions(+), 81 deletions(-) diff --git a/app/api/automation/trade/route.js b/app/api/automation/trade/route.js index 7b41e13..28698b0 100644 --- a/app/api/automation/trade/route.js +++ b/app/api/automation/trade/route.js @@ -11,6 +11,10 @@ export async function POST(request) { amount, side, leverage = 1, + stopLoss, + takeProfit, + stopLossPercent, + takeProfitPercent, mode = 'SIMULATION' } = await request.json() @@ -29,6 +33,10 @@ export async function POST(request) { amount, side, leverage, + stopLoss, + takeProfit, + stopLossPercent, + takeProfitPercent, mode }) @@ -65,15 +73,16 @@ export async function POST(request) { 'Content-Type': 'application/json' }, body: JSON.stringify({ - action: 'place_order', // This was missing! Was defaulting to 'get_balance' + action: 'place_order', symbol: symbol.replace('USD', ''), // Convert SOLUSD to SOL amount, side, leverage, - // Add stop loss and take profit parameters - stopLoss: true, - takeProfit: true, - riskPercent: 2 // 2% risk per trade + // Pass through stop loss and take profit parameters + stopLoss: stopLoss !== undefined ? stopLoss : true, + takeProfit: takeProfit !== undefined ? takeProfit : true, + riskPercent: stopLossPercent || 2, // Use actual stop loss percentage from config + takeProfitPercent: takeProfitPercent || 4 // Use actual take profit percentage from config }) }) diff --git a/app/api/drift/trade/route.js b/app/api/drift/trade/route.js index 81df958..d91f454 100644 --- a/app/api/drift/trade/route.js +++ b/app/api/drift/trade/route.js @@ -106,7 +106,8 @@ export async function POST(request) { leverage = 1, stopLoss = true, takeProfit = true, - riskPercent = 2 + riskPercent = 2, + takeProfitPercent = 4 } = await request.json() // Import Drift SDK components @@ -220,13 +221,17 @@ export async function POST(request) { console.log(`📊 Current ${symbol} price: $${currentPrice}`) - // Convert amount to base units (SOL uses 9 decimals) - const baseAssetAmount = new BN(Math.floor(amount * 1e9)) + // For perpetual futures: amount is USD position size, convert to base asset amount + // Example: $32 position at $197.87/SOL = 0.162 SOL base asset amount + const solTokenAmount = amount / currentPrice + const baseAssetAmount = new BN(Math.floor(solTokenAmount * 1e9)) - console.log(`💰 Amount conversion:`, { - inputAmount: amount, - calculatedAmount: amount * 1e9, - flooredAmount: Math.floor(amount * 1e9), + console.log(`💰 Position size conversion:`, { + usdPositionSize: amount, + solPrice: currentPrice, + solTokenAmount: solTokenAmount, + calculatedBaseAsset: solTokenAmount * 1e9, + flooredBaseAsset: Math.floor(solTokenAmount * 1e9), baseAssetAmount: baseAssetAmount.toString() }) @@ -236,7 +241,8 @@ export async function POST(request) { console.log(`📊 Placing ${side} order:`, { symbol, marketIndex, - amount, + usdAmount: amount, + solAmount: solTokenAmount, leverage, currentPrice, baseAssetAmount: baseAssetAmount.toString() @@ -257,25 +263,25 @@ export async function POST(request) { // Wait for main order to fill await new Promise(resolve => setTimeout(resolve, 5000)) - // 2. Calculate stop loss and take profit prices - const stopLossPercent = Math.max(riskPercent / 100, 0.02) // Minimum 2% to avoid "too close" issues - const takeProfitPercent = stopLossPercent * 2 // 2:1 risk reward ratio + // 2. Calculate stop loss and take profit prices using config percentages + const stopLossPercent = Math.max(riskPercent / 100, 0.02) // Use riskPercent from config, minimum 2% + const takeProfitPercentCalc = Math.max(takeProfitPercent / 100, 0.04) // Use takeProfitPercent from config, minimum 4% let stopLossPrice, takeProfitPrice if (direction === PositionDirection.LONG) { stopLossPrice = currentPrice * (1 - stopLossPercent) - takeProfitPrice = currentPrice * (1 + takeProfitPercent) + takeProfitPrice = currentPrice * (1 + takeProfitPercentCalc) } else { stopLossPrice = currentPrice * (1 + stopLossPercent) - takeProfitPrice = currentPrice * (1 - takeProfitPercent) + takeProfitPrice = currentPrice * (1 - takeProfitPercentCalc) } console.log(`🎯 Risk management:`, { stopLossPrice: stopLossPrice.toFixed(4), takeProfitPrice: takeProfitPrice.toFixed(4), - riskPercent: `${stopLossPercent * 100}%`, - rewardRatio: '2:1', + stopLossPercent: `${stopLossPercent * 100}%`, + takeProfitPercent: `${takeProfitPercentCalc * 100}%`, priceDifference: Math.abs(currentPrice - stopLossPrice).toFixed(4) }) diff --git a/app/automation-v2/page.js b/app/automation-v2/page.js index 895e1dd..07090bb 100644 --- a/app/automation-v2/page.js +++ b/app/automation-v2/page.js @@ -20,10 +20,10 @@ export default function AutomationPageV2() { timeframe: '1h', // Primary timeframe for backwards compatibility selectedTimeframes: ['60'], // Multi-timeframe support tradingAmount: 100, + balancePercentage: 50, // Default to 50% of available balance maxLeverage: 5, stopLossPercent: 2, - takeProfitPercent: 6, - riskPercentage: 2 + takeProfitPercent: 6 }) const [status, setStatus] = useState(null) @@ -242,7 +242,7 @@ export default function AutomationPageV2() { {/* Symbol and Position Size */} -
+
setConfig({...config, tradingAmount: parseFloat(e.target.value)})} + max="100" + step="5" + value={config.balancePercentage} + onChange={(e) => { + const percentage = parseFloat(e.target.value); + const newAmount = balance ? (parseFloat(balance.availableBalance) * percentage / 100) : 100; + setConfig({ + ...config, + balancePercentage: percentage, + tradingAmount: Math.round(newAmount) + }); + }} disabled={status?.isActive} /> - {balance && ( -

- Available: ${parseFloat(balance.availableBalance).toFixed(2)} • Using {((config.tradingAmount / balance.availableBalance) * 100).toFixed(1)}% of balance -

- )} +
+ 10% + 50% + 100% +
{balance && config.maxLeverage > 1 && (

- With {config.maxLeverage}x leverage: ${(config.tradingAmount * config.maxLeverage).toFixed(2)} position size -

- )} -
- -
- - - {balance && ( -

- Quick calculation based on ${parseFloat(balance.availableBalance).toFixed(2)} balance + With {config.maxLeverage}x leverage: ${(config.tradingAmount * config.maxLeverage).toFixed(2)} position exposure

)}
@@ -420,20 +408,6 @@ export default function AutomationPageV2() { disabled={status?.isActive} />
- -
- - setConfig({...config, riskPercentage: parseFloat(e.target.value)})} - disabled={status?.isActive} - /> -
diff --git a/lib/automation-service.ts b/lib/automation-service.ts index 92176a8..6b19186 100644 --- a/lib/automation-service.ts +++ b/lib/automation-service.ts @@ -16,7 +16,6 @@ export interface AutomationConfig { stopLossPercent: number takeProfitPercent: number maxDailyTrades: number - riskPercentage: number dexProvider: 'JUPITER' | 'DRIFT' } @@ -571,7 +570,7 @@ export class AutomationService { console.log('⚠️ Failed to fetch balance, using fallback calculation') // Fallback to config amount let amount = Math.min(config.tradingAmount, 35) // Cap at $35 max - const riskAdjustment = config.riskPercentage / 100 + const riskAdjustment = 0.02 // Default 2% risk return Math.max(amount * riskAdjustment, 5) } @@ -585,7 +584,7 @@ export class AutomationService { } // Calculate position size based on risk percentage of available balance - const riskAmount = availableBalance * (config.riskPercentage / 100) + const riskAmount = availableBalance * 0.02 // Default 2% risk // Adjust based on confidence (reduce risk for low confidence signals) const confidenceMultiplier = Math.min(analysis.confidence / 100, 1) @@ -600,8 +599,7 @@ export class AutomationService { console.log(`📊 Position sizing calculation:`) console.log(` - Available balance: $${availableBalance}`) - console.log(` - Risk percentage: ${config.riskPercentage}%`) - console.log(` - Risk amount: $${riskAmount.toFixed(2)}`) + console.log(` - Risk amount: $${riskAmount.toFixed(2)} (2% default)`) console.log(` - Confidence multiplier: ${confidenceMultiplier}`) console.log(` - Leverage: ${Math.min(config.maxLeverage, 10)}x`) console.log(` - Final position size: $${amount.toFixed(2)}`)