Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

robert97's avatar

Collection properties not working

I have a command, and here a i need to iterate over 2 collections, then use their properties for a math formula that would be "yield":

$stock = Stock::whereSymbol($this->argument('stock'))->first();

$dividends = $stock->dividends()
->selectRaw('ex_date as date')
->selectRaw('dividend as dividend')
->get();

$prices = $stock->dailyClosePrices()
->selectRaw('date as date')
->selectRaw('close_price as price')
->get();

foreach($prices as $price){
    return $prices;
}

foreach($dividends as $dividend){
    return $dividends;
}

$dividendYield = $stock->dividendYields();

if(!$dividendYield){
    resolve(CreateDividendYieldAction::class)->create(new DividendyieldData(
        stock: $stock,
        date: $price->date,
        yield: $dividend->dividend/$price->price*100,
        price: $price->price,
        yearlyDividend: $dividends->dividend
    ));
}
0 likes
27 replies
robert97's avatar

@tykus I did that because i want all $prices and $dividends and also i need to use their properties in that Actions below to fill the rows.

tykus's avatar

@robert97 but you return out of the method before you do anything, what was the intended purpose of the loops?

robert97's avatar

@tykus I put the loops in the if statement, but also nothing. The purpose is to have every $price->date, $price->price and also $dividend->date, $dividend->dividend so i can create that DividendYield and fill the raws in my databases.

tykus's avatar

@robert97 how do you pick the price and dividend that combine to compute the DividendYield - you have Collections at the moment; but you need one item from each Collection I suppose???

robert97's avatar

@tykus In my database:

	stocks_table -> 'id' , 'name' , 'symbol' HAS DATA
	daily_close_prices_table -> 'id', 'stock_id', 'date', 'close_price' HAS A BUNCH OF DATAS
	dividends_table-> 'id', 'stock_id', 'ex_date', 'dividend' HAS A BUNCH OF DATAS

	dividend_yields_table-> 'id', 'stock_id', 'date' , 'yield', 'price', 'yearly_dividend'- NO DATA

That is why i use

		$dividends = $stock->dividends()->get();
        $prices = $stock->dailyClosePrices()->get();
tykus's avatar

@robert97 that's not what I asked. If you have a Collection of $prices and a Collection of $dividends; and DividendYield is computed based on one item from $prices and one item from $dividends; how do we know which items to use???

robert97's avatar

@tykus To compute DividendYield i need :

$stock-id (i know how to get it)
$price->date
$price->close_price
$dividend->dividend

And the formula for yield is :

$dividend->dividend / $price->close_price * 100

These are the 5 datas that i need to feel dividend_yields_table from my database with the data from each price and each dividend, that is why i want to use iterate for getting datas from every single $price and every single $dividend which i have in my database tables ('daily_close_prices_table', 'dividends_table')

tykus's avatar

@robert97 you're making this really difficult... these queries return two Collections:

$dividends = $stock->dividends()
->selectRaw('ex_date as date')
->selectRaw('dividend as dividend')
->get();

$prices = $stock->dailyClosePrices()
->selectRaw('date as date')
->selectRaw('close_price as price')
->get();

So you have many prices and many dividends. As you iterate over either Collection; how do you select the item from the other Collection to compute the DividendYield?

robert97's avatar

@tykus That is what i want to find out ! I did not find a way yet, the iteration it's just a try maybe it's not a good idea, but how can i get every price and every dividend, and then use them to compute DividendYield? update: I also try to leave them as below, maybe it's better? i really don't know ...

		$dividends = $stock->dividends()->get();

        $prices = $stock->dailyClosePrices()->get();
tykus's avatar

@robert97 I can't help you with the business logic because I don't know what it should be. Should every price be matched against every dividend - so the end result is M x N DividendYield records (given M prices and N dividends)?

robert97's avatar

@tykus Don't think it's a business logic, i'm trying to make it programming clear: I have 2 collections, i want, with every given results from each, to compute another collection Forget about the formula, let's say that i want $price->close_price + $dividend->dividend, how can o do that?

tykus's avatar

@robert97 so the Nth item in each Collection is matched; meaning there is the same number of items in each Collection? Very basically, it will be like this:

$result = [];
foreach($prices as $index => $price) {
    $result[] = $price->close_price + $dividends[$index]->dividend;
}
robert97's avatar

I need a solution for that Action to create a DividendYield with datas came from both collections ( $prices and $dividends ) as you see, i need properties from both of them.

robert97's avatar

And from each collection ii need the 'date' raw so $dividend->date , $price->date and for case : $dividend->dividend and $price->price.

robert97's avatar

@tykus

$dividends = $stock->dividends()->get();

$prices = $stock->dailyClosePrices()->get();

$result = $price->close_price + $dividend->dividend;

How can i get $price->close_price  and $dividend->dividend?
tykus's avatar

@robert97 see this

I don't think it is actually the solution you need but we're taking baby steps now...

robert97's avatar

@tykus It is not working because

foreach($dividends as $dividend){
	{{ $dividend->dividend }} 
} 
This returns  93 results

foreach($dividends as $dividend){
	{{ $dividend->ex_date }} 
} 
This returns also 93 results

