This commit is contained in:
hackerESQ
2024-08-21 20:42:32 -05:00
parent b84bc94da6
commit 58533a454d
12 changed files with 118 additions and 86 deletions
@@ -4,7 +4,7 @@
$seriesData = array_merge([
'chart' => [
'type' => "area",
'stacked' => true,
'stacked' => false,
'height' => 300,
'foreColor' => "#999",
'dropShadow' => [
@@ -13,8 +13,11 @@
'toolbar' => [
'show' => false,
],
'zoom' => [
'enabled' => false
]
],
'colors' => ['#00E396', '#0090FF'],
'colors' => ['#3185FC', '#48435C', '#9792E3', '#00E396', '#B74F6F', ],
'stroke' => [
'curve' => "smooth",
'width' => 3
@@ -122,7 +125,7 @@
legendContainer.innerHTML = ''; // Clear any existing legend items
chartContext.w.globals.seriesNames.forEach(function (seriesName, i) {
var seriesColor = chartContext.w.config.colors[i];
var legendItem = document.createElement('div');
legendItem.classList.add('flex', 'items-center', 'm-2', 'cursor-pointer');
@@ -16,7 +16,7 @@
<x-menu-item title="{{ __('Create Portfolio') }}" icon="o-document-plus" link="{{ route('portfolio.create') }}" />
</x-menu-sub>
<x-menu-item title="{{ __('Transactions') }}" icon="o-banknotes" link="{{ route('transaction.index') }}" />
{{-- <x-menu-item title="{{ __('Transactions') }}" icon="o-banknotes" link="{{ route('transaction.index') }}" /> --}}
{{-- <x-menu-item title="{{ __('Reporting') }}" icon="o-chart-bar-square" link="####" /> --}}
</x-menu>
@@ -25,9 +25,9 @@ new class extends Component {
['key' => 'total_cost_basis', 'label' => __('Total Cost Basis')],
['key' => 'market_data_market_value', 'label' => __('Market Value')],
['key' => 'total_market_value', 'label' => __('Total Market Value')],
['key' => 'market_gain_loss_dollars', 'label' => __('Market Gain/Loss')],
['key' => 'market_gain_loss_percent', 'label' => __('Market Gain/Loss')],
['key' => 'realized_gain_loss_dollars', 'label' => __('Realized Gain/Loss')],
['key' => 'market_gain_dollars', 'label' => __('Market Gain/Loss')],
['key' => 'market_gain_percent', 'label' => __('Market Gain/Loss')],
['key' => 'realized_gain_dollars', 'label' => __('Realized Gain/Loss')],
['key' => 'dividends_earned', 'label' => __('Dividends Earned')],
['key' => 'market_data_fifty_two_week_low', 'label' => __('52 week low')],
['key' => 'market_data_fifty_two_week_high', 'label' => __('52 week high')],
@@ -40,9 +40,6 @@ new class extends Component {
{
return $this->portfolio
->holdings()
->with(['transactions' => function ($query) {
$query->portfolio($this->portfolio->id);
}])
->withCount(['transactions as num_transactions' => function ($query) {
$query->portfolio($this->portfolio->id);
}])
@@ -52,8 +49,8 @@ new class extends Component {
->withAggregate('market_data', 'fifty_two_week_high')
->withAggregate('market_data', 'updated_at')
->selectRaw('(market_data.market_value * holdings.quantity) AS total_market_value')
->selectRaw('((market_data.market_value - holdings.average_cost_basis) * holdings.quantity) AS market_gain_loss_dollars')
->selectRaw('(((market_data.market_value - holdings.average_cost_basis) / holdings.average_cost_basis) * 100) AS market_gain_loss_percent')
->selectRaw('((market_data.market_value - holdings.average_cost_basis) * holdings.quantity) AS market_gain_dollars')
->selectRaw('(((market_data.market_value - holdings.average_cost_basis) / holdings.average_cost_basis) * 100) AS market_gain_percent')
->join('market_data', 'holdings.symbol', 'market_data.symbol')
->orderBy(...array_values($this->sortBy))
->where('quantity', '>', 0)
@@ -1,5 +1,6 @@
<?php
use App\Models\DailyChange;
use App\Models\Portfolio;
use Livewire\Attributes\{Title, Rule};
use Livewire\Volt\Component;
@@ -11,70 +12,83 @@ new class extends Component {
public String $name = 'portfolio';
public String $scope = 'YTD';
public Array $options = [
['id' => '1M', 'name' => '1 month'],
['id' => '3M', 'name' => '3 months'],
['id' => 'YTD', 'name' => 'Year to date'],
['id' => '1Y', 'name' => '1 year'],
['id' => '3Y', 'name' => '3 years'],
['id' => 'ALL', 'name' => 'All time']
['id' => '1M', 'name' => '1 month', 'method' => 'subMonths', 'args' => [1]],
['id' => '3M', 'name' => '3 months', 'method' => 'subMonths', 'args' => [3]],
['id' => 'YTD', 'name' => 'Year to date', 'method' => 'startOfYear', 'args' => []],
['id' => '1Y', 'name' => '1 year', 'method' => 'subYears', 'args' => [1]],
['id' => '3Y', 'name' => '3 years', 'method' => 'subYears', 'args' => [3]],
['id' => 'ALL', 'name' => 'All time', 'method' => null]
];
// data
public Array $myChart;
public Array $chartSeries;
// methods
public function mount()
{
$this->myChart = [
$this->chartSeries = $this->generatePerformanceData();
}
public function generatePerformanceData()
{
$filterMethod = collect($this->options)->where('id', $this->scope)->first();
$dailyChangeQuery = DailyChange::query();
if (isset($this->portfolio)) {
$dailyChangeQuery->portfolio($this->portfolio->id);
} else {
$dailyChangeQuery->selectRaw('date,
SUM(total_market_value) as total_market_value,
SUM(total_cost_basis) as total_cost_basis,
SUM(total_gain) as total_gain,
SUM(total_dividends_earned) as total_dividends_earned,
SUM(realized_gains) as realized_gains'
)->groupBy('date');
}
if ($filterMethod['method']) {
$dailyChangeQuery->whereDate('date', '>=', now()->{$filterMethod['method']}(...$filterMethod['args']));
}
$dailyChange = $dailyChangeQuery->get();
return [
'series' => [
[
'name' => __('Total Views'),
'data' => $this->generateDateSeries('2024-01-01', '2024-08-01')
],
'name' => __('Market Value'),
'data' => $dailyChange->map(fn($data) => [$data->date, $data->total_market_value])->toArray(),
],
[
'name' => __('Second Views'),
'data' => $this->generateDateSeries('2024-01-01', '2024-08-01')
],
],
'name' => __('Cost Basis'),
'data' => $dailyChange->map(fn($data) => [$data->date, $data->total_cost_basis])->toArray(),
],
[
'name' => __('Market Gain'),
'data' => $dailyChange->map(fn($data) => [$data->date, $data->total_gain])->toArray()
],
[
'name' => __('Dividends Earned'),
'data' => $dailyChange->map(fn($data) => [$data->date, $data->total_dividends_earned])->toArray()
],
[
'name' => __('Realized Gains'),
'data' => $dailyChange->map(fn($data) => [$data->date, $data->realized_gains])->toArray()
],
]
];
// $this->marketGainLoss = rand(-200, 3999);
}
public function changeScope($scope)
{
$this->scope = $scope;
$this->dispatch('data-scope-updated', $scope);
$this->chartSeries = $this->generatePerformanceData();
}
public function getScopeName($scope)
{
return collect($this->options)->where('id', $scope)['name'];
}
private function generateDateSeries($startDate, $endDate)
{
$dateArray = [];
$currentDate = strtotime($startDate);
$endDate = strtotime($endDate);
while ($currentDate <= $endDate) {
// Generate a random integer
$randomInt = rand(1000, 3000);
// Format the current date to 'Y-m-d'
$formattedDate = date('Y-m-d', $currentDate);
// Append the date and random integer to the array
$dateArray[] = [$formattedDate, $randomInt];
// Move to the next day
$currentDate = strtotime("+1 day", $currentDate);
}
return $dateArray;
return collect($this->options)->where('id', $scope)->first()['name'];
}
}; ?>
@@ -90,7 +104,7 @@ new class extends Component {
</div>
<div class="flex items-center">
<x-button title="{{ __('Reset chart') }}" icon="o-arrow-path" class="btn-ghost btn-sm btn-circle mr-2" id="chart-reset-zoom-{{ $name }}" />
{{-- <x-button title="{{ __('Reset chart') }}" icon="o-arrow-path" class="btn-ghost btn-sm btn-circle mr-2" id="chart-reset-zoom-{{ $name }}" /> --}}
<x-dropdown title="{{ __('Choose time period') }}" label="{{ $scope }}" class="btn-ghost btn-sm">
@@ -110,7 +124,7 @@ new class extends Component {
<div
class="h-[280px] mb-5"
>
<x-ib-apex-chart :series-data="$myChart" :name="$name" />
<x-ib-apex-chart :series-data="$chartSeries" :name="$name" />
</div>
</x-card>
+6 -5
View File
@@ -53,29 +53,30 @@
<div class="grid sm:grid-cols-5 gap-5">
<x-card class="col-span-5 sm:col-span-1 bg-slate-100 dark:bg-base-200 rounded-lg">
<div class="text-sm text-gray-400 whitespace-nowrap">{{ __('Market Gain/Loss') }}</div>
<div class="font-black text-xl"> {{ Number::currency($portfolio->marketGainLoss) }} </div>
<div class="font-black text-xl"> {{ Number::currency($metrics->total_gain_dollars) }} </div>
</x-card>
<x-card class="col-span-5 sm:col-span-1 bg-slate-100 dark:bg-base-200 rounded-lg">
<div class="text-sm text-gray-400 whitespace-nowrap">{{ __('Total Cost Basis') }}</div>
<div class="font-black text-xl"> {{ Number::currency($portfolio->totalCostBasis) }} </div>
<div class="font-black text-xl"> {{ Number::currency($metrics->total_cost_basis) }} </div>
</x-card>
<x-card class="col-span-5 sm:col-span-1 bg-slate-100 dark:bg-base-200 rounded-lg">
<div class="text-sm text-gray-400 whitespace-nowrap">{{ __('Total Market Value') }}</div>
<div class="font-black text-xl"> {{ Number::currency($portfolio->totalMarketValue) }} </div>
<div class="font-black text-xl"> {{ Number::currency($metrics->total_market_value) }} </div>
</x-card>
<x-card class="col-span-5 sm:col-span-1 bg-slate-100 dark:bg-base-200 rounded-lg">
<div class="text-sm text-gray-400 whitespace-nowrap">{{ __('Realized Gain/Loss') }}</div>
<div class="font-black text-xl"> {{ Number::currency($portfolio->realizedGainLoss) }} </div>
<div class="font-black text-xl"> {{ Number::currency($metrics->realized_gain_dollars) }} </div>
</x-card>
<x-card class="col-span-5 sm:col-span-1 bg-slate-100 dark:bg-base-200 rounded-lg">
<div class="text-sm text-gray-400 whitespace-nowrap">{{ __('Dividends Earned') }}</div>
<div class="font-black text-xl"> {{ Number::currency($portfolio->dividendsEarned) }} </div>
<div class="font-black text-xl"> {{ Number::currency($metrics->total_dividends_earned) }} </div>
</x-card>
</div>