Skip to content

Commit bb0826c

Browse files
committed
Add Options->Strikes method
1 parent 67e6fcb commit bb0826c

4 files changed

Lines changed: 117 additions & 17 deletions

File tree

src/Endpoints/Options.php

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,30 @@ public function expirations(string $symbol, int $strike = null, Carbon $date = n
6565
public function lookup(string $input): Lookup
6666
{
6767
// Stub
68-
return new Lookup($this->client->execute(self::BASE_URL . "options/expirations/" . urlencode($input)));
68+
return new Lookup($this->client->execute(self::BASE_URL . "options/lookup/" . urlencode($input)));
6969
}
7070

71-
public function strikes(): Strikes
71+
/**
72+
* Get a list of current or historical options strikes for an underlying symbol. If no optional parameters are used,
73+
* the endpoint returns the strikes for every expiration in the chain.
74+
*
75+
* @param string $symbol The underlying ticker symbol for the options chain you wish to lookup.
76+
*
77+
* @param Carbon|null $expiration Limit the lookup of strikes to options that expire on a specific expiration date.
78+
*
79+
* @param Carbon|null $date Use to lookup a historical list of strikes from a specific previous trading day. If date
80+
* is omitted the expiration dates will be from the current trading day during market hours or from the last trading
81+
* day when the market is closed.
82+
*
83+
* @throws ApiException|GuzzleException
84+
*/
85+
public function strikes(string $symbol, Carbon $expiration = null, Carbon $date = null): Strikes
7286
{
7387
// Stub
74-
return new Strikes();
88+
return new Strikes($this->client->execute(self::BASE_URL . "options/strikes/$symbol", [
89+
'expiration' => $expiration,
90+
'date' => $date,
91+
]));
7592
}
7693

7794
/**

src/Endpoints/Responses/Options/Expirations.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class Expirations
1515
*
1616
* @var Carbon[] $expirations
1717
**/
18-
public array $expirations;
18+
public array $expirations = [];
1919

2020
// The date and time of this list of options strikes was updated in Unix time. For historical strikes, this number
2121
// should match the date parameter.
@@ -34,9 +34,9 @@ public function __construct(object $response)
3434

3535
switch ($this->status) {
3636
case 'ok':
37-
for ($i = 0; $i < count($response->expirations); $i++) {
38-
$this->expirations[] = Carbon::parse($response->expirations[$i]);
39-
}
37+
$this->expirations = array_map(function ($expiration) {
38+
return Carbon::parse($expiration);
39+
}, $response->expirations);
4040
$this->updated = Carbon::parse($response->updated);
4141
break;
4242

@@ -50,7 +50,5 @@ public function __construct(object $response)
5050
}
5151
break;
5252
}
53-
54-
$this->updated = Carbon::parse($response->updated);
5553
}
5654
}

src/Endpoints/Responses/Options/Strikes.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,49 @@
22

33
namespace MarketDataApp\Endpoints\Responses\Options;
44

5+
use Carbon\Carbon;
6+
57
class Strikes
68
{
9+
// Will always be ok when there is data for the candles requested.
10+
public string $status;
11+
12+
/**
13+
* The expiration dates requested for the underlying with the option strikes for each expiration.
14+
*
15+
* @var array[int[]] $dates
16+
*/
17+
public array $dates = [];
18+
19+
/**
20+
* The date and time of this list of options strikes was updated in Unix time. For historical strikes, this number
21+
* should match the date parameter.
22+
*
23+
* @var Carbon $updated
24+
*/
25+
public Carbon $updated;
26+
27+
// Time of the next quote if there is no data in the requested period, but there is data in a subsequent period.
28+
public Carbon $next_time;
29+
30+
// Time of the previous quote if there is no data in the requested period, but there is data in a previous period.
31+
public Carbon $prev_time;
32+
33+
public function __construct(object $response)
34+
{
35+
// Convert the response to this object.
36+
$this->status = $response->s;
37+
38+
switch ($this->status) {
39+
case 'ok':
40+
$this->dates = (array) $response->dates;
41+
$this->updated = Carbon::parse($response->updated);
42+
break;
43+
44+
case 'no_data' && isset($response->nextTime):
45+
$this->next_time = Carbon::parse($response->nextTime);
46+
$this->prev_time = Carbon::parse($response->prevTime);
47+
break;
48+
}
49+
}
750
}

