From 2d5fdda2cd6d773eb6a4dbc859b2bffc47fd297e Mon Sep 17 00:00:00 2001 From: hackerESQ Date: Tue, 17 Sep 2024 19:44:29 -0500 Subject: [PATCH] wip --- .../MarketData/NasdaqMarketData.php | 144 ++++++++++++++++++ routes/web.php | 26 ++++ 2 files changed, 170 insertions(+) create mode 100644 app/Interfaces/MarketData/NasdaqMarketData.php diff --git a/app/Interfaces/MarketData/NasdaqMarketData.php b/app/Interfaces/MarketData/NasdaqMarketData.php new file mode 100644 index 0000000..eff28ac --- /dev/null +++ b/app/Interfaces/MarketData/NasdaqMarketData.php @@ -0,0 +1,144 @@ +quote($symbol)->isNotEmpty(); + } + + public function quote(String $symbol): Collection + { + // https://api.nasdaq.com/api/quote/GOOG/info?assetclass=stocks + + $quote = Alphavantage::core()->quoteEndpoint($symbol); + $quote = Arr::get($quote, 'Global Quote', []); + + // https://api.nasdaq.com/api/quote/GOOG/summary?assetclass=stocks + + $fundamental = cache()->tags(['quote', 'alpha-vantage', $symbol])->remember( + 'symbol-'.$symbol, + 1440, + function () use ($symbol) { + return Alphavantage::fundamentals()->overview($symbol); + } + ); + + if (empty($fundamental)) return collect(); + + return collect([ + 'name' => Arr::get($fundamental, 'Name'), + 'symbol' => Arr::get($fundamental, 'Symbol'), + 'market_value' => Arr::get($quote, '05. price'), + 'fifty_two_week_high' => Arr::get($fundamental, '52WeekHigh'), + 'fifty_two_week_low' => Arr::get($fundamental, '52WeekLow'), + 'forward_pe' => Arr::get($fundamental, 'ForwardPE'), + 'trailing_pe' => Arr::get($fundamental, 'TrailingPE'), + 'market_cap' => Arr::get($fundamental, 'MarketCapitalization'), + 'book_value' => Arr::get($fundamental, 'BookValue'), + 'last_dividend_date' => Arr::get($fundamental, 'DividendDate') != 'None' + ? Arr::get($fundamental, 'DividendDate') + : null, + 'dividend_yield' => Arr::get($fundamental, 'DividendYield') != 'None' + ? Arr::get($fundamental, 'DividendYield') + : null + ]); + } + + public function dividends(String $symbol, $startDate, $endDate): Collection + { + // https://api.nasdaq.com/api/quote/GOOG/dividends?assetclass=stocks + + $dividends = Alphavantage::fundamentals()->dividends($symbol); + $dividends = Arr::get($dividends, 'data', []); + + return collect($dividends) + ->filter(function($dividend) use ($startDate, $endDate) { + + return Carbon::parse(Arr::get($dividend, 'ex_dividend_date'))->between($startDate, $endDate); + }) + ->map(function($dividend) use ($symbol) { + + return [ + 'symbol' => $symbol, + 'date' => Carbon::parse(Arr::get($dividend, 'ex_dividend_date')) + ->format('Y-m-d H:i:s'), + 'dividend_amount' => Arr::get($dividend, 'amount'), + ]; + }); + } + + public function splits(String $symbol, $startDate, $endDate): Collection + { + throw new \Exception('The Nasdaq provider does not offer a splits endpoint.'); + } + + public function history(String $symbol, $startDate, $endDate): Collection + { + + // https://api.nasdaq.com/api/quote/GOOG/historical?assetclass=stocks&fromdate=2014-09-16&limit=2000&offset=10&todate=2024-09-16 + // https://api.nasdaq.com/api/quote/GOOG/chart?assetclass=stocks&fromdate=2014-09-16&todate=2024-09-16 + + $history = Alphavantage::timeSeries()->daily($symbol, 'full'); + + $history = Arr::get($history, 'Time Series (Daily)', []); + + return collect($history) + ->filter(function ($history, $date) use ($startDate, $endDate) { + + return Carbon::parse($date)->between($startDate, $endDate); + }) + ->mapWithKeys(function($history, $date) use ($symbol) { + + $date = Carbon::parse($date)->format('Y-m-d'); + + return [ $date => [ + 'symbol' => $symbol, + 'date' => $date, + 'close' => (float) Arr::get($history, '4. close') + ]]; + }); + } + + public function nasdaqClient($symbol, $method, $params = [], $retry = false): Array|Object + // protected function nasdaqClient($symbol, $method, $params = [], $retry = false): Array|Object + { + + $symbol = strtoupper($symbol); + $params = array_merge([ + 'assetclass' => 'stocks' + ], $params); + + if (!in_array($method, ['info', 'summary', 'dividends', 'historical', 'chart'])) { + + throw new \Exception('This is not a valid method.'); + } + + $endpoint = 'https://api.nasdaq.com/api/quote'; + + // return [url("$endpoint/$symbol/$method?assetclass=stock", $params), $params]; + + $response = Http::get("https://api.nasdaq.com/api/quote/$symbol/$method?assetclass=stock", $params)->json(); + + // if ($response->status->rCode != 200) { + + // if ($retry == true) { + // throw new \Exception("Couldn't resolve $method for $symbol from Nasdaq."); + // } + + // return $this->nasdaqClient($symbol, $method, array_merge($params, [ 'assetclass' => 'etf' ]), retry: true); + // } + + return $response; + } +} \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 3637157..f61ba8a 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,10 +1,13 @@ 'stocks', + ]) + ->withCookies(['akaalb_ALB_Default' => '=~op=ao_api__east1:ao_api_east1|~rv=76~m=ao_api_east1:0|~os=ff51b6e767de05e2054c5c99e232919a~id=a7cdebc3132b5b30c8507ad37aec9418'], 'api.nasdaq.com') + ->withHeader('accept', '*/*') + ->withUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36') + ->timeout(4) + ->withOptions(['debug' => true]) + ->get("https://api.nasdaq.com/api/quote/GOOG/info"); + } catch (\Exception $e) { + + } + + return $cookieJar->toArray(); + return $response->getHeaders(); + return $response; + // return Http::get("https://api.nasdaq.com/api/quote/GOOG/info?assetclass=stocks"); + + return (new NasdaqMarketData)->nasdaqClient('AAPL', 'info'); }); Route::middleware(['auth:sanctum', config('jetstream.auth_session'), 'verified'])->group(function () {