You are returning early?
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
));
}
@tykus I am sorry, i don't understand what you mean.
@robert97 this
foreach($prices as $price){
return $prices;
}
@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.
@robert97 but you return out of the method before you do anything, what was the intended purpose of the loops?
@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.
@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???
@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();
@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???
@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')
@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?
@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();
@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)?
@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?
@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;
}
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.
And from each collection ii need the 'date' raw so $dividend->date , $price->date and for case : $dividend->dividend and $price->price.
$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 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
@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???
@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.
@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'];
});
@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{}
}
@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???
}
@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
));
@tykus Can you?
Please or to participate in this conversation.