wip sync daily holdings

This commit is contained in:
hackerESQ
2024-09-11 23:04:21 -05:00
parent eb6e7b9002
commit a4f2def766
4 changed files with 53 additions and 11 deletions
+37 -5
View File
@@ -2,17 +2,21 @@
namespace App\Console\Commands; namespace App\Console\Commands;
use App\Models\Portfolio;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use App\Interfaces\MarketData\MarketDataInterface; use Illuminate\Contracts\Console\PromptsForMissingInput;
use function Laravel\Prompts\search;
class SyncDailyChange extends Command class SyncDailyChange extends Command implements PromptsForMissingInput
{ {
/** /**
* The name and signature of the console command. * The name and signature of the console command.
* *
* @var string * @var string
*/ */
protected $signature = 'sync:daily-change'; protected $signature = 'sync:daily-change
{portfolio_id : The ID of the portfolio to re-calculate.}
{--force : Don\'t ask to confirm.}';
/** /**
* The console command description. * The console command description.
@@ -21,6 +25,24 @@ class SyncDailyChange extends Command
*/ */
protected $description = 'Re-calculates daily snapshots of your portfolio\'s daily performance. Use discretion as this is a resource intensive command.'; protected $description = 'Re-calculates daily snapshots of your portfolio\'s daily performance. Use discretion as this is a resource intensive command.';
/**
* Prompt for missing input arguments using the returned questions.
*
* @return array<string, string>
*/
protected function promptForMissingArgumentsUsing(): array
{
return [
'portfolio_id' => fn () => search(
label: 'Choose the portfolio you wish to re-calculate:',
placeholder: 'E.g. My favorite stocks',
options: fn ($value) => strlen($value) > 0
? Portfolio::where('title', 'like', "%{$value}%")->pluck('title', 'id')->all()
: []
),
];
}
/** /**
* Create a new command instance. * Create a new command instance.
* *
@@ -38,7 +60,17 @@ class SyncDailyChange extends Command
*/ */
public function handle() public function handle()
{ {
// get history try {
// $history = app(MarketDataInterface::class)->history($symbol);
$portfolio = Portfolio::findOrFail($this->argument('portfolio_id'));
$portfolio->syncDailyChanges();
$this->line('Awesome! Daily change history for '. $portfolio->title .' has been completed.');
} catch (\Throwable $e) {
$this->error($e->getMessage());
}
} }
} }
@@ -89,7 +89,7 @@ class AlphaVantageMarketData implements MarketDataInterface
public function history($symbol, $startDate, $endDate): Collection public function history($symbol, $startDate, $endDate): Collection
{ {
$history = Alphavantage::timeSeries()->daily($symbol); $history = Alphavantage::timeSeries()->daily($symbol, 'full');
$history = Arr::get($history, 'Time Series (Daily)', []); $history = Arr::get($history, 'Time Series (Daily)', []);
+5
View File
@@ -232,7 +232,12 @@ class Holding extends Model
$date_interval = "DATE_ADD(date, INTERVAL 1 DAY)"; $date_interval = "DATE_ADD(date, INTERVAL 1 DAY)";
if (config('database.default') === 'sqlite') { if (config('database.default') === 'sqlite') {
$date_interval = "date(date, '+1 day')"; $date_interval = "date(date, '+1 day')";
} else if (config('database.default') === 'mysql') {
DB::statement('SET GLOBAL cte_max_recursion_depth = 20000;');
} }
return DB::table(DB::raw("( return DB::table(DB::raw("(
+10 -5
View File
@@ -98,15 +98,16 @@ class Portfolio extends Model
$join->on('transactions.symbol', '=', 'holdings.symbol') $join->on('transactions.symbol', '=', 'holdings.symbol')
->where('transactions.portfolio_id', '=', $this->id); ->where('transactions.portfolio_id', '=', $this->id);
}) })
->select('holdings.*', DB::raw('min(transactions.date) as first_transaction_date')) // get first transaction date ->select('holdings.symbol', 'holdings.portfolio_id', DB::raw('min(transactions.date) as first_transaction_date')) // get first transaction date
->groupBy('holdings.symbol') ->groupBy(['holdings.symbol', 'holdings.portfolio_id'])
->get(); ->get();
$total_performance = []; $total_performance = [];
$holdings->each(function($holding) use (&$total_performance) { $holdings->each(function($holding) use (&$total_performance) {
$all_history = app(MarketDataInterface::class)->history('ACME', $holding->first_transaction_date, now()); $all_history = app(MarketDataInterface::class)->history($holding->symbol, $holding->first_transaction_date, now());
$quantity = $holding->dailyPerformance($holding->first_transaction_date, now()); $quantity = $holding->dailyPerformance($holding->first_transaction_date, now());
$dividends = $holding->dividends->keyBy(function ($dividend, $key) { $dividends = $holding->dividends->keyBy(function ($dividend, $key) {
@@ -150,8 +151,12 @@ class Portfolio extends Model
} }
}); });
$this->daily_change()->delete(); if (!empty($total_performance)) {
DB::transaction(function () use ($total_performance) {
$this->daily_change()->delete();
DailyChange::insert($total_performance); DailyChange::insert($total_performance);
});
}
} }
} }