wip
This commit is contained in:
+17
-35
@@ -120,12 +120,18 @@ class DailyChange extends Model
|
|||||||
) END)
|
) END)
|
||||||
AS rate")
|
AS rate")
|
||||||
->selectRaw(
|
->selectRaw(
|
||||||
"CASE
|
"COALESCE(SUM(CASE
|
||||||
WHEN tx1.transaction_type = 'BUY'
|
WHEN tx1.transaction_type = 'BUY'
|
||||||
THEN tx1.quantity
|
THEN tx1.cost_basis_base * tx1.quantity
|
||||||
ELSE -tx1.quantity
|
END), 0)
|
||||||
END
|
AS total_cost_basis_for_purchases"
|
||||||
AS remaining_quantity"
|
)
|
||||||
|
->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(
|
->selectRaw(
|
||||||
"(CASE
|
"(CASE
|
||||||
@@ -156,38 +162,14 @@ class DailyChange extends Model
|
|||||||
$join->on('cr.date', '=', 'daily_change.date')
|
$join->on('cr.date', '=', 'daily_change.date')
|
||||||
->where('cr.currency', '=', $currency);
|
->where('cr.currency', '=', $currency);
|
||||||
})
|
})
|
||||||
->selectRaw("
|
->selectRaw('
|
||||||
(SUM(
|
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)
|
||||||
CASE
|
|
||||||
WHEN cost_basis_display.transaction_type = 'BUY'
|
|
||||||
THEN cost_basis_display.cost_basis_base * cost_basis_display.quantity * cost_basis_display.rate
|
|
||||||
END
|
|
||||||
)
|
|
||||||
/ SUM(
|
|
||||||
CASE
|
|
||||||
WHEN cost_basis_display.transaction_type = 'BUY'
|
|
||||||
THEN cost_basis_display.quantity
|
|
||||||
END
|
|
||||||
))
|
|
||||||
* SUM(cost_basis_display.remaining_quantity)
|
|
||||||
AS total_cost_basis
|
AS total_cost_basis
|
||||||
")
|
')
|
||||||
->selectRaw("(
|
->selectRaw('(
|
||||||
daily_change.total_market_value * COALESCE(cr.rate, 1)
|
daily_change.total_market_value * COALESCE(cr.rate, 1)
|
||||||
) - (SUM(
|
) - (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))
|
||||||
CASE
|
as total_gain')
|
||||||
WHEN cost_basis_display.transaction_type = 'BUY'
|
|
||||||
THEN cost_basis_display.cost_basis_base * cost_basis_display.quantity * cost_basis_display.rate
|
|
||||||
END
|
|
||||||
)
|
|
||||||
/ SUM(
|
|
||||||
CASE
|
|
||||||
WHEN cost_basis_display.transaction_type = 'BUY'
|
|
||||||
THEN cost_basis_display.quantity
|
|
||||||
END
|
|
||||||
))
|
|
||||||
* SUM(cost_basis_display.remaining_quantity)
|
|
||||||
as total_gain")
|
|
||||||
->selectRaw('(
|
->selectRaw('(
|
||||||
daily_change.total_market_value * COALESCE(cr.rate, 1)
|
daily_change.total_market_value * COALESCE(cr.rate, 1)
|
||||||
) as total_market_value')
|
) as total_market_value')
|
||||||
|
|||||||
+47
-17
@@ -544,17 +544,22 @@ class MultiCurrencyTest extends TestCase
|
|||||||
|
|
||||||
$this->actingAs($user = User::factory()->create());
|
$this->actingAs($user = User::factory()->create());
|
||||||
|
|
||||||
|
$monthAgo = now()->subMonth()->toDateString();
|
||||||
|
$fiveWeeksAgo = now()->subWeeks(5)->toDateString();
|
||||||
|
$fiveDaysAgo = now()->subDays(5)->toDateString();
|
||||||
|
|
||||||
$portfolio = Portfolio::factory()->create();
|
$portfolio = Portfolio::factory()->create();
|
||||||
Transaction::factory(5)->buy()->lastMonth()->portfolio($portfolio->id)->symbol('AAPL')->create();
|
Transaction::factory(5)->buy()->costBasis(100)->date($monthAgo)->portfolio($portfolio->id)->symbol('AAPL')->create();
|
||||||
Transaction::factory(5)->buy()->lastMonth()->portfolio($portfolio->id)->symbol('ACME')->create();
|
Transaction::factory(5)->buy()->costBasis(190)->date($fiveWeeksAgo)->portfolio($portfolio->id)->symbol('ACME')->create();
|
||||||
Transaction::factory()->sell()->recent()->portfolio($portfolio->id)->symbol('ACME')->create();
|
Transaction::factory()->sell()->date($fiveDaysAgo)->portfolio($portfolio->id)->symbol('ACME')->create();
|
||||||
|
|
||||||
$portfolio->syncDailyChanges();
|
$portfolio->syncDailyChanges();
|
||||||
|
|
||||||
$dailyChange = DailyChange::withDailyPerformance()
|
$dailyChange = DailyChange::withDailyPerformance()
|
||||||
->portfolio($portfolio->id)
|
->portfolio($portfolio->id)
|
||||||
->get()
|
->get();
|
||||||
->sortBy('date')
|
|
||||||
|
$dailyChange = $dailyChange->sortBy('date')
|
||||||
->groupBy('date')
|
->groupBy('date')
|
||||||
->map(function ($group) {
|
->map(function ($group) {
|
||||||
return (object) [
|
return (object) [
|
||||||
@@ -572,18 +577,39 @@ class MultiCurrencyTest extends TestCase
|
|||||||
->getPortfolioMetrics();
|
->getPortfolioMetrics();
|
||||||
|
|
||||||
$this->assertEqualsWithDelta($metrics->get('total_market_value'), $dailyChange->last()->total_market_value, 0.01);
|
$this->assertEqualsWithDelta($metrics->get('total_market_value'), $dailyChange->last()->total_market_value, 0.01);
|
||||||
// expected 2773.034 Failed asserting that 2816.46 matches .
|
|
||||||
|
|
||||||
// "total_cost_basis" => 1771.476
|
|
||||||
// "total_gain_dollars" => 300.234
|
|
||||||
|
|
||||||
// +"total_cost_basis": 1765.431
|
|
||||||
// +"total_gain": 306.279
|
|
||||||
|
|
||||||
$this->assertEqualsWithDelta($metrics->get('total_cost_basis'), $dailyChange->last()->total_cost_basis, 0.01);
|
$this->assertEqualsWithDelta($metrics->get('total_cost_basis'), $dailyChange->last()->total_cost_basis, 0.01);
|
||||||
|
$this->assertEqualsWithDelta(Holding::get()->sum('total_cost_basis'), $dailyChange->last()->total_cost_basis, 0.01);
|
||||||
$this->assertEqualsWithDelta($metrics->get('realized_gain_dollars'), $dailyChange->last()->realized_gain_dollars, 0.01);
|
$this->assertEqualsWithDelta($metrics->get('realized_gain_dollars'), $dailyChange->last()->realized_gain_dollars, 0.01);
|
||||||
$this->assertEqualsWithDelta($metrics->get('total_market_value') - $metrics->get('total_cost_basis'), $dailyChange->last()->total_gain, 0.01);
|
$this->assertEqualsWithDelta($metrics->get('total_market_value') - $metrics->get('total_cost_basis'), $dailyChange->last()->total_gain, 0.01);
|
||||||
|
|
||||||
|
// add currency rates
|
||||||
|
$rates = collect([[
|
||||||
|
'currency' => 'GBP',
|
||||||
|
'rate' => .88,
|
||||||
|
'date' => $fiveWeeksAgo,
|
||||||
|
], [
|
||||||
|
'currency' => 'GBP',
|
||||||
|
'rate' => .88,
|
||||||
|
'date' => $fiveDaysAgo,
|
||||||
|
], [
|
||||||
|
'currency' => 'GBP',
|
||||||
|
'rate' => .88,
|
||||||
|
'date' => $monthAgo,
|
||||||
|
], [
|
||||||
|
'currency' => 'GBP',
|
||||||
|
'rate' => .88,
|
||||||
|
'date' => now()->subDay()->toDateString(),
|
||||||
|
], [
|
||||||
|
'currency' => 'GBP',
|
||||||
|
'rate' => .88,
|
||||||
|
'date' => now()->toDateString(),
|
||||||
|
], [
|
||||||
|
'currency' => 'GBP',
|
||||||
|
'rate' => .88,
|
||||||
|
'date' => now()->addDay()->toDateString(),
|
||||||
|
]]);
|
||||||
|
$rates->each(fn ($rate) => CurrencyRate::create($rate));
|
||||||
|
|
||||||
// switch user display currency
|
// switch user display currency
|
||||||
$user->options = array_merge($user->options ?? [], [
|
$user->options = array_merge($user->options ?? [], [
|
||||||
'display_currency' => 'GBP',
|
'display_currency' => 'GBP',
|
||||||
@@ -592,10 +618,14 @@ class MultiCurrencyTest extends TestCase
|
|||||||
|
|
||||||
$dailyChange = DailyChange::withDailyPerformance()
|
$dailyChange = DailyChange::withDailyPerformance()
|
||||||
->portfolio($portfolio->id)
|
->portfolio($portfolio->id)
|
||||||
->get()
|
->get();
|
||||||
->sortBy('date')
|
|
||||||
|
dump($dailyChange->toArray());
|
||||||
|
|
||||||
|
$dailyChange = $dailyChange->sortBy('date')
|
||||||
->groupBy('date')
|
->groupBy('date')
|
||||||
->map(function ($group) {
|
->map(function ($group) {
|
||||||
|
|
||||||
return (object) [
|
return (object) [
|
||||||
'date' => $group->first()->date->toDateString(),
|
'date' => $group->first()->date->toDateString(),
|
||||||
'total_market_value' => $group->sum('total_market_value'),
|
'total_market_value' => $group->sum('total_market_value'),
|
||||||
@@ -610,10 +640,10 @@ class MultiCurrencyTest extends TestCase
|
|||||||
->portfolio($portfolio->id)
|
->portfolio($portfolio->id)
|
||||||
->getPortfolioMetrics();
|
->getPortfolioMetrics();
|
||||||
|
|
||||||
$this->assertEqualsWithDelta($metrics->get('total_market_value'), $dailyChange->last()->total_market_value, 0.01);
|
$this->assertEqualsWithDelta($metrics->get('total_market_value'), $dailyChange->last()->total_market_value, 0.01); // TODO:
|
||||||
$this->assertEqualsWithDelta($metrics->get('total_cost_basis'), $dailyChange->last()->total_cost_basis, 0.01);
|
$this->assertEqualsWithDelta($metrics->get('total_cost_basis'), $dailyChange->last()->total_cost_basis, 0.01);
|
||||||
$this->assertEqualsWithDelta($metrics->get('realized_gain_dollars'), $dailyChange->last()->realized_gain_dollars, 0.01);
|
$this->assertEqualsWithDelta($metrics->get('realized_gain_dollars'), $dailyChange->last()->realized_gain_dollars, 0.01);
|
||||||
$this->assertEqualsWithDelta($metrics->get('total_market_value') - $metrics->get('total_cost_basis'), $dailyChange->last()->total_gain, 0.01);
|
$this->assertEqualsWithDelta($metrics->get('total_market_value') - $metrics->get('total_cost_basis'), $dailyChange->last()->total_gain, 0.01); // TODO:
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_multi_currency_import_calculates_correct_holding_data(): void
|
public function test_multi_currency_import_calculates_correct_holding_data(): void
|
||||||
|
|||||||
Reference in New Issue
Block a user