Skip to content

Commit 35a51d5

Browse files
authored
Merge pull request #2 from MarketDataApp/add-quotes
Add quotes
2 parents 5804414 + 7b4d5b3 commit 35a51d5

20 files changed

Lines changed: 1133 additions & 66 deletions

CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
# Changelog
22

3-
All notable changes to `marketdataapp-sdk-php` will be documented in this file.
3+
## v0.2.0-alpha
44

5+
- Completed Indices endpoints.
6+
- Added Stocks endpoints: quote, quotes, bulkQuotes, candles, bulkCandles.
7+
- Added custom ApiException class to handle status = 'error' messages.
8+
- Moved Responses to new directory.
9+
10+
## v0.1.0-alpha
11+
12+
- Initial release with single Indices > quote endpoint.

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,20 @@ composer require MarketDataApp/sdk-php
2121

2222
```php
2323
$client = new MarketDataApp\Client();
24+
25+
// Indices
2426
$quote = $client->indices->quote('DJI');
25-
$candles = $this->client->indices->candles(
27+
$candles = $client->indices->candles(
2628
symbol: "DJI",
2729
from: Carbon::parse('2022-09-01'),
2830
to: Carbon::parse('2022-09-05'),
2931
resolution: 'D'
3032
);
33+
34+
// Stocks
35+
$quote = $client->stocks->quote('AAPL');
36+
$quotes = $client->stocks->quotes(['AAPL', 'NFLX']);
37+
$bulk_quotes = $client->stocks->bulk_quotes(['AAPL', 'NFLX']);
3138
```
3239

3340
## Testing

src/Client.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace MarketDataApp;
44

55
use MarketDataApp\Endpoints\Indices;
6+
use MarketDataApp\Endpoints\Stocks;
67

78
class Client extends ClientBase
89
{
@@ -13,10 +14,16 @@ class Client extends ClientBase
1314
*/
1415
public Indices $indices;
1516

17+
/**
18+
* Stock endpoints include numerous fundamental, technical, and pricing data.
19+
*/
20+
public Stocks $stocks;
21+
1622
public function __construct($token)
1723
{
1824
parent::__construct($token);
1925

2026
$this->indices = new Indices($this);
27+
$this->stocks = new Stocks($this);
2128
}
2229
}

src/ClientBase.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use GuzzleHttp\Exception\GuzzleException;
77
use GuzzleHttp\Promise;
88
use GuzzleHttp\Promise\PromiseInterface;
9+
use MarketDataApp\Exceptions\ApiException;
910

1011
abstract class ClientBase
1112
{
@@ -53,6 +54,7 @@ protected function async($method, array $arguments = []): PromiseInterface
5354

5455
/**
5556
* @throws GuzzleException
57+
* @throws ApiException
5658
*/
5759
public function execute($method, array $arguments = []): object
5860
{
@@ -62,7 +64,13 @@ public function execute($method, array $arguments = []): object
6264
]);
6365
$json_response = (string)$response->getBody();
6466

65-
return json_decode($json_response);
67+
$response = json_decode($json_response);
68+
69+
if($response->s === 'error') {
70+
throw new ApiException(message: $response->errmsg, response: $response);
71+
}
72+
73+
return $response;
6674
}
6775

6876
protected function headers(): array

src/Endpoints/Indices.php

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
use Carbon\Carbon;
66
use GuzzleHttp\Exception\GuzzleException;
77
use MarketDataApp\Client;
8-
use MarketDataApp\Endpoints\Responses\IndicesCandles;
9-
use MarketDataApp\Endpoints\Responses\IndicesQuote;
8+
use MarketDataApp\Endpoints\Responses\Indices\Candles;
9+
use MarketDataApp\Endpoints\Responses\Indices\Quote;
10+
use MarketDataApp\Exceptions\ApiException;
1011

1112
class Indices
1213
{
@@ -20,41 +21,46 @@ public function __construct($client)
2021
}
2122

2223
/**
24+
* Get a real-time quote for an index.
25+
*
2326
* @param string $symbol The index symbol, without any leading or trailing index identifiers. For example, use DJI
2427
* do not use $DJI, ^DJI, .DJI, DJI.X, etc.
25-
* @throws GuzzleException
28+
* @throws GuzzleException|ApiException
2629
*/
27-
public function quote(string $symbol): IndicesQuote
30+
public function quote(string $symbol, bool $fifty_two_week = false): Quote
2831
{
29-
return new IndicesQuote($this->client->execute(self::BASE_URL . "quotes/{$symbol}"));
32+
return new Quote($this->client->execute(self::BASE_URL . "quotes/{$symbol}", ['52week' => $fifty_two_week]));
3033
}
3134

