This commit is contained in:
hackerESQ
2025-08-11 19:58:17 -05:00
parent 9260de5f25
commit 97b13063d9
4 changed files with 64 additions and 141 deletions
+57 -91
View File
@@ -65,7 +65,7 @@ class DailyChange extends Model
$dividendSub = DB::table('holdings')
->join('dividends', 'dividends.symbol', '=', 'holdings.symbol')
->leftJoin('currency_rates as cr', function ($join) use ($currency) {
$join->on('cr.date', '=', 'dividends.date')
$join->on(DB::raw('DATE(cr.date)'), '=', DB::raw('DATE(dividends.date)'))
->where('cr.currency', '=', $currency);
})
->join('transactions as tx', function ($join) {
@@ -86,112 +86,78 @@ class DailyChange extends Model
AS total_dividends_earned")
->groupBy(['holdings.portfolio_id', 'dividends.date', 'tx.transaction_type', 'tx.quantity']);
$totalCostBasisSub = DB::table('transactions as tx1')
$costBasisSub = DB::table('transactions')
->leftJoin('currency_rates as cr', function ($join) use ($currency) {
$join->on('cr.date', '=', 'tx1.date')
->where('cr.currency', '=', $currency);
$join->on(DB::raw('DATE(cr.date)'), '=', DB::raw('DATE(transactions.date)'))
->where('cr.currency', $currency);
})
->select([
'tx1.portfolio_id',
'tx1.date',
'tx1.symbol',
'tx1.transaction_type',
'tx1.cost_basis_base',
'tx1.quantity',
])
->selectRaw("(CASE
WHEN
tx1.transaction_type = 'BUY'
OR SUM(tx1.cost_basis_base) = 0
THEN
COALESCE(cr.rate, 1)
ELSE (
SELECT
SUM(COALESCE(cr2.rate, 1) * buy.cost_basis_base)
/ SUM(buy.cost_basis_base)
FROM transactions as buy
LEFT JOIN currency_rates as cr2
ON cr2.date = buy.date
AND cr2.currency = '{$currency}'
WHERE buy.symbol = tx1.symbol
AND buy.portfolio_id = tx1.portfolio_id
AND buy.transaction_type = 'BUY'
AND buy.date <= tx1.date
) END)
AS rate")
->selectRaw(
"COALESCE(SUM(CASE
WHEN tx1.transaction_type = 'BUY'
THEN tx1.cost_basis_base * tx1.quantity
END), 0)
AS total_cost_basis_for_purchases"
)
->selectRaw(
"COALESCE(SUM(CASE
WHEN tx1.transaction_type = 'SELL'
THEN tx1.cost_basis_base * tx1.quantity
END), 0)
AS total_cost_basis_for_sales"
)
->selectRaw(
"(CASE
WHEN tx1.transaction_type = 'SELL'
THEN tx1.sale_price_base - tx1.cost_basis_base
ELSE 0 END)
* tx1.quantity
* COALESCE(cr.rate, 1)
AS realized_gain_dollars")
->groupBy([
'tx1.portfolio_id',
'tx1.date',
'tx1.symbol',
'tx1.transaction_type',
'tx1.cost_basis_base',
'tx1.quantity',
'cr.rate',
'tx1.sale_price_base',
]);
->select(['transactions.portfolio_id', 'transactions.date']);
return $query
->select(['daily_change.date', 'daily_change.portfolio_id'])
->leftJoinSub($totalCostBasisSub, 'cost_basis_display', function ($join) {
$join->on('daily_change.date', '>=', 'cost_basis_display.date')
->whereColumn('daily_change.portfolio_id', '=', 'cost_basis_display.portfolio_id');
})
->selectRaw('daily_change.total_market_value * COALESCE(cr.rate, 1) AS total_market_value')
->leftJoin('currency_rates as cr', function ($join) use ($currency) {
$join->on('cr.date', '=', 'daily_change.date')
$join->on(DB::raw('DATE(cr.date)'), '=', DB::raw('DATE(daily_change.date)'))
->where('cr.currency', '=', $currency);
})
->selectRaw('
SUM(cost_basis_display.rate * cost_basis_display.total_cost_basis_for_purchases) - SUM(cost_basis_display.rate * cost_basis_display.total_cost_basis_for_sales)
AS total_cost_basis
')
->selectRaw('(
daily_change.total_market_value * COALESCE(cr.rate, 1)
) - (SUM(cost_basis_display.rate * cost_basis_display.total_cost_basis_for_purchases) - SUM(cost_basis_display.rate * cost_basis_display.total_cost_basis_for_sales))
as total_gain')
->selectRaw('(
daily_change.total_market_value * COALESCE(cr.rate, 1)
) as total_market_value')
->selectRaw('
SUM(
cost_basis_display.realized_gain_dollars
) as realized_gain_dollars')
->selectSub(function ($query) use ($dividendSub) {
->selectSub(function ($query) use ($costBasisSub) {
$query->fromSub(
$costBasisSub->selectRaw("
(CASE
WHEN transactions.transaction_type = 'BUY'
THEN 1 ELSE -1 END
) * transactions.cost_basis_base * transactions.quantity * COALESCE(cr.rate, 1) AS total_cost_basis"),
'cb')
->selectRaw('SUM(cb.total_cost_basis)')
->whereColumn('cb.date', '<=', 'daily_change.date')
->whereColumn('cb.portfolio_id', '=', 'daily_change.portfolio_id');
}, 'total_cost_basis')
->selectSub(function ($query) use ($costBasisSub) {
$query->fromSub(
$costBasisSub->selectRaw("
(CASE
WHEN transactions.transaction_type = 'SELL'
THEN transactions.sale_price_base - transactions.cost_basis_base
END
) * transactions.quantity * COALESCE(cr.rate, 1) AS realized_gain_loss"),
'cb')
->selectRaw('SUM(cb.realized_gain_loss)')
->whereColumn('cb.date', '<=', 'daily_change.date')
->whereColumn('cb.portfolio_id', '=', 'daily_change.portfolio_id');
}, 'realized_gain_loss')
->selectSub(function ($query) use ($dividendSub) { // todo: maybe costbasis uses this model?
$query->fromSub($dividendSub, 'd')
->selectRaw('SUM(d.total_dividends_earned)')
->whereColumn('d.date', '<=', 'daily_change.date')
->whereColumn('d.portfolio_id', '=', 'daily_change.portfolio_id');
}, 'total_dividends_earned')
->groupBy([
'daily_change.date',
'cr.rate',
'daily_change.total_market_value',
'daily_change.portfolio_id',
])
->addSelect('annotation')
->orderBy('daily_change.date');
}
public function scopeGetDailyPerformance($query)
{
return $query->get()
->sortBy('date')
->groupBy('date')
->map(function ($group) {
$total_market_value = $group->sum('total_market_value');
$total_cost_basis = $group->sum('total_cost_basis');
$total_market_gain = $total_market_value - $total_cost_basis;
return (object) [
'date' => $group->first()->date->toDateString(),
'total_market_value' => $total_market_value,
'total_cost_basis' => $total_cost_basis,
'total_gain' => $total_market_gain,
'realized_gain_dollars' => $group->sum('realized_gain_dollars'),
'total_dividends_earned' => $group->sum('total_dividends_earned'),
];
})
->values();
}
public function portfolio()
{
return $this->belongsTo(Portfolio::class);