adds dividend re-investment feature

This commit is contained in:
hackerESQ
2024-10-18 20:46:22 -05:00
parent e4d45f391c
commit 51c33ebec0
14 changed files with 218 additions and 17 deletions
+35 -6
View File
@@ -6,6 +6,7 @@ use App\Models\Holding;
use App\Models\MarketData;
use App\Models\Transaction;
use Illuminate\Support\Str;
use Illuminate\Support\Carbon;
use Illuminate\Database\Eloquent\Model;
use App\Interfaces\MarketData\MarketDataInterface;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
@@ -86,10 +87,15 @@ class Dividend extends Model
(new self)->insert($dividend_data->toArray());
// sync to holdings
self::syncHoldings($dividend_data);
self::syncHoldings($symbol);
// get market data
$market_data = MarketData::firstOrNew(['symbol' => $symbol]);
// re-invest dividends
self::reinvestDividends($dividend_data, $market_data);
// sync last dividend amount to market data table
$market_data = MarketData::firstOrNew(['symbol' => $symbol]);
$market_data->last_dividend_amount = $dividend_data->sortByDesc('date')->first()['dividend_amount'];
$market_data->save();
}
@@ -97,10 +103,8 @@ class Dividend extends Model
return $dividend_data;
}
public static function syncHoldings($dividend_data): void
public static function syncHoldings(string $symbol): void
{
$symbol = $dividend_data->last()['symbol'];
// group by holdings
$dividends = self::select(['holdings.portfolio_id', 'dividends.date', 'dividends.symbol', 'dividends.dividend_amount'])
->selectRaw('
@@ -115,7 +119,7 @@ class Dividend extends Model
')
->join('transactions', 'transactions.symbol', '=', 'dividends.symbol')
->join('holdings', 'transactions.portfolio_id', '=', 'holdings.portfolio_id')
->where('dividends.symbol', $dividend_data->last()['symbol'])
->where('dividends.symbol', $symbol)
->groupBy('holdings.portfolio_id', 'dividends.date', 'dividends.symbol', 'dividends.dividend_amount', 'total_received')
->havingRaw('total_received > 0')
->get();
@@ -130,4 +134,29 @@ class Dividend extends Model
]);
});
}
public static function reinvestDividends(iterable $dividend_data, MarketData $market_data): void
{
// re-invest dividends
Holding::where([
'symbol' => $market_data->symbol,
'reinvest_dividends' => true,
])
->get()
->each(function($holding) use ($dividend_data, $market_data) {
foreach($dividend_data as $dividend) {
Transaction::create([
'date' => $dividend['date'],
'portfolio_id' => $holding->portfolio_id,
'symbol' => $holding->symbol,
'transaction_type' => "BUY",
'reinvested_dividend' => true,
'cost_basis' => $market_data->market_value,
'quantity' => ($dividend['dividend_amount'] * $holding->qtyOwned(Carbon::parse($dividend['date']))) / $market_data->market_value,
]);
}
});
}
}
+16 -1
View File
@@ -26,11 +26,13 @@ class Holding extends Model
'realized_gain_dollars',
'dividends_earned',
'splits_synced_at',
'reinvest_dividends'
];
protected $casts = [
'splits_synced_at' => 'datetime',
'first_transaction_date' => 'datetime'
'first_transaction_date' => 'datetime',
'reinvest_dividends' => 'boolean'
];
protected $attributes = [
@@ -209,6 +211,19 @@ class Holding extends Model
$this->save();
}
public function qtyOwned(\Illuminate\Support\Carbon $date = null)
{
if ($date == null) $date = now();
$transactions = $this->transactions->where('date', '<=', $date);
$purchases = $transactions->where('transaction_type', 'BUY')->sum('quantity');
$sales = $transactions->where('transaction_type', 'SELL')->sum('quantity');
return $purchases - $sales;
}
public function dailyPerformance(
\Illuminate\Support\Carbon $start_date = null,
\Illuminate\Support\Carbon $end_date = null,
+2
View File
@@ -23,6 +23,7 @@ class Transaction extends Model
'cost_basis',
'sale_price',
'split',
'reinvested_dividend'
];
protected $hidden = [];
@@ -30,6 +31,7 @@ class Transaction extends Model
protected $casts = [
'date' => 'datetime',
'split' => 'boolean',
'reinvested_dividend' => 'boolean'
];
protected static function boot()