fix p&l
This commit is contained in:
parent
ec6426781d
commit
8c23c68565
1 changed files with 35 additions and 26 deletions
|
|
@ -44,40 +44,49 @@ export async function GET({ request }) {
|
||||||
const value = quantity * price;
|
const value = quantity * price;
|
||||||
totalCoinValue += value;
|
totalCoinValue += value;
|
||||||
|
|
||||||
// Calculate total cost basis from buy transactions
|
const allTransactions = await db.select({
|
||||||
const costBasisResult = await db.select({
|
type: transaction.type,
|
||||||
totalCostBasis: sql<number>`COALESCE(SUM(${transaction.totalBaseCurrencyAmount}), 0)`
|
quantity: transaction.quantity,
|
||||||
|
totalBaseCurrencyAmount: transaction.totalBaseCurrencyAmount,
|
||||||
|
timestamp: transaction.timestamp
|
||||||
})
|
})
|
||||||
.from(transaction)
|
.from(transaction)
|
||||||
.where(
|
.where(
|
||||||
and(
|
and(
|
||||||
eq(transaction.userId, userId),
|
eq(transaction.userId, userId),
|
||||||
eq(transaction.coinId, holding.coinId),
|
eq(transaction.coinId, holding.coinId)
|
||||||
eq(transaction.type, 'BUY')
|
|
||||||
)
|
)
|
||||||
);
|
)
|
||||||
|
.orderBy(transaction.timestamp);
|
||||||
|
|
||||||
// Calculate average purchase price for reference
|
// calculate cost basis
|
||||||
const avgPriceResult = await db.select({
|
let remainingQuantity = quantity;
|
||||||
avgPrice: sql<number>`
|
let totalCostBasis = 0;
|
||||||
CASE
|
let runningQuantity = 0;
|
||||||
WHEN SUM(${transaction.quantity}) > 0
|
|
||||||
THEN SUM(${transaction.totalBaseCurrencyAmount}) / SUM(${transaction.quantity})
|
|
||||||
ELSE 0
|
|
||||||
END
|
|
||||||
`
|
|
||||||
})
|
|
||||||
.from(transaction)
|
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(transaction.userId, userId),
|
|
||||||
eq(transaction.coinId, holding.coinId),
|
|
||||||
eq(transaction.type, 'BUY')
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const totalCostBasis = Number(costBasisResult[0]?.totalCostBasis || 0);
|
for (const tx of allTransactions) {
|
||||||
const avgPurchasePrice = Number(avgPriceResult[0]?.avgPrice || 0);
|
const txQuantity = Number(tx.quantity);
|
||||||
|
const txAmount = Number(tx.totalBaseCurrencyAmount);
|
||||||
|
|
||||||
|
if (tx.type === 'BUY') {
|
||||||
|
runningQuantity += txQuantity;
|
||||||
|
|
||||||
|
// if we still need to account for held coins
|
||||||
|
if (remainingQuantity > 0) {
|
||||||
|
const quantityToAttribute = Math.min(txQuantity, remainingQuantity);
|
||||||
|
const avgPrice = txAmount / txQuantity;
|
||||||
|
totalCostBasis += quantityToAttribute * avgPrice;
|
||||||
|
remainingQuantity -= quantityToAttribute;
|
||||||
|
}
|
||||||
|
} else if (tx.type === 'SELL') {
|
||||||
|
runningQuantity -= txQuantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we accounted for all held coins, break
|
||||||
|
if (remainingQuantity <= 0) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const avgPurchasePrice = quantity > 0 ? totalCostBasis / quantity : 0;
|
||||||
|
|
||||||
const percentageChange = totalCostBasis > 0
|
const percentageChange = totalCostBasis > 0
|
||||||
? ((value - totalCostBasis) / totalCostBasis) * 100
|
? ((value - totalCostBasis) / totalCostBasis) * 100
|
||||||
|
|
|
||||||
Reference in a new issue