tests/OptionsTest.php

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ protected function setUp(): void
3838
public function testExpirations_success()
3939
{
4040
$mocked_response = [
41-
's' => 'ok',
42-
'expirations' => ['2022-09-23', '2022-09-30'],
43-
'updated' => 1663704000
41+
's' => 'ok',
42+
'expirations' => ['2022-09-23', '2022-09-30'],
43+
'updated' => 1663704000
4444
];
4545
$this->setMockResponses([new Response(200, [], json_encode($mocked_response))]);
4646

@@ -60,7 +60,7 @@ public function testExpirations_success()
6060
public function testExpirations_noData_success()
6161
{
6262
$mocked_response = [
63-
's' => 'no_data',
63+
's' => 'no_data',
6464
'nextTime' => 1663704000,
6565
'prevTime' => 1663705000
6666
];
@@ -70,15 +70,15 @@ public function testExpirations_noData_success()
7070

7171
// Verify that the response is an object of the correct type.
7272
$this->assertInstanceOf(Expirations::class, $response);
73-
$this->assertFalse(isset($response->expirations));
73+
$this->assertEmpty($response->expirations);
7474
$this->assertEquals(Carbon::parse($mocked_response['nextTime']), $response->next_time);
7575
$this->assertEquals(Carbon::parse($mocked_response['prevTime']), $response->prev_time);
7676
}
7777

7878
public function testLookup_success()
7979
{
8080
$mocked_response = [
81-
's' => 'no_data',
81+
's' => 'no_data',
8282
'optionSymbol' => 'AAPL230728C00200000',
8383
];
8484
$this->setMockResponses([new Response(200, [], json_encode($mocked_response))]);
@@ -92,8 +92,50 @@ public function testLookup_success()
9292

9393
public function testStrikes_success()
9494
{
95-
// Stub
96-
$this->assertInstanceOf(Strikes::class, $this->client->options->strikes());
95+
$mocked_response = [
96+
's' => 'ok',
97+
'updated' => 1663704000,
98+
'dates' => [
99+
'2023-01-20' => [
100+
30.0,
101+
35.0
102+
]
103+
]
104+
];
105+
$this->setMockResponses([new Response(200, [], json_encode($mocked_response))]);
106+
107+
$response = $this->client->options->strikes(
108+
symbol: 'AAPL',
109+
expiration: Carbon::parse('2023-01-20'),
110+
date: Carbon::parse('2023-01-03'),
111+
);
112+
113+
// Verify that the response is an object of the correct type.
114+
$this->assertInstanceOf(Strikes::class, $response);
115+
$this->assertEquals(Carbon::parse($mocked_response['updated']), $response->updated);
116+
$this->assertEquals((array)$mocked_response['dates'], $response->dates);
117+
}
118+
119+
public function testStrikes_noData_success()
120+
{
121+
$mocked_response = [
122+
's' => 'no_data',
123+
'nextTime' => 1663704000,
124+
'prevTime' => 1663705000
125+
];
126+
$this->setMockResponses([new Response(200, [], json_encode($mocked_response))]);
127+
128+
$response = $this->client->options->strikes(
129+
symbol: 'AAPL',
130+
expiration: Carbon::parse('2023-01-20'),
131+
date: Carbon::parse('2023-01-03'),
132+
);
133+
134+
// Verify that the response is an object of the correct type.
135+
$this->assertInstanceOf(Strikes::class, $response);
136+
$this->assertEmpty($response->dates);
137+
$this->assertEquals(Carbon::parse($mocked_response['nextTime']), $response->next_time);
138+
$this->assertEquals(Carbon::parse($mocked_response['prevTime']), $response->prev_time);
97139
}
98140

99141
public function testQuotes_success()

0 commit comments

Comments
 (0)