diff --git a/src/app/hashtag/[tag]/TradePanel.tsx b/src/app/hashtag/[tag]/TradePanel.tsx index 792e12a..50f8ef4 100644 --- a/src/app/hashtag/[tag]/TradePanel.tsx +++ b/src/app/hashtag/[tag]/TradePanel.tsx @@ -11,11 +11,13 @@ interface Props { shortPosition: { shares: number; avgBuyPrice: number } | null fundId?: string fundName?: string + maxPositionShares: number + maxPositionValue: number } type Tab = 'BUY_LONG' | 'SELL_LONG' | 'BUY_SHORT' | 'SELL_SHORT' -export function TradePanel({ hashtag, balance, longPosition, shortPosition, fundId, fundName }: Props) { +export function TradePanel({ hashtag, balance, longPosition, shortPosition, fundId, fundName, maxPositionShares, maxPositionValue }: Props) { const router = useRouter() const [tab, setTab] = useState('BUY_LONG') const [shares, setShares] = useState('') @@ -25,12 +27,19 @@ export function TradePanel({ hashtag, balance, longPosition, shortPosition, fund const sharesNum = parseFloat(shares) || 0 const cost = sharesNum * hashtag.currentPrice - const maxBuyShares = hashtag.currentPrice > 0 ? Math.floor((balance / hashtag.currentPrice) * 100) / 100 : 0 + // For buys: max is the lowest of (balance cap, shares cap, value cap) minus existing position + const existingBuyShares = tab === 'BUY_LONG' ? (longPosition?.shares ?? 0) : (shortPosition?.shares ?? 0) + const remainingShareCap = Math.max(0, maxPositionShares - existingBuyShares) + const remainingValueCap = Math.max(0, maxPositionValue - existingBuyShares * hashtag.currentPrice) + const sharesFromValueCap = hashtag.currentPrice > 0 ? remainingValueCap / hashtag.currentPrice : 0 + const sharesFromBalance = hashtag.currentPrice > 0 ? balance / hashtag.currentPrice : 0 + const maxBuyShares = Math.floor(Math.min(remainingShareCap, sharesFromValueCap, sharesFromBalance) * 100) / 100 + const maxSellShares = tab === 'SELL_LONG' ? longPosition?.shares ?? 0 : shortPosition?.shares ?? 0 const canAfford = - tab === 'BUY_LONG' || tab === 'BUY_SHORT' ? cost <= balance : sharesNum <= (maxSellShares ?? 0) + tab === 'BUY_LONG' || tab === 'BUY_SHORT' ? cost <= balance && sharesNum <= maxBuyShares : sharesNum <= (maxSellShares ?? 0) async function handleTrade() { if (sharesNum <= 0) return @@ -129,6 +138,9 @@ export function TradePanel({ hashtag, balance, longPosition, shortPosition, fund )} > Max + {(tab === 'BUY_LONG' || tab === 'BUY_SHORT') && maxBuyShares === 0 + ? ' (limit reached)' + : null} - {/* Header */}} + {/* Header */}

#{hashtag.displayTag}

@@ -193,6 +197,8 @@ export default async function HashtagPage({ params, searchParams }: Props) { shortPosition={activeShort ? { shares: activeShort.shares, avgBuyPrice: activeShort.avgBuyPrice } : null} fundId={fundContext?.id} fundName={fundContext?.name} + maxPositionShares={fundContext ? FUND_MAX_POSITION_SHARES : MAX_POSITION_SHARES} + maxPositionValue={fundContext ? FUND_MAX_POSITION_VALUE : MAX_POSITION_VALUE} /> ) : (