diff --git a/app/Interfaces/MarketData/AlphaVantageMarketData.php b/app/Interfaces/MarketData/AlphaVantageMarketData.php index 524a587..17c4856 100644 --- a/app/Interfaces/MarketData/AlphaVantageMarketData.php +++ b/app/Interfaces/MarketData/AlphaVantageMarketData.php @@ -18,15 +18,7 @@ class AlphaVantageMarketData implements MarketDataInterface public function exists(string $symbol): bool { - try { - $this->quote($symbol); - - return true; - - } catch (\Throwable $e) { - - return false; - } + return (bool) $this->quote($symbol); } public function quote(string $symbol): Quote diff --git a/app/Interfaces/MarketData/FallbackInterface.php b/app/Interfaces/MarketData/FallbackInterface.php index ec6bcad..ff25749 100644 --- a/app/Interfaces/MarketData/FallbackInterface.php +++ b/app/Interfaces/MarketData/FallbackInterface.php @@ -39,6 +39,13 @@ class FallbackInterface } } + // don't need to throw error if calling exists + if ($method == 'exists') { + + // symbol prob just doesn't exist + return false; + } + throw new \Exception("Could not get market data: {$this->latest_error}"); } } diff --git a/app/Interfaces/MarketData/FinnhubMarketData.php b/app/Interfaces/MarketData/FinnhubMarketData.php index 244fa14..8cd561e 100644 --- a/app/Interfaces/MarketData/FinnhubMarketData.php +++ b/app/Interfaces/MarketData/FinnhubMarketData.php @@ -28,15 +28,7 @@ class FinnhubMarketData implements MarketDataInterface public function exists(string $symbol): bool { - try { - $this->quote($symbol); - - return true; - - } catch (\Throwable $e) { - - return false; - } + return (bool) $this->quote($symbol); } public function quote(string $symbol): Quote diff --git a/app/Interfaces/MarketData/YahooMarketData.php b/app/Interfaces/MarketData/YahooMarketData.php index c9830e1..3261a2f 100644 --- a/app/Interfaces/MarketData/YahooMarketData.php +++ b/app/Interfaces/MarketData/YahooMarketData.php @@ -26,15 +26,7 @@ class YahooMarketData implements MarketDataInterface public function exists(string $symbol): bool { - try { - $this->quote($symbol); - - return true; - - } catch (\Throwable $e) { - - return false; - } + return (bool) $this->quote($symbol); } public function quote(string $symbol): Quote @@ -42,22 +34,18 @@ class YahooMarketData implements MarketDataInterface $quote = $this->client->getQuote($symbol); - if (is_null($quote)) { - throw new \Exception('Symbol ('.$symbol.') does not exist'); - } - return new Quote([ - 'name' => $quote->getLongName() ?? $quote->getShortName(), + 'name' => $quote?->getLongName() ?? $quote?->getShortName(), 'symbol' => $symbol, - 'market_value' => $quote->getRegularMarketPrice(), - 'fifty_two_week_high' => $quote->getFiftyTwoWeekHigh(), - 'fifty_two_week_low' => $quote->getFiftyTwoWeekLow(), - 'forward_pe' => $quote->getForwardPE(), - 'trailing_pe' => $quote->getTrailingPE(), - 'market_cap' => $quote->getMarketCap(), - 'book_value' => $quote->getBookValue(), - 'last_dividend_date' => $quote->getDividendDate(), - 'dividend_yield' => $quote->getTrailingAnnualDividendYield() * 100, + 'market_value' => $quote?->getRegularMarketPrice(), + 'fifty_two_week_high' => $quote?->getFiftyTwoWeekHigh(), + 'fifty_two_week_low' => $quote?->getFiftyTwoWeekLow(), + 'forward_pe' => $quote?->getForwardPE(), + 'trailing_pe' => $quote?->getTrailingPE(), + 'market_cap' => $quote?->getMarketCap(), + 'book_value' => $quote?->getBookValue(), + 'last_dividend_date' => $quote?->getDividendDate(), + 'dividend_yield' => $quote?->getTrailingAnnualDividendYield() * 100, ]); } diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index b734633..0962232 100644 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -143,6 +143,7 @@ class Transaction extends Model public function refreshMarketData(): void { + MarketData::getMarketData($this->attributes['symbol']); } diff --git a/app/Rules/SymbolValidationRule.php b/app/Rules/SymbolValidationRule.php index c01e844..428b6b9 100644 --- a/app/Rules/SymbolValidationRule.php +++ b/app/Rules/SymbolValidationRule.php @@ -29,12 +29,13 @@ class SymbolValidationRule implements ValidationRule { $this->symbol = $value; + // Check if the symbol exists in the Market Data table first (avoid API call) if (MarketData::find($this->symbol)) { return; } - // Check if the symbol exists in the Market Data table first (avoid API call) + // Then check against market data provider if (! app(MarketDataInterface::class)->exists($value)) { $fail('The symbol provided ('.$this->symbol.') is not valid'); } diff --git a/tests/FallbackInterfaceTest.php b/tests/FallbackInterfaceTest.php index 6053fe2..484fae0 100644 --- a/tests/FallbackInterfaceTest.php +++ b/tests/FallbackInterfaceTest.php @@ -77,4 +77,30 @@ class FallbackInterfaceTest extends TestCase Log::shouldHaveReceived('warning')->with('Failed calling method quote (yahoo): Yahoo failed'); Log::shouldHaveReceived('warning')->with('Failed calling method quote (alpha): Alpha failed'); } + + public function test_exists_method_fails_without_exception() + { + config()->set('investbrain.provider', 'yahoo,alpha'); + config()->set('investbrain.interfaces', [ + 'yahoo' => YahooMarketData::class, + 'alphavantage' => AlphaVantageMarketData::class, + ]); + + $yahooMock = Mockery::mock(YahooMarketData::class); + $yahooMock->shouldReceive('exists') + ->andThrow(new \Exception('Yahoo failed')); + + $alphaMock = Mockery::mock(AlphaVantageMarketData::class); + $alphaMock->shouldReceive('exists') + ->andThrow(new \Exception('Alpha failed')); + + $this->app->instance(YahooMarketData::class, $yahooMock); + $this->app->instance(AlphaVantageMarketData::class, $alphaMock); + + $fallbackInterface = new FallbackInterface; + + $result = $fallbackInterface->exists('ZZZ'); + + $this->assertFalse($result); + } }