3235
/**
36+
* Get historical price candles for an index.
37+
*
3338
* @param string $symbol The index symbol, without any leading or trailing index identifiers. For example, use DJI
3439
* do not use $DJI, ^DJI, .DJI, DJI.X, etc.
40+
*
3541
* @param Carbon $from The leftmost candle on a chart (inclusive). If you use countback, to is not required.
36-
* Accepted timestamp inputs: ISO 8601, unix, spreadsheet.
37-
* @param Carbon|null $to The rightmost candle on a chart (inclusive). Accepted timestamp inputs: ISO 8601, unix,
38-
* spreadsheet.
42+
* @param Carbon|null $to The rightmost candle on a chart (inclusive).
3943
* @param string $resolution The duration of each candle.
4044
* Minutely Resolutions: (minutely, 1, 3, 5, 15, 30, 45, ...) Hourly Resolutions: (hourly, H, 1H, 2H, ...)
4145
* Daily Resolutions: (daily, D, 1D, 2D, ...)
4246
* Weekly Resolutions: (weekly, W, 1W, 2W, ...)
4347
* Monthly Resolutions: (monthly, M, 1M, 2M, ...)
4448
* Yearly Resolutions:(yearly, Y, 1Y, 2Y, ...)
49+
*
4550
* @param int|null $countback Will fetch a number of candles before (to the left of) to. If you use from, countback
4651
* is not required.
47-
* @return IndicesCandles
48-
* @throws GuzzleException
52+
*
53+
* @return Candles
54+
* @throws GuzzleException|ApiException
4955
*/
5056
public function candles(
5157
string $symbol,
5258
Carbon $from,
5359
Carbon $to = null,
5460
string $resolution = 'D',
5561
int $countback = null
56-
): IndicesCandles {
57-
return new IndicesCandles($this->client->execute(self::BASE_URL . "candles/{$resolution}/{$symbol}/",
62+
): Candles {
63+
return new Candles($this->client->execute(self::BASE_URL . "candles/{$resolution}/{$symbol}/",
5864
compact('from', 'to', 'countback')
5965
));
6066
}

src/Endpoints/Responses/IndicesCandle.php renamed to src/Endpoints/Responses/Indices/Candle.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<?php
22

3-
namespace MarketDataApp\Endpoints\Responses;
3+
namespace MarketDataApp\Endpoints\Responses\Indices;
44

55
use Carbon\Carbon;
66

7-
class IndicesCandle
7+
class Candle
88
{
99

1010
// Open price.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace MarketDataApp\Endpoints\Responses\Indices;
4+
5+
use Carbon\Carbon;
6+
7+
class Candles
8+
{
9+
10+
/**
11+
* - Will always be ok when there is data for the candles requested.
12+
* - Status will be no_data if no candles are found for the request.
13+
* - Status will be error if the request produces an error response.
14+
*/
15+
public string $status;
16+
17+
/** @var Candle[] $candles */
18+
public array $candles = [];
19+
20+
// Unix time of the next quote if there is no data in the requested period, but there is data in a subsequent
21+
// period.
22+
public int $next_time;
23+
24+
/**
25+
* @throws \Exception
26+
*/
27+
public function __construct(object $response)
28+
{
29+
// Convert the response to this object.
30+
$this->status = $response->s;
31+
32+
switch ($this->status) {
33+
case 'ok':
34+
for ($i = 0; $i < count($response->o); $i++) {
35+
$this->candles[] = new Candle(
36+
$response->o[$i],
37+
$response->h[$i],
38+
$response->l[$i],
39+
$response->c[$i],
40+
Carbon::parse($response->t[$i]),
41+
);
42+
}
43+
break;
44+
45+
case 'no_data' && isset($response->nextTime):
46+
$this->next_time = $response->nextTime;
47+
break;
48+
}
49+
}
50+
}
Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<?php
22

3-
namespace MarketDataApp\Endpoints\Responses;
3+
namespace MarketDataApp\Endpoints\Responses\Indices;
44

55
use Carbon\Carbon;
66

7-
class IndicesQuote
7+
class Quote
88
{
99

1010
// Will always be ok when there is data for the symbol requested.
@@ -34,14 +34,15 @@ class IndicesQuote
3434

3535
public function __construct(object $response)
3636
{
37-
// Convert the response to this object.
3837
$this->status = $response->s;
39-
$this->symbol = $response->symbol[0];
40-
$this->last = $response->last[0];
41-
$this->change = $response->change[0];
42-
$this->change_percent = $response->changepct[0];
43-
$this->fifty_two_week_high = $response->{'52weekHigh'}[0];
44-
$this->fifty_two_week_low = $response->{'52weekLow'}[0];
45-
$this->updated = Carbon::parse($response->updated);
38+
if ($this->status === "ok") {
39+
$this->symbol = $response->symbol[0];
40+
$this->last = $response->last[0];
41+
$this->change = $response->change[0];
42+
$this->change_percent = $response->changepct[0];
43+
$this->fifty_two_week_high = $response->{'52weekHigh'}[0];
44+
$this->fifty_two_week_low = $response->{'52weekLow'}[0];
45+
$this->updated = Carbon::parse($response->updated);
46+
}
4647
}
4748
}

src/Endpoints/Responses/IndicesCandles.php

Lines changed: 0 additions & 30 deletions
This file was deleted.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace MarketDataApp\Endpoints\Responses\Stocks;
4+
5+
use Carbon\Carbon;
6+
7+
class BulkCandles
8+
{
9+
10+
// Will always be ok when there is data for the candles requested.
11+
public string $status;
12+
13+
// The ticker symbols of the stock.
14+
public array $symbols = [];
15+
16+
/** @var Candle[] $candles */
17+
public array $candles = [];
18+
19+
public function __construct(object $response)
20+
{
21+
// Convert the response to this object.
22+
$this->status = $response->s;
23+
24+
if ($this->status === 'ok') {
25+
$this->symbols = array_map('trim', explode(',', $response->symbol));
26+
for ($i = 0; $i < count($response->o); $i++) {
27+
$this->candles[] = new Candle(
28+
$response->o[$i],
29+
$response->h[$i],
30+
$response->l[$i],
31+
$response->c[$i],
32+
$response->v[$i],
33+
Carbon::parse($response->t[$i]),
34+
);
35+
}
36+
}
37+
}
38+
}

0 commit comments

Comments
 (0)