From 13c4933eb80452d2ec87594fba259fc8b4cacc1d Mon Sep 17 00:00:00 2001 From: Lars Eijman Date: Fri, 5 Mar 2021 15:48:48 +0100 Subject: [PATCH] Added institutional fund endpoints --- src/Facades/InstitutionalFunds/Cik.php | 13 ++ src/Facades/InstitutionalFunds/CikList.php | 13 ++ src/Facades/InstitutionalFunds/CikSearch.php | 13 ++ .../InstitutionalFunds/CusipMapper.php | 13 ++ .../EtfCountryWeightings.php | 13 ++ src/Facades/InstitutionalFunds/EtfHolder.php | 13 ++ .../EtfSectorWeightings.php | 13 ++ src/Facades/InstitutionalFunds/Form13F.php | 13 ++ .../InstitutionalHolder.php | 13 ++ .../InstitutionalFunds/MutualFundHolder.php | 13 ++ src/Facades/InstitutionalFunds/SecRssFeed.php | 13 ++ src/InstitutionalFunds/Cik.php | 59 ++++++++ src/InstitutionalFunds/CikList.php | 30 ++++ src/InstitutionalFunds/CikSearch.php | 59 ++++++++ src/InstitutionalFunds/CusipMapper.php | 59 ++++++++ .../EtfCountryWeightings.php | 42 ++++++ src/InstitutionalFunds/EtfHolder.php | 42 ++++++ .../EtfSectorWeightings.php | 42 ++++++ src/InstitutionalFunds/Form13F.php | 91 ++++++++++++ .../InstitutionalHolder.php | 42 ++++++ src/InstitutionalFunds/MutualFundHolder.php | 42 ++++++ src/InstitutionalFunds/SecRssFeed.php | 44 ++++++ tests/InstitutionalFunds/CikListTest.php | 66 +++++++++ tests/InstitutionalFunds/CikSearchTest.php | 99 +++++++++++++ tests/InstitutionalFunds/CikTest.php | 69 +++++++++ tests/InstitutionalFunds/CusipMapperTest.php | 67 +++++++++ .../EtfCountryWeightingsTest.php | 64 +++++++++ tests/InstitutionalFunds/EtfHolderTest.php | 77 ++++++++++ .../EtfSectorWeightingsTest.php | 94 +++++++++++++ tests/InstitutionalFunds/Form13FTest.php | 133 ++++++++++++++++++ .../InstitutionalHolderTest.php | 81 +++++++++++ .../MutualFundHolderTest.php | 85 +++++++++++ tests/InstitutionalFunds/SecRssFeedTest.php | 108 ++++++++++++++ 33 files changed, 1638 insertions(+) create mode 100644 src/Facades/InstitutionalFunds/Cik.php create mode 100644 src/Facades/InstitutionalFunds/CikList.php create mode 100644 src/Facades/InstitutionalFunds/CikSearch.php create mode 100644 src/Facades/InstitutionalFunds/CusipMapper.php create mode 100644 src/Facades/InstitutionalFunds/EtfCountryWeightings.php create mode 100644 src/Facades/InstitutionalFunds/EtfHolder.php create mode 100644 src/Facades/InstitutionalFunds/EtfSectorWeightings.php create mode 100644 src/Facades/InstitutionalFunds/Form13F.php create mode 100644 src/Facades/InstitutionalFunds/InstitutionalHolder.php create mode 100644 src/Facades/InstitutionalFunds/MutualFundHolder.php create mode 100644 src/Facades/InstitutionalFunds/SecRssFeed.php create mode 100644 src/InstitutionalFunds/Cik.php create mode 100644 src/InstitutionalFunds/CikList.php create mode 100644 src/InstitutionalFunds/CikSearch.php create mode 100644 src/InstitutionalFunds/CusipMapper.php create mode 100644 src/InstitutionalFunds/EtfCountryWeightings.php create mode 100644 src/InstitutionalFunds/EtfHolder.php create mode 100644 src/InstitutionalFunds/EtfSectorWeightings.php create mode 100644 src/InstitutionalFunds/Form13F.php create mode 100644 src/InstitutionalFunds/InstitutionalHolder.php create mode 100644 src/InstitutionalFunds/MutualFundHolder.php create mode 100644 src/InstitutionalFunds/SecRssFeed.php create mode 100644 tests/InstitutionalFunds/CikListTest.php create mode 100644 tests/InstitutionalFunds/CikSearchTest.php create mode 100644 tests/InstitutionalFunds/CikTest.php create mode 100644 tests/InstitutionalFunds/CusipMapperTest.php create mode 100644 tests/InstitutionalFunds/EtfCountryWeightingsTest.php create mode 100644 tests/InstitutionalFunds/EtfHolderTest.php create mode 100644 tests/InstitutionalFunds/EtfSectorWeightingsTest.php create mode 100644 tests/InstitutionalFunds/Form13FTest.php create mode 100644 tests/InstitutionalFunds/InstitutionalHolderTest.php create mode 100644 tests/InstitutionalFunds/MutualFundHolderTest.php create mode 100644 tests/InstitutionalFunds/SecRssFeedTest.php diff --git a/src/Facades/InstitutionalFunds/Cik.php b/src/Facades/InstitutionalFunds/Cik.php new file mode 100644 index 0000000..1ed7aa5 --- /dev/null +++ b/src/Facades/InstitutionalFunds/Cik.php @@ -0,0 +1,13 @@ +id, self::ENDPOINT); + } + + /** + * @param string $id + * + * @return Cik + */ + public function setCik(string $id): self + { + $this->id = $id; + + return $this; + } + + /** + * @return bool|void + * @throws InvalidData + */ + protected function validateParams(): void + { + if (empty($this->id)) { + throw InvalidData::invalidDataProvided('Please provide a CIK code to the query!'); + } + } +} diff --git a/src/InstitutionalFunds/CikList.php b/src/InstitutionalFunds/CikList.php new file mode 100644 index 0000000..cb5af68 --- /dev/null +++ b/src/InstitutionalFunds/CikList.php @@ -0,0 +1,30 @@ +name, self::ENDPOINT); + } + + /** + * @param string $name + * + * @return CikSearch + */ + public function setName(string $name): self + { + $this->name = $name; + + return $this; + } + + /** + * @return bool|void + * @throws InvalidData + */ + protected function validateParams(): void + { + if (empty($this->name)) { + throw InvalidData::invalidDataProvided('Please provide a name to the query!'); + } + } +} diff --git a/src/InstitutionalFunds/CusipMapper.php b/src/InstitutionalFunds/CusipMapper.php new file mode 100644 index 0000000..67f0cba --- /dev/null +++ b/src/InstitutionalFunds/CusipMapper.php @@ -0,0 +1,59 @@ +cusip, self::ENDPOINT); + } + + /** + * @param string $cusip + * + * @return CusipMapper + */ + public function setCusip(string $cusip): self + { + $this->cusip = $cusip; + + return $this; + } + + /** + * @return bool|void + * @throws InvalidData + */ + protected function validateParams(): void + { + if (empty($this->cusip)) { + throw InvalidData::invalidDataProvided('Please provide a cusip to the query!'); + } + } +} diff --git a/src/InstitutionalFunds/EtfCountryWeightings.php b/src/InstitutionalFunds/EtfCountryWeightings.php new file mode 100644 index 0000000..b53233a --- /dev/null +++ b/src/InstitutionalFunds/EtfCountryWeightings.php @@ -0,0 +1,42 @@ +symbol, self::ENDPOINT); + } + + /** + * @return bool|void + * @throws InvalidData + */ + protected function validateParams(): void + { + if (empty($this->symbol)) { + throw InvalidData::invalidDataProvided('Please provide a symbol to query!'); + } + } +} diff --git a/src/InstitutionalFunds/EtfHolder.php b/src/InstitutionalFunds/EtfHolder.php new file mode 100644 index 0000000..58f9341 --- /dev/null +++ b/src/InstitutionalFunds/EtfHolder.php @@ -0,0 +1,42 @@ +symbol, self::ENDPOINT); + } + + /** + * @return bool|void + * @throws InvalidData + */ + protected function validateParams(): void + { + if (empty($this->symbol)) { + throw InvalidData::invalidDataProvided('Please provide a symbol to query!'); + } + } +} diff --git a/src/InstitutionalFunds/EtfSectorWeightings.php b/src/InstitutionalFunds/EtfSectorWeightings.php new file mode 100644 index 0000000..f52ab1a --- /dev/null +++ b/src/InstitutionalFunds/EtfSectorWeightings.php @@ -0,0 +1,42 @@ +symbol, self::ENDPOINT); + } + + /** + * @return bool|void + * @throws InvalidData + */ + protected function validateParams(): void + { + if (empty($this->symbol)) { + throw InvalidData::invalidDataProvided('Please provide a symbol to query!'); + } + } +} diff --git a/src/InstitutionalFunds/Form13F.php b/src/InstitutionalFunds/Form13F.php new file mode 100644 index 0000000..34178ad --- /dev/null +++ b/src/InstitutionalFunds/Form13F.php @@ -0,0 +1,91 @@ +cik = $cik; + + return $this; + } + + /** + * @return string + */ + protected function getFullEndpoint(): string + { + return str_replace('{cik}', $this->cik, self::ENDPOINT); + } + + /** + * @param string $date + * + * @return Form13F + */ + public function setDate(string $date): self + { + $this->date = $date; + array_push($this->query_string, ['date' => $date]); + + return $this; + } + + /** + * @return bool|void + * @throws InvalidData + */ + protected function validateParams(): void + { + if (empty($this->cik)) { + throw InvalidData::invalidDataProvided('Please provide a cik to the query!'); + } + + try { + $invalid_data_msg = 'The given date format is incorrect, expected; (\'Y-m-d\').'; + if (!empty($this->date)) { + if (Carbon::createFromFormat('Y-m-d', $this->date)->format('Y-m-d') != $this->date) { + throw new InvalidFormatException($invalid_data_msg); + } + } + } catch (InvalidFormatException $message) { + throw InvalidData::invalidDataProvided($invalid_data_msg); + } + } +} diff --git a/src/InstitutionalFunds/InstitutionalHolder.php b/src/InstitutionalFunds/InstitutionalHolder.php new file mode 100644 index 0000000..8d68083 --- /dev/null +++ b/src/InstitutionalFunds/InstitutionalHolder.php @@ -0,0 +1,42 @@ +symbol, self::ENDPOINT); + } + + /** + * @return bool|void + * @throws InvalidData + */ + protected function validateParams(): void + { + if (empty($this->symbol)) { + throw InvalidData::invalidDataProvided('Please provide a symbol to query!'); + } + } +} diff --git a/src/InstitutionalFunds/MutualFundHolder.php b/src/InstitutionalFunds/MutualFundHolder.php new file mode 100644 index 0000000..e5e2e78 --- /dev/null +++ b/src/InstitutionalFunds/MutualFundHolder.php @@ -0,0 +1,42 @@ +symbol, self::ENDPOINT); + } + + /** + * @return bool|void + * @throws InvalidData + */ + protected function validateParams(): void + { + if (empty($this->symbol)) { + throw InvalidData::invalidDataProvided('Please provide a symbol to query!'); + } + } +} diff --git a/src/InstitutionalFunds/SecRssFeed.php b/src/InstitutionalFunds/SecRssFeed.php new file mode 100644 index 0000000..936fb32 --- /dev/null +++ b/src/InstitutionalFunds/SecRssFeed.php @@ -0,0 +1,44 @@ +query_string, ['limit' => $limit]); + + return $this; + } +} diff --git a/tests/InstitutionalFunds/CikListTest.php b/tests/InstitutionalFunds/CikListTest.php new file mode 100644 index 0000000..eaf19bd --- /dev/null +++ b/tests/InstitutionalFunds/CikListTest.php @@ -0,0 +1,66 @@ +response = new Response(200, [], '[{ + "cik" : "0001767045", + "name" : "Lindbrook Capital, LLC " + }, { + "cik" : "0000913760", + "name" : "INTL FCSTONE INC. " + }, { + "cik" : "0001424322", + "name" : "Cubic Asset Management, LLC " + }, { + "cik" : "0001666363", + "name" : "Venturi Wealth Management, LLC " + }]'); + + $this->client = $this->setupMockedClient($this->response); + } + + /** @test */ + public function it_can_query_the_cik_list_endpoint() + { + $cik_list = new \Leijman\FmpApiSdk\InstitutionalFunds\CikList($this->client); + + $response = $cik_list->get(); + + $this->assertInstanceOf(Collection::class, $response); + $this->assertCount(4, $response); + $this->assertEquals('Venturi Wealth Management, LLC ', $response->last()->name); + $this->assertEquals('0001666363', $response->last()->cik); + } + + /** @test */ + public function it_can_call_the_facade() + { + $this->setConfig(); + + CikList::shouldReceive('get') + ->once() + ->andReturn(collect(json_decode($this->response->getBody()->getContents()))); + + $response = CikList::get(); + + $this->assertInstanceOf(Collection::class, $response); + $this->assertCount(4, $response); + } +} diff --git a/tests/InstitutionalFunds/CikSearchTest.php b/tests/InstitutionalFunds/CikSearchTest.php new file mode 100644 index 0000000..f7fd0fc --- /dev/null +++ b/tests/InstitutionalFunds/CikSearchTest.php @@ -0,0 +1,99 @@ +response = new Response(200, [], '[{ + "cik" : "0001067983", + "name" : " BERKSHIRE HATHAWAY" + }, { + "cik" : "0000949012", + "name" : " BERKSHIRE ASSET MANAGEMENT LLC/PA " + }, { + "cik" : "0000949012", + "name" : " BERKSHIRE ASSET MANAGEMENT INC/PA " + }, { + "cik" : "0001133742", + "name" : " BERKSHIRE CAPITAL HOLDINGS" + }, { + "cik" : "0001535172", + "name" : " Berkshire Money Management, Inc. " + }, { + "cik" : "0001067983", + "name" : "BERKSHIRE HATHAWAY" + }, { + "cik" : "0001312988", + "name" : "Berkshire Partners LLC" + }, { + "cik" : "0001133742", + "name" : "BERKSHIRE CAPITAL HOLDINGS" + }, { + "cik" : "0000949012", + "name" : "BERKSHIRE ASSET MANAGEMENT LLC/PA" + }, { + "cik" : "0001535172", + "name" : "Berkshire Money Management, Inc." + }, { + "cik" : "0001831984", + "name" : "Berkshire Bank" + }, { + "cik" : "0001831984", + "name" : "BERKSHIRE HATHAWAY" + }]'); + + $this->client = $this->setupMockedClient($this->response); + } + + /** @test */ + public function it_should_fail_without_a_name() + { + $cik_search = new \Leijman\FmpApiSdk\InstitutionalFunds\CikSearch($this->client); + + $this->expectException(InvalidData::class); + + $cik_search->get(); + } + + /** @test */ + public function it_can_query_the_cik_search_endpoint() + { + $cik_search = new \Leijman\FmpApiSdk\InstitutionalFunds\CikSearch($this->client); + + $response = $cik_search->setName('Berkshire')->get(); + + $this->assertInstanceOf(Collection::class, $response); + $this->assertCount(12, $response); + $this->assertEquals('BERKSHIRE HATHAWAY', $response->last()->name); + $this->assertEquals('0001831984', $response->last()->cik); + } + + /** @test */ + public function it_can_call_the_facade() + { + $this->setConfig(); + + CikSearch::shouldReceive('setName') + ->once() + ->andReturnSelf(); + + CikSearch::setName('Berkshire'); + } +} + + diff --git a/tests/InstitutionalFunds/CikTest.php b/tests/InstitutionalFunds/CikTest.php new file mode 100644 index 0000000..bb1c5b8 --- /dev/null +++ b/tests/InstitutionalFunds/CikTest.php @@ -0,0 +1,69 @@ +response = new Response(200, [], '[{ + "cik" : "0001067983", + "name" : "BERKSHIRE HATHAWAY" + }, { + "cik" : "0001067983", + "name" : "BERKSHIRE HATHAWAY" + }]'); + + $this->client = $this->setupMockedClient($this->response); + } + + /** @test */ + public function it_should_fail_without_a_cik() + { + $cik = new \Leijman\FmpApiSdk\InstitutionalFunds\Cik($this->client); + + $this->expectException(InvalidData::class); + + $cik->get(); + } + + /** @test */ + public function it_can_query_the_cik_endpoint() + { + $cik = new \Leijman\FmpApiSdk\InstitutionalFunds\Cik($this->client); + + $response = $cik->setCik('0001067983')->get(); + + $this->assertInstanceOf(Collection::class, $response); + $this->assertCount(2, $response); + $this->assertEquals('BERKSHIRE HATHAWAY', $response->last()->name); + $this->assertEquals('0001067983', $response->last()->cik); + } + + /** @test */ + public function it_can_call_the_facade() + { + $this->setConfig(); + + Cik::shouldReceive('setCik') + ->once() + ->andReturnSelf(); + + Cik::setCik('0001067983'); + } +} + + diff --git a/tests/InstitutionalFunds/CusipMapperTest.php b/tests/InstitutionalFunds/CusipMapperTest.php new file mode 100644 index 0000000..0a8dc91 --- /dev/null +++ b/tests/InstitutionalFunds/CusipMapperTest.php @@ -0,0 +1,67 @@ +response = new Response(200, [], '{ + "ticker" : "AAON", + "cusip" : "000360206", + "company" : "AAON INC" + }'); + + $this->client = $this->setupMockedClient($this->response); + } + + /** @test */ + public function it_should_fail_without_a_cusip() + { + $cusip = new \Leijman\FmpApiSdk\InstitutionalFunds\CusipMapper($this->client); + + $this->expectException(InvalidData::class); + + $cusip->get(); + } + + /** @test */ + public function it_can_query_the_cusip_mapper_endpoint() + { + $cusip = new \Leijman\FmpApiSdk\InstitutionalFunds\CusipMapper($this->client); + + $response = $cusip->setCusip('000360206')->get(); + + $this->assertInstanceOf(Collection::class, $response); + $this->assertCount(3, $response); + $this->assertEquals('AAON INC', $response['company']); + $this->assertEquals('000360206', $response['cusip']); + } + + /** @test */ + public function it_can_call_the_facade() + { + $this->setConfig(); + + CusipMapper::shouldReceive('setCusip') + ->once() + ->andReturnSelf(); + + CusipMapper::setCusip('000360206'); + } +} + + diff --git a/tests/InstitutionalFunds/EtfCountryWeightingsTest.php b/tests/InstitutionalFunds/EtfCountryWeightingsTest.php new file mode 100644 index 0000000..0413bf3 --- /dev/null +++ b/tests/InstitutionalFunds/EtfCountryWeightingsTest.php @@ -0,0 +1,64 @@ +response = new Response(200, [], '[{ + "country" : "United States", + "weightPercentage" : "100.00%" + }]'); + + $this->client = $this->setupMockedClient($this->response); + } + + /** @test */ + public function it_should_fail_without_a_symbol() + { + $etf_country_weightings = new \Leijman\FmpApiSdk\InstitutionalFunds\EtfCountryWeightings($this->client); + + $this->expectException(InvalidData::class); + + $etf_country_weightings->get(); + } + + /** @test */ + public function it_can_query_the_etf_country_weightings_endpoint() + { + $etf_country_weightings = new \Leijman\FmpApiSdk\InstitutionalFunds\EtfCountryWeightings($this->client); + + $response = $etf_country_weightings->setSymbol('SPY')->get(); + + $this->assertInstanceOf(Collection::class, $response); + $this->assertCount(1, $response); + $this->assertEquals('United States', $response->last()->country); + $this->assertEquals('100.00%', $response->last()->weightPercentage); + } + + /** @test */ + public function it_can_call_the_facade() + { + $this->setConfig(); + + EtfCountryWeightings::shouldReceive('setSymbol') + ->once() + ->andReturnSelf(); + + EtfCountryWeightings::setSymbol('SPY'); + } +} diff --git a/tests/InstitutionalFunds/EtfHolderTest.php b/tests/InstitutionalFunds/EtfHolderTest.php new file mode 100644 index 0000000..19bce7a --- /dev/null +++ b/tests/InstitutionalFunds/EtfHolderTest.php @@ -0,0 +1,77 @@ +response = new Response(200, [], '[{ + "asset" : "AAPL", + "sharesNumber" : 164453500, + "weightPercentage" : 5.98 + }, { + "asset" : "MSFT", + "sharesNumber" : 77798290, + "weightPercentage" : 5.35 + }, { + "asset" : "AMZN", + "sharesNumber" : 4388660, + "weightPercentage" : 4.03 + }, { + "asset" : "FB", + "sharesNumber" : 24737140, + "weightPercentage" : 1.89 + }]'); + + $this->client = $this->setupMockedClient($this->response); + } + + /** @test */ + public function it_should_fail_without_a_symbol() + { + $etf_holder = new \Leijman\FmpApiSdk\InstitutionalFunds\EtfHolder($this->client); + + $this->expectException(InvalidData::class); + + $etf_holder->get(); + } + + /** @test */ + public function it_can_query_the_etf_holder_endpoint() + { + $etf_holder = new \Leijman\FmpApiSdk\InstitutionalFunds\EtfHolder($this->client); + + $response = $etf_holder->setSymbol('SPY')->get(); + + $this->assertInstanceOf(Collection::class, $response); + $this->assertCount(4, $response); + $this->assertEquals('FB', $response->last()->asset); + $this->assertEquals(24737140, $response->last()->sharesNumber); + } + + /** @test */ + public function it_can_call_the_facade() + { + $this->setConfig(); + + EtfHolder::shouldReceive('setSymbol') + ->once() + ->andReturnSelf(); + + EtfHolder::setSymbol('SPY'); + } +} diff --git a/tests/InstitutionalFunds/EtfSectorWeightingsTest.php b/tests/InstitutionalFunds/EtfSectorWeightingsTest.php new file mode 100644 index 0000000..9ea007a --- /dev/null +++ b/tests/InstitutionalFunds/EtfSectorWeightingsTest.php @@ -0,0 +1,94 @@ +response = new Response(200, [], '[{ + "sector" : "Healthcare", + "weightPercentage" : "13.55%" + }, { + "sector" : "Telecommunications Services", + "weightPercentage" : "10.77%" + }, { + "sector" : "Energy", + "weightPercentage" : "2.28%" + }, { + "sector" : "Basic Materials", + "weightPercentage" : "2.27%" + }, { + "sector" : "Consumer Cyclicals", + "weightPercentage" : "12.50%" + }, { + "sector" : "Technology", + "weightPercentage" : "24.19%" + }, { + "sector" : "Financials", + "weightPercentage" : "13.50%" + }, { + "sector" : "Utilities", + "weightPercentage" : "2.76%" + }, { + "sector" : "Consumer Non-Cyclicals", + "weightPercentage" : "6.97%" + }, { + "sector" : "Industrials", + "weightPercentage" : "8.79%" + }, { + "sector" : "Real Estate", + "weightPercentage" : "2.42%" + }]'); + + $this->client = $this->setupMockedClient($this->response); + } + + /** @test */ + public function it_should_fail_without_a_symbol() + { + $etf_sector_weightings = new \Leijman\FmpApiSdk\InstitutionalFunds\EtfSectorWeightings($this->client); + + $this->expectException(InvalidData::class); + + $etf_sector_weightings->get(); + } + + /** @test */ + public function it_can_query_the_etf_sector_weightings_endpoint() + { + $etf_sector_weightings = new \Leijman\FmpApiSdk\InstitutionalFunds\EtfSectorWeightings($this->client); + + $response = $etf_sector_weightings->setSymbol('SPY')->get(); + + $this->assertInstanceOf(Collection::class, $response); + $this->assertCount(11, $response); + $this->assertEquals('Real Estate', $response->last()->sector); + $this->assertEquals('2.42%', $response->last()->weightPercentage); + } + + /** @test */ + public function it_can_call_the_facade() + { + $this->setConfig(); + + EtfSectorWeightings::shouldReceive('setSymbol') + ->once() + ->andReturnSelf(); + + EtfSectorWeightings::setSymbol('SPY'); + } +} diff --git a/tests/InstitutionalFunds/Form13FTest.php b/tests/InstitutionalFunds/Form13FTest.php new file mode 100644 index 0000000..829b2a6 --- /dev/null +++ b/tests/InstitutionalFunds/Form13FTest.php @@ -0,0 +1,133 @@ +response = new Response(200, [], '[{ + "date" : "2020-06-30", + "fillingDate" : "2020-08-14", + "acceptedDate" : "2020-08-14 16:01:47", + "cik" : "0001067983", + "cusip" : "037833100", + "tickercusip" : "AAPL", + "nameOfIssuer" : "APPLE INC", + "shares" : 245155566, + "titleOfClass" : "COM", + "value" : 89432750000, + "link" : "https://www.sec.gov/Archives/edgar/data/1067983/000095012320009058/0000950123-20-009058-index.htm", + "finalLink" : "https://www.sec.gov/Archives/edgar/data/1067983/000095012320009058/xslForm13F_X01/960.xml" + }, { + "date" : "2020-06-30", + "fillingDate" : "2020-08-14", + "acceptedDate" : "2020-08-14 16:01:47", + "cik" : "0001067983", + "cusip" : "067901108", + "tickercusip" : "ABX", + "nameOfIssuer" : "BARRICK GOLD CORPORATION", + "shares" : 20918701, + "titleOfClass" : "COM", + "value" : 563550000, + "link" : "https://www.sec.gov/Archives/edgar/data/1067983/000095012320009058/0000950123-20-009058-index.htm", + "finalLink" : "https://www.sec.gov/Archives/edgar/data/1067983/000095012320009058/xslForm13F_X01/960.xml" + }, { + "date" : "2020-06-30", + "fillingDate" : "2020-08-14", + "acceptedDate" : "2020-08-14 16:01:47", + "cik" : "0001067983", + "cusip" : "023135106", + "tickercusip" : "AMZN", + "nameOfIssuer" : "AMAZON COM INC", + "shares" : 533300, + "titleOfClass" : "COM", + "value" : 1471279000, + "link" : "https://www.sec.gov/Archives/edgar/data/1067983/000095012320009058/0000950123-20-009058-index.htm", + "finalLink" : "https://www.sec.gov/Archives/edgar/data/1067983/000095012320009058/xslForm13F_X01/960.xml" + }]'); + + $this->client = $this->setupMockedClient($this->response); + } + + /** @test */ + public function it_should_fail_without_a_cik() + { + $form13f = new \Leijman\FmpApiSdk\InstitutionalFunds\Form13F($this->client); + + $this->expectException(InvalidData::class); + + $form13f->get(); + } + + /** @test */ + public function it_can_query_the_form13f_endpoint() + { + $form13f = new \Leijman\FmpApiSdk\InstitutionalFunds\Form13F($this->client); + + $response = $form13f->setCik('0001067983')->get(); + + $this->assertInstanceOf(Collection::class, $response); + $this->assertCount(3, $response); + $this->assertEquals('0001067983', $response->last()->cik); + $this->assertEquals('AMAZON COM INC', $response->last()->nameOfIssuer); + } + + /** @test */ + public function it_can_query_the_date_form13f_endpoint() + { + $form13f = new \Leijman\FmpApiSdk\InstitutionalFunds\Form13F($this->client); + + $date = Carbon::now()->subMonth(5)->format('Y-m-d'); + $response = $form13f->setCik('0001067983') + ->setDate($date) + ->get(); + + $this->assertInstanceOf(Collection::class, $response); + $this->assertCount(3, $response); + $this->assertEquals('0001067983', $response->last()->cik); + $this->assertEquals('AMAZON COM INC', $response->last()->nameOfIssuer); + } + + /** @test */ + public function it_should_fail_when_the_date_has_an_incorrect_format() + { + $form13f = new \Leijman\FmpApiSdk\InstitutionalFunds\Form13F($this->client); + + $this->expectException(InvalidData::class); + $this->expectExceptionMessage('date format is incorrect'); + + $date = Carbon::now()->subMonth(2)->format('d-m-Y'); + $form13f->setCik('0001067983') + ->setDate($date) + ->get(); + } + + /** @test */ + public function it_can_call_the_facade() + { + $this->setConfig(); + + Form13F::shouldReceive('setCik') + ->once() + ->andReturnSelf(); + + Form13F::setCik('0001067983'); + } +} + + diff --git a/tests/InstitutionalFunds/InstitutionalHolderTest.php b/tests/InstitutionalFunds/InstitutionalHolderTest.php new file mode 100644 index 0000000..ef7d643 --- /dev/null +++ b/tests/InstitutionalFunds/InstitutionalHolderTest.php @@ -0,0 +1,81 @@ +response = new Response(200, [], '[{ + "holder" : "LAIRD NORTON TRUST COMPANY, LLC", + "shares" : 56147, + "dateReported" : "2021-02-26", + "change" : 56147 + }, { + "holder" : "Bridge Advisory, LLC", + "shares" : 38873, + "dateReported" : "2021-02-26", + "change" : 38873 + }, { + "holder" : "M Holdings Securities, Inc.", + "shares" : 219369, + "dateReported" : "2021-02-26", + "change" : 7105 + }, { + "holder" : "FOCUS Wealth Advisors, LLC", + "shares" : 15079, + "dateReported" : "2021-02-26", + "change" : 15079 + }]'); + + $this->client = $this->setupMockedClient($this->response); + } + + /** @test */ + public function it_should_fail_without_a_symbol() + { + $institutional_holder = new \Leijman\FmpApiSdk\InstitutionalFunds\InstitutionalHolder($this->client); + + $this->expectException(InvalidData::class); + + $institutional_holder->get(); + } + + /** @test */ + public function it_can_query_the_institutional_holder_endpoint() + { + $institutional_holder = new \Leijman\FmpApiSdk\InstitutionalFunds\InstitutionalHolder($this->client); + + $response = $institutional_holder->setSymbol('AAPL')->get(); + + $this->assertInstanceOf(Collection::class, $response); + $this->assertCount(4, $response); + $this->assertEquals('FOCUS Wealth Advisors, LLC', $response->last()->holder); + $this->assertEquals(15079, $response->last()->change); + } + + /** @test */ + public function it_can_call_the_facade() + { + $this->setConfig(); + + InstitutionalHolder::shouldReceive('setSymbol') + ->once() + ->andReturnSelf(); + + InstitutionalHolder::setSymbol('AAPL'); + } +} diff --git a/tests/InstitutionalFunds/MutualFundHolderTest.php b/tests/InstitutionalFunds/MutualFundHolderTest.php new file mode 100644 index 0000000..003457a --- /dev/null +++ b/tests/InstitutionalFunds/MutualFundHolderTest.php @@ -0,0 +1,85 @@ +response = new Response(200, [], '[{ + "holder" : "Verition Fund Management LLC", + "shares" : 3299900, + "dateReported" : "2021-02-16", + "change" : 0, + "weightPercent" : null + }, { + "holder" : "CAPITAL FUND MANAGEMENT S.A.", + "shares" : 1648900, + "dateReported" : "2021-02-12", + "change" : 1631701, + "weightPercent" : null + }, { + "holder" : "FJARDE AP-FONDEN /FOURTH SWEDISH NATIONAL PENSION FUND", + "shares" : 5109136, + "dateReported" : "2021-02-12", + "change" : 5109136, + "weightPercent" : null + }, { + "holder" : "Lumina Fund Management LLC", + "shares" : 64000, + "dateReported" : "2021-02-12", + "change" : 64000, + "weightPercent" : null + }]'); + + $this->client = $this->setupMockedClient($this->response); + } + + /** @test */ + public function it_should_fail_without_a_symbol() + { + $mutual_fund_holder = new \Leijman\FmpApiSdk\InstitutionalFunds\MutualFundHolder($this->client); + + $this->expectException(InvalidData::class); + + $mutual_fund_holder->get(); + } + + /** @test */ + public function it_can_query_the_mutual_fund_holder_endpoint() + { + $mutual_fund_holder = new \Leijman\FmpApiSdk\InstitutionalFunds\MutualFundHolder($this->client); + + $response = $mutual_fund_holder->setSymbol('AAPL')->get(); + + $this->assertInstanceOf(Collection::class, $response); + $this->assertCount(4, $response); + $this->assertEquals('Lumina Fund Management LLC', $response->last()->holder); + $this->assertEquals(64000, $response->last()->shares); + } + + /** @test */ + public function it_can_call_the_facade() + { + $this->setConfig(); + + MutualFundHolder::shouldReceive('setSymbol') + ->once() + ->andReturnSelf(); + + MutualFundHolder::setSymbol('AAPL'); + } +} diff --git a/tests/InstitutionalFunds/SecRssFeedTest.php b/tests/InstitutionalFunds/SecRssFeedTest.php new file mode 100644 index 0000000..003555f --- /dev/null +++ b/tests/InstitutionalFunds/SecRssFeedTest.php @@ -0,0 +1,108 @@ +response = new Response(200, [], '[{ + "title" : "10-K - HUTTIG BUILDING PRODUCTS INC (0001093082) (Filer)", + "date" : "2021-03-02 17:28:11", + "link" : "https://www.sec.gov/Archives/edgar/data/1093082/000156459021010338/0001564590-21-010338-index.htm", + "cik" : "0001093082", + "form_type" : "10-K", + "ticker" : "HBP" + }, { + "title" : "20-F - Orphazyme A/S (0001764791) (Filer)", + "date" : "2021-03-02 17:25:05", + "link" : "https://www.sec.gov/Archives/edgar/data/1764791/000156459021010332/0001564590-21-010332-index.htm", + "cik" : "0001764791", + "form_type" : "20-F", + "ticker" : "ORPH" + }, { + "title" : "10-K - MONROE CAPITAL Corp (0001512931) (Filer)", + "date" : "2021-03-02 17:23:21", + "link" : "https://www.sec.gov/Archives/edgar/data/1512931/000110465921030862/0001104659-21-030862-index.htm", + "cik" : "0001512931", + "form_type" : "10-K", + "ticker" : "MRCCL" + }, { + "title" : "10-K - CARRIAGE SERVICES INC (0001016281) (Filer)", + "date" : "2021-03-02 17:18:20", + "link" : "https://www.sec.gov/Archives/edgar/data/1016281/000101628121000071/0001016281-21-000071-index.htm", + "cik" : "0001016281", + "form_type" : "10-K", + "ticker" : "CSV" + }]'); + + $this->client = $this->setupMockedClient($this->response); + } + + /** @test */ + public function it_can_query_the_sec_rss_feed_endpoint() + { + $sec_rss_feed = new \Leijman\FmpApiSdk\InstitutionalFunds\SecRssFeed($this->client); + + $response = $sec_rss_feed->get(); + + $this->assertInstanceOf(Collection::class, $response); + $this->assertCount(4, $response); + $this->assertEquals('10-K - CARRIAGE SERVICES INC (0001016281) (Filer)', $response->last()->title); + $this->assertEquals('0001016281', $response->last()->cik); + } + + /** @test */ + public function it_can_set_a_limit() + { + $sec_rss_feed = new \Leijman\FmpApiSdk\InstitutionalFunds\SecRssFeed($this->client); + + $response = $sec_rss_feed->setLimit(4) + ->get(); + + $this->assertInstanceOf(Collection::class, $response); + $this->assertCount(4, $response); + $this->assertEquals('10-K - CARRIAGE SERVICES INC (0001016281) (Filer)', $response->last()->title); + $this->assertEquals('0001016281', $response->last()->cik); + } + + /** @test */ + public function it_should_fail_when_the_limit_is_not_an_integer() + { + $sec_rss_feed = new \Leijman\FmpApiSdk\InstitutionalFunds\SecRssFeed($this->client); + + $this->expectException(TypeError::class); + $this->expectExceptionMessage('must be of type int, string given'); + + $sec_rss_feed->setLimit('abc') + ->get(); + } + + /** @test */ + public function it_can_call_the_facade() + { + $this->setConfig(); + + SecRssFeed::shouldReceive('get') + ->once() + ->andReturn(collect(json_decode($this->response->getBody()->getContents()))); + + $response = SecRssFeed::get(); + + $this->assertInstanceOf(Collection::class, $response); + $this->assertCount(4, $response); + } +}