foreach($prices as $price){
	{{ $price->close_price }} 
} 
This returns  10,565 results

	foreach($prices as $price){
	{{ $price->date }} 
} 
This returns also  10,565 results
tykus's avatar

@robert97 of course it's not working if the two Collections are different sizes that is why I asked so the Nth item in each Collection is matched; meaning there is the same number of items in each Collection?.

You still cannot answer the very basic question of the 93 $dividends, and 10,565 $prices , which individual $price and individual $dividend are you using here $price->close_price + $dividend->dividend???

robert97's avatar

@tykus I understand what you asked now but the answer is not that easy. You see, every $price is daily, that is why a have 10,565 prices and 10,565 dates, for every day is a different price.

But when it comes to dividends, well yes i have 93 of them and also i do have 93 dates, like that : - a dividend it's declared (almost) once in a 3 months, and every (declaration)date matches with one dividend from then. The real example from my database for, let's say 3 examples of dividends, is :

Dividend 1 
$dividend->date => 2022-11-04;
$dividend->dividend => 0.23;

Dividend 2
$dividend->date => 2022-08-05;
$dividend->dividend => 0.22;

Dividend 3
$dividend->date => 2022-05-06;
$dividend->dividend => 0.25;

Dividend 4
$dividend->date => 2022-01-05;
$dividend->dividend => 0.25;

As you may see, it's declared irregular. SO WHAT I ACTUALY WANT IS :

$dividend->dividend (FROM DIVIDEND 1 ) + $price->price( FROM TODAY AND EVERY DAILY PRICES TILL 2022-08-06) 

Then

$dividend->dividend (FROM DIVIDEND 2) + $price->price( FROM 2022-05-06 AND EVERY DAILY PRICES TILL 2022-01-06) .... and so on

Value from dividend to be the same until it's the new declaration date, but the price to be the daily value from database. So $dividend->dividend (FROM DIVIDEND 1 ) will remain 0.23 almost 3 months but the price will be different.

tykus's avatar

@robert97 okay, now we're getting somewhere!

So the $prices Collection needs to be split into groups based on the corresponding $dividend date. Now, assuming each $price is individually added to the corresponding dividend (so you will have a result with 10,565 items in the end):

// Make sure `$dividends` is sorted by date asc.
$prices->map(function ($price) use ($dividends) {
    return $price->price + $dividends->firstWhere('date', '<=', $price->date)['dividend'];
});
1 like
robert97's avatar

@tykus I really hope that it's it man ! but, above i just say an example with " + " to make it a little bit clear... And i don't want to be rude to ask you how to make it work in my code, but i have difficulties ... So please, how can i fit the split in here?

	 public function handle()
{
    $stock = Stock::whereSymbol($this->argument('stock'))->first();
    
    $dividends= Dividend::where('stock_id', $stock->id)
        ->selectRaw('ex_date as date')
        ->selectRaw('dividend as dividend')
        ->orderBy('date', 'asc')
        ->get();

    $prices = DailyClosePrice::where('stock_id', $stock->id)
        ->selectRaw('date as date')
        ->selectRaw('close_price as price')
        ->orderBy('date', 'asc')
        ->get();

    $dividendYield = DividendYield::where('stock_id', $stock->id)->first();

    if(!$dividendYield){
        resolve(CreateDividendYieldAction::class)->create(new DividendYieldData(
            stock: $stock,
            date: $price->date,
            yield: $dividend->dividend/$price->price*100,
            price: $price->price,
            yearlyDividend: $dividend->dividend
        ));
    }else{}
}
tykus's avatar
tykus
Best Answer
Level 104

@robert97 I guess something like this...

if(!$dividendYield){
    foreach ($prices as $price) { 
        $dividend = $dividends->firstWhere('date', '>=', $price->date);

        resolve(CreateDividendYieldAction::class)->create(new DividendYieldData(
            stock: $stock,
            date: $price->date,
            yield: $dividend->dividend/$price->price*100,
            price: $price->price,
            yearlyDividend: $dividend->dividend
        ));
    }
} else {
    // what???
}
1 like
robert97's avatar

@tykus unbelievable man ! Thank you sooo much, it works! After days maybe weeks it works.... About that else, well the if statement says : if it's not exist, create it, otherwise find the latest records in the endpoint and update my database without recall all the action from above. Something like this:

		 $latestPrice = DailyClosePrice::where('stock_id', $stock->id)
        ->selectRaw('date as date')
        ->selectRaw('close_price as price')
        ->orderBy('date', 'desc')
        ->first();

         
    $latestDividend = Dividend::where('stock_id', $stock->id)
        ->selectRaw('ex_date as date')
        ->selectRaw('dividend as dividend')
        ->orderBy('date', 'desc')
        ->first();

//if(!$dividendYield){ ...........................................

		} else {
            resolve(CreateDividendYieldAction::class)->create(new DividendYieldData(
                stock: $stock,
                date: $latestPrice->date,
                yield: $latestDividend->dividend/$latestPrice->price*100,
                price: $latestPrice->price,
                yearlyDividend: $latestDividend->dividend
            ));

Please or to participate in this conversation.