feat: enhance position display with proper formatting and value calculation
- Fix price formatting to show exactly 2 decimal places - Display position size in SOL units (16.40 SOL) instead of incorrect dollar amount - Add new Value field showing total dollar value of position (Size × Current Price) - Improve Open Positions section with accurate financial data display - Maintain enhanced styling and responsive layout - All prices now formatted professionally with consistent decimal places
This commit is contained in:
@@ -16,12 +16,74 @@ export async function POST(request) {
|
||||
stopLossPrice: 178.06
|
||||
};
|
||||
|
||||
// Calculate some metrics - handle missing stop loss
|
||||
const hasStopLoss = position.stopLossPrice && position.stopLossPrice > 0;
|
||||
const estimatedStopLoss = hasStopLoss ? position.stopLossPrice : (position.entryPrice * 0.95); // 5% default
|
||||
const stopLossDistance = Math.abs(position.entryPrice - estimatedStopLoss);
|
||||
// Fetch actual Drift orders to get real stop loss and take profit
|
||||
let actualStopLoss = null;
|
||||
let actualTakeProfit = null;
|
||||
let orderAnalysis = "Orders not accessible";
|
||||
|
||||
try {
|
||||
const ordersResponse = await fetch('http://localhost:3000/api/drift/orders');
|
||||
if (ordersResponse.ok) {
|
||||
const ordersData = await ordersResponse.json();
|
||||
|
||||
if (ordersData.success && ordersData.orders) {
|
||||
const relevantOrders = ordersData.orders.filter(order =>
|
||||
order.symbol === position.symbol &&
|
||||
order.reduceOnly &&
|
||||
order.status === 'OPEN'
|
||||
);
|
||||
|
||||
// Find stop loss (price below entry for long, above for short)
|
||||
const stopLossOrders = relevantOrders.filter(order => {
|
||||
const isStopDirection = position.side.toLowerCase() === 'long' ?
|
||||
(order.direction === 'SHORT' || order.direction === 'SELL') :
|
||||
(order.direction === 'LONG' || order.direction === 'BUY');
|
||||
|
||||
const hasStopPrice = position.side.toLowerCase() === 'long' ?
|
||||
(order.triggerPrice && parseFloat(order.triggerPrice) < position.entryPrice) :
|
||||
(order.triggerPrice && parseFloat(order.triggerPrice) > position.entryPrice);
|
||||
|
||||
return isStopDirection && hasStopPrice;
|
||||
});
|
||||
|
||||
// Find take profit (price above entry for long, below for short)
|
||||
const takeProfitOrders = relevantOrders.filter(order => {
|
||||
const isTpDirection = position.side.toLowerCase() === 'long' ?
|
||||
(order.direction === 'SHORT' || order.direction === 'SELL') :
|
||||
(order.direction === 'LONG' || order.direction === 'BUY');
|
||||
|
||||
const hasTpPrice = position.side.toLowerCase() === 'long' ?
|
||||
(order.triggerPrice && parseFloat(order.triggerPrice) > position.entryPrice) :
|
||||
(order.triggerPrice && parseFloat(order.triggerPrice) < position.entryPrice);
|
||||
|
||||
return isTpDirection && hasTpPrice;
|
||||
});
|
||||
|
||||
if (stopLossOrders.length > 0) {
|
||||
actualStopLoss = parseFloat(stopLossOrders[0].triggerPrice);
|
||||
}
|
||||
|
||||
if (takeProfitOrders.length > 0) {
|
||||
actualTakeProfit = parseFloat(takeProfitOrders[0].triggerPrice);
|
||||
}
|
||||
|
||||
orderAnalysis = `Found ${relevantOrders.length} reduce-only orders: ${stopLossOrders.length} stop loss, ${takeProfitOrders.length} take profit`;
|
||||
}
|
||||
}
|
||||
} catch (orderError) {
|
||||
console.log('Could not fetch orders for analysis:', orderError.message);
|
||||
orderAnalysis = "Order fetch failed - using estimates";
|
||||
}
|
||||
|
||||
// Use actual orders if available, otherwise estimate
|
||||
const hasRealStopLoss = actualStopLoss !== null;
|
||||
const hasRealTakeProfit = actualTakeProfit !== null;
|
||||
const effectiveStopLoss = hasRealStopLoss ? actualStopLoss : (position.entryPrice * 0.95);
|
||||
const effectiveTakeProfit = hasRealTakeProfit ? actualTakeProfit : (position.entryPrice * 1.10);
|
||||
|
||||
const stopLossDistance = Math.abs(position.entryPrice - effectiveStopLoss);
|
||||
const stopLossPercent = ((stopLossDistance / position.entryPrice) * 100).toFixed(1);
|
||||
const leverage = (position.size * position.entryPrice) / (position.size * position.entryPrice * 0.08); // Estimate based on position
|
||||
const leverage = (position.size * position.entryPrice) / (position.size * position.entryPrice * 0.08);
|
||||
const estimatedLeverage = Math.round(leverage * 10) / 10;
|
||||
|
||||
// Generate realistic AI reasoning based on the position
|
||||
@@ -33,9 +95,10 @@ export async function POST(request) {
|
||||
• Position size of ${position.size} SOL indicates moderate conviction
|
||||
|
||||
📊 Risk Management Assessment:
|
||||
• Stop loss at $${estimatedStopLoss.toFixed(2)} (${stopLossPercent}% protection)${hasStopLoss ? '' : ' - ESTIMATED'}
|
||||
• Risk/reward setup suggests ${stopLossPercent}% stop with potential 2-3x reward
|
||||
• Position sizing appears conservative for risk tolerance
|
||||
• Stop loss at $${effectiveStopLoss.toFixed(2)} (${stopLossPercent}% protection)${hasRealStopLoss ? ' ✅ CONFIRMED' : ' ⚠️ ESTIMATED'}
|
||||
• Take profit at $${effectiveTakeProfit.toFixed(2)}${hasRealTakeProfit ? ' ✅ CONFIRMED' : ' ⚠️ ESTIMATED'}
|
||||
• Risk/reward ratio: ${((Math.abs(effectiveTakeProfit - position.entryPrice) / stopLossDistance)).toFixed(1)}:1
|
||||
• ${orderAnalysis}
|
||||
|
||||
⚡ Leverage Analysis:
|
||||
• Estimated leverage: ~${estimatedLeverage}x (based on position metrics)
|
||||
@@ -44,14 +107,15 @@ export async function POST(request) {
|
||||
|
||||
🛡️ Current Status:
|
||||
• Position currently ${position.currentPrice > position.entryPrice ? 'profitable' : 'underwater'}
|
||||
• Distance to ${hasStopLoss ? 'stop loss' : 'estimated stop'}: ${((Math.abs(position.currentPrice - estimatedStopLoss) / position.currentPrice) * 100).toFixed(1)}%
|
||||
• Distance to stop loss: ${((Math.abs(position.currentPrice - effectiveStopLoss) / position.currentPrice) * 100).toFixed(1)}%
|
||||
• Distance to take profit: ${((Math.abs(position.currentPrice - effectiveTakeProfit) / position.currentPrice) * 100).toFixed(1)}%
|
||||
• Monitoring recommended for further developments`;
|
||||
|
||||
// Create a decision object for the existing position
|
||||
const retroactiveDecision = {
|
||||
timestamp: new Date().toISOString(),
|
||||
recommendation: `${position.side.toUpperCase()} (Executed)`,
|
||||
confidence: 82, // Estimated confidence based on position size and setup
|
||||
confidence: hasRealStopLoss && hasRealTakeProfit ? 92 : 82, // Higher confidence with real orders
|
||||
minConfidenceRequired: 75,
|
||||
reasoning: aiReasoning,
|
||||
executed: true,
|
||||
@@ -60,11 +124,16 @@ export async function POST(request) {
|
||||
amount: Math.round(position.size * position.entryPrice),
|
||||
leverage: estimatedLeverage,
|
||||
currentPrice: position.entryPrice,
|
||||
stopLoss: estimatedStopLoss,
|
||||
takeProfit: position.entryPrice + (stopLossDistance * 2.5), // Estimate 2.5:1 RR
|
||||
aiReasoning: `Retrospective analysis: ${estimatedLeverage}x leverage with ${stopLossPercent}% stop loss provides balanced risk/reward. Position sizing suggests moderate risk appetite with professional risk management principles applied.${hasStopLoss ? '' : ' Note: Stop loss estimated as not visible in position data.'}`,
|
||||
stopLoss: effectiveStopLoss,
|
||||
takeProfit: effectiveTakeProfit,
|
||||
aiReasoning: `Retrospective analysis: ${estimatedLeverage}x leverage with ${stopLossPercent}% stop loss provides balanced risk/reward. Position sizing suggests moderate risk appetite with professional risk management principles applied.${hasRealStopLoss ? ' Actual stop loss orders detected and confirmed.' : ' Stop loss estimated - actual orders may differ.'}`,
|
||||
txId: 'existing_position_analysis',
|
||||
aiStopLossPercent: `${stopLossPercent}% protective stop`
|
||||
aiStopLossPercent: `${stopLossPercent}% protective stop`,
|
||||
orderStatus: {
|
||||
realStopLoss: hasRealStopLoss,
|
||||
realTakeProfit: hasRealTakeProfit,
|
||||
orderAnalysis: orderAnalysis
|
||||
}
|
||||
},
|
||||
executionError: null,
|
||||
isRetrospective: true // Flag to indicate this is retroactive analysis
|
||||
|
||||
Reference in New Issue
Block a user