wip sync daily holdings
This commit is contained in:
@@ -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)', []);
|
||||||
|
|
||||||
|
|||||||
@@ -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("(
|
||||||
|
|||||||
@@ -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
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!empty($total_performance)) {
|
||||||
|
DB::transaction(function () use ($total_performance) {
|
||||||
$this->daily_change()->delete();
|
$this->daily_change()->delete();
|
||||||
|
|
||||||
DailyChange::insert($total_performance);
|
DailyChange::insert($total_performance);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user