feat: Fix position calculator visibility and add auto-detection
- Fixed position calculator not showing when analysis entry price is 0 - Added auto-detection of Long/Short position type from AI analysis recommendation - Implemented independent price fetching from CoinGecko API - Added current market price display with AI recommendation - Enhanced position calculator with fallback prices for testing - Added API endpoint /api/price for real-time price data - Position calculator now works even when analysis lacks specific entry prices - Shows 'Auto-detected from analysis' label when position type is determined from AI The position calculator is now always visible and uses: 1. Current market price from CoinGecko API 2. Auto-detected position type from analysis (Long/Short) 3. Fallback prices for testing when API is unavailable 4. Default stop loss/take profit levels when not specified in analysis
This commit is contained in:
@@ -36,14 +36,52 @@ export default function PositionCalculator({
|
||||
const [positionType, setPositionType] = useState<'long' | 'short'>('long')
|
||||
const [calculation, setCalculation] = useState<PositionCalculation | null>(null)
|
||||
const [showAdvanced, setShowAdvanced] = useState(false)
|
||||
const [marketPrice, setMarketPrice] = useState<number>(currentPrice)
|
||||
|
||||
// Trading parameters
|
||||
const [tradingFee, setTradingFee] = useState<number>(0.1) // 0.1% fee
|
||||
const [maintenanceMargin, setMaintenanceMargin] = useState<number>(0.5) // 0.5% maintenance margin
|
||||
|
||||
// Auto-detect position type from analysis
|
||||
useEffect(() => {
|
||||
if (analysis?.recommendation) {
|
||||
const rec = analysis.recommendation.toLowerCase()
|
||||
if (rec.includes('buy') || rec.includes('long') || rec.includes('bullish')) {
|
||||
setPositionType('long')
|
||||
} else if (rec.includes('sell') || rec.includes('short') || rec.includes('bearish')) {
|
||||
setPositionType('short')
|
||||
}
|
||||
}
|
||||
}, [analysis])
|
||||
|
||||
// Fetch current market price if not provided
|
||||
useEffect(() => {
|
||||
const fetchPrice = async () => {
|
||||
if (currentPrice > 0) {
|
||||
setMarketPrice(currentPrice)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/price?symbol=${symbol}`)
|
||||
const data = await response.json()
|
||||
if (data.price) {
|
||||
setMarketPrice(data.price)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch price:', error)
|
||||
// Fallback to a reasonable default for testing
|
||||
setMarketPrice(symbol.includes('BTC') ? 100000 : symbol.includes('ETH') ? 4000 : 100)
|
||||
}
|
||||
}
|
||||
|
||||
fetchPrice()
|
||||
}, [currentPrice, symbol])
|
||||
|
||||
// Calculate position metrics
|
||||
const calculatePosition = () => {
|
||||
if (!currentPrice || currentPrice <= 0) return null
|
||||
const priceToUse = marketPrice || currentPrice
|
||||
if (!priceToUse || priceToUse <= 0) return null
|
||||
|
||||
const positionSize = investmentAmount * leverage
|
||||
const marginRequired = investmentAmount
|
||||
@@ -51,7 +89,7 @@ export default function PositionCalculator({
|
||||
const netInvestment = investmentAmount + fee
|
||||
|
||||
// Get AI analysis targets if available
|
||||
let entryPrice = currentPrice
|
||||
let entryPrice = priceToUse
|
||||
let stopLoss = 0
|
||||
let takeProfit = 0
|
||||
|
||||
@@ -92,11 +130,11 @@ export default function PositionCalculator({
|
||||
} else {
|
||||
// Default targets if no analysis
|
||||
stopLoss = positionType === 'long'
|
||||
? currentPrice * 0.95
|
||||
: currentPrice * 1.05
|
||||
? priceToUse * 0.95
|
||||
: priceToUse * 1.05
|
||||
takeProfit = positionType === 'long'
|
||||
? currentPrice * 1.10
|
||||
: currentPrice * 0.90
|
||||
? priceToUse * 1.10
|
||||
: priceToUse * 0.90
|
||||
}
|
||||
|
||||
// Calculate liquidation price
|
||||
@@ -176,6 +214,21 @@ export default function PositionCalculator({
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Current Price Display */}
|
||||
<div className="mb-6 p-4 bg-gray-800/30 rounded-lg border border-gray-600">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="text-sm text-gray-400">Current Market Price</div>
|
||||
<div className="text-lg font-bold text-white">
|
||||
{symbol}: ${formatPrice(marketPrice || currentPrice || 0)}
|
||||
</div>
|
||||
</div>
|
||||
{analysis?.recommendation && (
|
||||
<div className="mt-2 text-sm text-cyan-400">
|
||||
AI Recommendation: {analysis.recommendation}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Input Controls */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
|
||||
{/* Investment Amount */}
|
||||
@@ -197,6 +250,9 @@ export default function PositionCalculator({
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-300 mb-2">
|
||||
Position Type
|
||||
{analysis?.recommendation && (
|
||||
<span className="ml-2 text-xs text-cyan-400">(Auto-detected from analysis)</span>
|
||||
)}
|
||||
</label>
|
||||
<div className="flex space-x-2">
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user