chore: code style
This commit is contained in:
@@ -2,33 +2,35 @@
|
||||
|
||||
namespace App\Interfaces\MarketData;
|
||||
|
||||
use App\Interfaces\MarketData\Types\Dividend;
|
||||
use App\Interfaces\MarketData\Types\Ohlc;
|
||||
use App\Interfaces\MarketData\Types\Quote;
|
||||
use App\Interfaces\MarketData\Types\Split;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use App\Interfaces\MarketData\Types\Quote;
|
||||
use App\Interfaces\MarketData\Types\Split;
|
||||
use App\Interfaces\MarketData\Types\Dividend;
|
||||
use App\Interfaces\MarketData\Types\Ohlc;
|
||||
use Tschucki\Alphavantage\Facades\Alphavantage;
|
||||
|
||||
class AlphaVantageMarketData implements MarketDataInterface
|
||||
{
|
||||
public function exists(String $symbol): Bool
|
||||
public function exists(string $symbol): bool
|
||||
{
|
||||
|
||||
return $this->quote($symbol)->isNotEmpty();
|
||||
}
|
||||
|
||||
public function quote(String $symbol): Quote
|
||||
public function quote(string $symbol): Quote
|
||||
{
|
||||
$quote = Alphavantage::core()->quoteEndpoint($symbol);
|
||||
$quote = Arr::get($quote, 'Global Quote', []);
|
||||
|
||||
if (empty($quote)) return new Quote();
|
||||
if (empty($quote)) {
|
||||
return new Quote;
|
||||
}
|
||||
|
||||
$fundamental = cache()->remember(
|
||||
'av-symbol-'.$symbol,
|
||||
1440,
|
||||
'av-symbol-'.$symbol,
|
||||
1440,
|
||||
function () use ($symbol) {
|
||||
return Alphavantage::fundamentals()->overview($symbol);
|
||||
}
|
||||
@@ -49,71 +51,71 @@ class AlphaVantageMarketData implements MarketDataInterface
|
||||
: null,
|
||||
'dividend_yield' => Arr::get($fundamental, 'DividendYield') != 'None'
|
||||
? Arr::get($fundamental, 'DividendYield')
|
||||
: null
|
||||
]);
|
||||
: null,
|
||||
]);
|
||||
}
|
||||
|
||||
public function dividends(String $symbol, $startDate, $endDate): Collection
|
||||
public function dividends(string $symbol, $startDate, $endDate): Collection
|
||||
{
|
||||
$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 new Dividend([
|
||||
'symbol' => $symbol,
|
||||
'date' => Carbon::parse(Arr::get($dividend, 'ex_dividend_date')),
|
||||
'dividend_amount' => Arr::get($dividend, 'amount'),
|
||||
]);
|
||||
});
|
||||
->filter(function ($dividend) use ($startDate, $endDate) {
|
||||
|
||||
return Carbon::parse(Arr::get($dividend, 'ex_dividend_date'))->between($startDate, $endDate);
|
||||
})
|
||||
->map(function ($dividend) use ($symbol) {
|
||||
|
||||
return new Dividend([
|
||||
'symbol' => $symbol,
|
||||
'date' => Carbon::parse(Arr::get($dividend, 'ex_dividend_date')),
|
||||
'dividend_amount' => Arr::get($dividend, 'amount'),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
public function splits(String $symbol, $startDate, $endDate): Collection
|
||||
{
|
||||
public function splits(string $symbol, $startDate, $endDate): Collection
|
||||
{
|
||||
$splits = Alphavantage::fundamentals()->splits($symbol);
|
||||
$splits = Arr::get($splits, 'data', []);
|
||||
|
||||
return collect($splits)
|
||||
->filter(function($split) use ($startDate, $endDate) {
|
||||
|
||||
return Carbon::parse(Arr::get($split, 'effective_date'))->between($startDate, $endDate);
|
||||
})
|
||||
->map(function($split) use ($symbol) {
|
||||
|
||||
return new Split([
|
||||
'symbol' => $symbol,
|
||||
'date' => Carbon::parse(Arr::get($split, 'effective_date')),
|
||||
'split_amount' => Arr::get($split, 'split_factor'),
|
||||
]);
|
||||
});
|
||||
->filter(function ($split) use ($startDate, $endDate) {
|
||||
|
||||
return Carbon::parse(Arr::get($split, 'effective_date'))->between($startDate, $endDate);
|
||||
})
|
||||
->map(function ($split) use ($symbol) {
|
||||
|
||||
return new Split([
|
||||
'symbol' => $symbol,
|
||||
'date' => Carbon::parse(Arr::get($split, 'effective_date')),
|
||||
'split_amount' => Arr::get($split, 'split_factor'),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
public function history(String $symbol, $startDate, $endDate): Collection
|
||||
public function history(string $symbol, $startDate, $endDate): Collection
|
||||
{
|
||||
|
||||
$history = Alphavantage::timeSeries()->daily($symbol, 'full');
|
||||
|
||||
$history = Arr::get($history, 'Time Series (Daily)', []);
|
||||
|
||||
|
||||
return collect($history)
|
||||
->filter(function ($history, $date) use ($startDate, $endDate) {
|
||||
->filter(function ($history, $date) use ($startDate, $endDate) {
|
||||
|
||||
return Carbon::parse($date)->between($startDate, $endDate);
|
||||
})
|
||||
->mapWithKeys(function($history, $date) use ($symbol) {
|
||||
return Carbon::parse($date)->between($startDate, $endDate);
|
||||
})
|
||||
->mapWithKeys(function ($history, $date) use ($symbol) {
|
||||
|
||||
$date = Carbon::parse($date)->format('Y-m-d');
|
||||
|
||||
return [ $date => new Ohlc([
|
||||
'symbol' => $symbol,
|
||||
'date' => $date,
|
||||
'close' => Arr::get($history, '4. close')
|
||||
]) ];
|
||||
});
|
||||
$date = Carbon::parse($date)->format('Y-m-d');
|
||||
|
||||
return [$date => new Ohlc([
|
||||
'symbol' => $symbol,
|
||||
'date' => $date,
|
||||
'close' => Arr::get($history, '4. close'),
|
||||
])];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,22 +2,22 @@
|
||||
|
||||
namespace App\Interfaces\MarketData;
|
||||
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use App\Interfaces\MarketData\Types\Quote;
|
||||
use App\Interfaces\MarketData\Types\Dividend;
|
||||
use App\Interfaces\MarketData\Types\Ohlc;
|
||||
use App\Interfaces\MarketData\Types\Quote;
|
||||
use App\Interfaces\MarketData\Types\Split;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class FakeMarketData implements MarketDataInterface
|
||||
{
|
||||
public function exists(String $symbol): Bool
|
||||
public function exists(string $symbol): bool
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function quote(String $symbol): Quote
|
||||
public function quote(string $symbol): Quote
|
||||
{
|
||||
|
||||
return new Quote([
|
||||
@@ -31,11 +31,11 @@ class FakeMarketData implements MarketDataInterface
|
||||
'market_cap' => 9800700600,
|
||||
'book_value' => 4.7,
|
||||
'last_dividend_date' => now()->subDays(45),
|
||||
'dividend_yield' => 0.033
|
||||
'dividend_yield' => 0.033,
|
||||
]);
|
||||
}
|
||||
|
||||
public function dividends(String $symbol, $startDate, $endDate): Collection
|
||||
public function dividends(string $symbol, $startDate, $endDate): Collection
|
||||
{
|
||||
|
||||
return collect([
|
||||
@@ -57,23 +57,23 @@ class FakeMarketData implements MarketDataInterface
|
||||
]);
|
||||
}
|
||||
|
||||
public function splits(String $symbol, $startDate, $endDate): Collection
|
||||
{
|
||||
public function splits(string $symbol, $startDate, $endDate): Collection
|
||||
{
|
||||
|
||||
return collect([
|
||||
new Split([
|
||||
'symbol' => $symbol,
|
||||
'date' => now()->subMonths(36),
|
||||
'split_amount' => 10,
|
||||
])
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public function history(String $symbol, $startDate, $endDate): Collection
|
||||
public function history(string $symbol, $startDate, $endDate): Collection
|
||||
{
|
||||
$numDays = Carbon::parse($startDate)->diffInDays($endDate, true);
|
||||
|
||||
for ($i = 0; $i < $numDays; $i++) {
|
||||
for ($i = 0; $i < $numDays; $i++) {
|
||||
|
||||
$date = now()->subDays($i)->format('Y-m-d');
|
||||
|
||||
@@ -83,7 +83,7 @@ class FakeMarketData implements MarketDataInterface
|
||||
'close' => rand(150, 400),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
return collect($series);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,21 +6,20 @@ use Illuminate\Support\Facades\Log;
|
||||
|
||||
class FallbackInterface
|
||||
{
|
||||
|
||||
protected string $latest_error;
|
||||
|
||||
public function __call($method, $arguments)
|
||||
{
|
||||
|
||||
$providers = explode(',', config('investbrain.provider', 'yahoo'));
|
||||
|
||||
|
||||
foreach ($providers as $provider) {
|
||||
|
||||
$provider = trim($provider);
|
||||
|
||||
try {
|
||||
|
||||
if (!in_array($provider, array_keys(config('investbrain.interfaces', [])))) {
|
||||
if (! in_array($provider, array_keys(config('investbrain.interfaces', [])))) {
|
||||
|
||||
throw new \Exception("Provider [{$provider}] is not a valid market data interface.");
|
||||
}
|
||||
@@ -30,7 +29,7 @@ class FallbackInterface
|
||||
return app()->make($provider_class_name)->$method(...$arguments);
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
|
||||
|
||||
$this->latest_error = $e->getMessage();
|
||||
|
||||
Log::warning("Failed calling method {$method} ({$provider}): {$this->latest_error}");
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
namespace App\Interfaces\MarketData;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use App\Interfaces\MarketData\Types\Dividend;
|
||||
use App\Interfaces\MarketData\Types\Ohlc;
|
||||
use App\Interfaces\MarketData\Types\Quote;
|
||||
use App\Interfaces\MarketData\Types\Split;
|
||||
use App\Interfaces\MarketData\Types\Dividend;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class FinnhubMarketData implements MarketDataInterface
|
||||
{
|
||||
@@ -16,13 +16,14 @@ class FinnhubMarketData implements MarketDataInterface
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
|
||||
$this->client = new \Finnhub\Api\DefaultApi(
|
||||
new \GuzzleHttp\Client(),
|
||||
new \GuzzleHttp\Client,
|
||||
\Finnhub\Configuration::getDefaultConfiguration()->setApiKey('token', config('finnhub.key'))
|
||||
);
|
||||
}
|
||||
public function exists(String $symbol): Bool
|
||||
|
||||
public function exists(string $symbol): bool
|
||||
{
|
||||
|
||||
return $this->quote($symbol)->isNotEmpty();
|
||||
@@ -32,20 +33,22 @@ class FinnhubMarketData implements MarketDataInterface
|
||||
{
|
||||
$quote = $this->client->quote($symbol);
|
||||
|
||||
if (empty($quote)) return new Quote();
|
||||
|
||||
if (empty($quote)) {
|
||||
return new Quote;
|
||||
}
|
||||
|
||||
$fundamental = cache()->remember(
|
||||
'fh-symbol-'.$symbol,
|
||||
1440,
|
||||
'fh-symbol-'.$symbol,
|
||||
1440,
|
||||
function () use ($symbol) {
|
||||
return $this->client->companyBasicFinancials($symbol, "all");
|
||||
return $this->client->companyBasicFinancials($symbol, 'all');
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
return new Quote([
|
||||
'name' => Arr::get($fundamental, 'metric.name'),
|
||||
'symbol' => $symbol,
|
||||
'market_value' => Arr::get($quote, 'c'),
|
||||
'market_value' => Arr::get($quote, 'c'),
|
||||
'fifty_two_week_high' => Arr::get($fundamental, 'metric.52WeekHigh'),
|
||||
'fifty_two_week_low' => Arr::get($fundamental, 'metric.52WeekLow'),
|
||||
'forward_pe' => Arr::get($fundamental, 'metric.forwardPE'), // confirm
|
||||
@@ -54,15 +57,15 @@ class FinnhubMarketData implements MarketDataInterface
|
||||
'book_value' => Arr::get($fundamental, 'metric.bookValuePerShare'), // confirm
|
||||
'last_dividend_date' => Arr::get($fundamental, 'metric.lastDivDate'), // confirm
|
||||
'dividend_yield' => Arr::get($fundamental, 'metric.dividendYield'), // confirm
|
||||
]);
|
||||
]);
|
||||
}
|
||||
|
||||
public function dividends($symbol, $startDate, $endDate): Collection
|
||||
{
|
||||
$dividends = $this->client->stockDividends($symbol, $startDate->format('Y-m-d'), $endDate->format('Y-m-d'));
|
||||
|
||||
return collect($dividends)->map(function($dividend) use ($symbol) {
|
||||
|
||||
|
||||
return collect($dividends)->map(function ($dividend) use ($symbol) {
|
||||
|
||||
return new Dividend([
|
||||
'symbol' => $symbol,
|
||||
'date' => Carbon::parse(Arr::get($dividend, 'date')),
|
||||
@@ -72,12 +75,12 @@ class FinnhubMarketData implements MarketDataInterface
|
||||
}
|
||||
|
||||
public function splits($symbol, $startDate, $endDate): Collection
|
||||
{
|
||||
{
|
||||
|
||||
$splits = $this->client->stockSplits($symbol, $startDate->format('Y-m-d'), $endDate->format('Y-m-d'));
|
||||
|
||||
return collect($splits)->map(function($split) use ($symbol) {
|
||||
|
||||
return collect($splits)->map(function ($split) use ($symbol) {
|
||||
|
||||
return new Split([
|
||||
'symbol' => $symbol,
|
||||
'date' => Carbon::parse(Arr::get($split, 'date')),
|
||||
@@ -89,18 +92,19 @@ class FinnhubMarketData implements MarketDataInterface
|
||||
public function history($symbol, $startDate, $endDate): Collection
|
||||
{
|
||||
|
||||
$history = $this->client->stockCandles($symbol, "D", $startDate->timestamp, $endDate->timestamp);
|
||||
$history = $this->client->stockCandles($symbol, 'D', $startDate->timestamp, $endDate->timestamp);
|
||||
|
||||
$timestamps = Arr::get($history, 't', []);
|
||||
$closes = Arr::get($history, 'c', []);
|
||||
|
||||
return collect($timestamps)->mapWithKeys(function ($timestamp, $index) use ($symbol, $closes) {
|
||||
$date = Carbon::createFromTimestamp($timestamp)->format('Y-m-d');
|
||||
return [ $date => new Ohlc([
|
||||
|
||||
return [$date => new Ohlc([
|
||||
'symbol' => $symbol,
|
||||
'date' => $date,
|
||||
'close' => $closes[$index],
|
||||
]) ];
|
||||
])];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,59 +2,33 @@
|
||||
|
||||
namespace App\Interfaces\MarketData;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use App\Interfaces\MarketData\Types\Quote;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
interface MarketDataInterface
|
||||
{
|
||||
/**
|
||||
* Does this symbol actually exist?
|
||||
*
|
||||
* @param String $symbol
|
||||
*
|
||||
* @return Bool
|
||||
*/
|
||||
public function exists(String $symbol): Bool;
|
||||
public function exists(string $symbol): bool;
|
||||
|
||||
/**
|
||||
* Get quote data
|
||||
*
|
||||
* @param String $symbol
|
||||
*
|
||||
* @return Quote
|
||||
*/
|
||||
public function quote(String $symbol): Quote;
|
||||
public function quote(string $symbol): Quote;
|
||||
|
||||
/**
|
||||
* Get dividend data
|
||||
*
|
||||
* @param String $symbol
|
||||
* @param \DateTimeInterface $startDate
|
||||
* @param \DateTimeInterface $endDate
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function dividends(String $symbol, \DateTimeInterface $startDate, \DateTimeInterface $endDate): Collection;
|
||||
public function dividends(string $symbol, \DateTimeInterface $startDate, \DateTimeInterface $endDate): Collection;
|
||||
|
||||
/**
|
||||
* Get split data
|
||||
*
|
||||
* @param String $symbol
|
||||
* @param \DateTimeInterface $startDate
|
||||
* @param \DateTimeInterface $endDate
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function splits(String $symbol, \DateTimeInterface $startDate, \DateTimeInterface $endDate): Collection;
|
||||
public function splits(string $symbol, \DateTimeInterface $startDate, \DateTimeInterface $endDate): Collection;
|
||||
|
||||
/**
|
||||
* Get historical close data
|
||||
*
|
||||
* @param String $symbol
|
||||
* @param \DateTimeInterface $startDate
|
||||
* @param \DateTimeInterface $endDate
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function history(String $symbol, \DateTimeInterface $startDate, \DateTimeInterface $endDate): Collection;
|
||||
public function history(string $symbol, \DateTimeInterface $startDate, \DateTimeInterface $endDate): Collection;
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@ namespace App\Interfaces\MarketData\Types;
|
||||
|
||||
use DateTime;
|
||||
use Illuminate\Support\Carbon;
|
||||
use App\Interfaces\MarketData\Types\MarketDataType;
|
||||
|
||||
class Dividend extends MarketDataType
|
||||
{
|
||||
public function setSymbol(string $symbol): self
|
||||
{
|
||||
$this->items['symbol'] = $symbol;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ class Dividend extends MarketDataType
|
||||
public function setDividendAmount($dividendAmount): self
|
||||
{
|
||||
$this->items['dividend_amount'] = (float) $dividendAmount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -30,9 +31,10 @@ class Dividend extends MarketDataType
|
||||
return $this->items['dividend_amount'] ?? 0.0;
|
||||
}
|
||||
|
||||
public function setDate(String|DateTime $date): self
|
||||
public function setDate(string|DateTime $date): self
|
||||
{
|
||||
$this->items['date'] = Carbon::parse($date)->format('Y-m-d H:i:s');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -40,4 +42,4 @@ class Dividend extends MarketDataType
|
||||
{
|
||||
return $this->items['date'] ?? null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,18 +2,15 @@
|
||||
|
||||
namespace App\Interfaces\MarketData\Types;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class MarketDataType extends Collection
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct($items = [])
|
||||
{
|
||||
|
||||
foreach($this->getArrayableItems($items) as $key => $value) {
|
||||
foreach ($this->getArrayableItems($items) as $key => $value) {
|
||||
|
||||
$this->{$key} = $value;
|
||||
}
|
||||
@@ -33,4 +30,4 @@ class MarketDataType extends Collection
|
||||
{
|
||||
return $this->items[$key] ?? null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@ namespace App\Interfaces\MarketData\Types;
|
||||
|
||||
use DateTime;
|
||||
use Illuminate\Support\Carbon;
|
||||
use App\Interfaces\MarketData\Types\MarketDataType;
|
||||
|
||||
class Ohlc extends MarketDataType
|
||||
{
|
||||
public function setSymbol(string $symbol): self
|
||||
{
|
||||
$this->items['symbol'] = $symbol;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ class Ohlc extends MarketDataType
|
||||
public function setOpen($open): self
|
||||
{
|
||||
$this->items['open'] = (float) $open;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -33,6 +34,7 @@ class Ohlc extends MarketDataType
|
||||
public function setHigh($high): self
|
||||
{
|
||||
$this->items['high'] = (float) $high;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -44,6 +46,7 @@ class Ohlc extends MarketDataType
|
||||
public function setLow($low): self
|
||||
{
|
||||
$this->items['low'] = (float) $low;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -55,6 +58,7 @@ class Ohlc extends MarketDataType
|
||||
public function setClose($close): self
|
||||
{
|
||||
$this->items['close'] = (float) $close;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -63,9 +67,10 @@ class Ohlc extends MarketDataType
|
||||
return $this->items['close'] ?? 0.0;
|
||||
}
|
||||
|
||||
public function setDate(String|DateTime $date): self
|
||||
public function setDate(string|DateTime $date): self
|
||||
{
|
||||
$this->items['date'] = Carbon::parse($date)->format('Y-m-d H:i:s');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -73,4 +78,4 @@ class Ohlc extends MarketDataType
|
||||
{
|
||||
return $this->items['date'] ?? null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@ namespace App\Interfaces\MarketData\Types;
|
||||
|
||||
use DateTime;
|
||||
use Illuminate\Support\Carbon;
|
||||
use App\Interfaces\MarketData\Types\MarketDataType;
|
||||
|
||||
class Quote extends MarketDataType
|
||||
{
|
||||
{
|
||||
public function setName($name): self
|
||||
{
|
||||
$this->items['name'] = (string) $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ class Quote extends MarketDataType
|
||||
public function setSymbol($symbol): self
|
||||
{
|
||||
$this->items['symbol'] = (string) $symbol;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -30,9 +31,10 @@ class Quote extends MarketDataType
|
||||
return $this->items['symbol'] ?? '';
|
||||
}
|
||||
|
||||
public function setMarketValue($marketValue): self
|
||||
public function setMarketValue($marketValue): self
|
||||
{
|
||||
$this->items['market_value'] = (float) $marketValue;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -41,9 +43,10 @@ class Quote extends MarketDataType
|
||||
return $this->items['market_value'] ?? 0.0;
|
||||
}
|
||||
|
||||
public function setFiftyTwoWeekHigh($high): self
|
||||
public function setFiftyTwoWeekHigh($high): self
|
||||
{
|
||||
$this->items['fifty_two_week_high'] = (float) $high;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -52,9 +55,10 @@ class Quote extends MarketDataType
|
||||
return $this->items['fifty_two_week_high'] ?? 0.0;
|
||||
}
|
||||
|
||||
public function setFiftyTwoWeekLow($low): self
|
||||
public function setFiftyTwoWeekLow($low): self
|
||||
{
|
||||
$this->items['fifty_two_week_low'] = (float) $low;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -63,9 +67,10 @@ class Quote extends MarketDataType
|
||||
return $this->items['fifty_two_week_low'] ?? 0.0;
|
||||
}
|
||||
|
||||
public function setForwardPE($pe): self
|
||||
public function setForwardPE($pe): self
|
||||
{
|
||||
$this->items['forward_pe'] = (float) $pe;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -74,9 +79,10 @@ class Quote extends MarketDataType
|
||||
return $this->items['forward_pe'] ?? 0.0;
|
||||
}
|
||||
|
||||
public function setTrailingPE($pe): self
|
||||
public function setTrailingPE($pe): self
|
||||
{
|
||||
$this->items['trailing_pe'] = (float) $pe;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -88,6 +94,7 @@ class Quote extends MarketDataType
|
||||
public function setMarketCap($cap): self
|
||||
{
|
||||
$this->items['market_cap'] = (int) $cap;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -96,9 +103,10 @@ class Quote extends MarketDataType
|
||||
return $this->items['market_cap'] ?? 0;
|
||||
}
|
||||
|
||||
public function setBookValue($value): self
|
||||
public function setBookValue($value): self
|
||||
{
|
||||
$this->items['book_value'] = (float) $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -110,6 +118,7 @@ class Quote extends MarketDataType
|
||||
public function setLastDividendDate(mixed $date): self
|
||||
{
|
||||
$this->items['last_dividend_date'] = is_null($date) ? null : Carbon::parse($date)->format('Y-m-d H:i:s');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -118,9 +127,10 @@ class Quote extends MarketDataType
|
||||
return $this->items['last_dividend_date'] ?? null;
|
||||
}
|
||||
|
||||
public function setDividendYield($yield): self
|
||||
public function setDividendYield($yield): self
|
||||
{
|
||||
$this->items['dividend_yield'] = (float) $yield;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -128,4 +138,4 @@ class Quote extends MarketDataType
|
||||
{
|
||||
return $this->items['dividend_yield'] ?? 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@ namespace App\Interfaces\MarketData\Types;
|
||||
|
||||
use DateTime;
|
||||
use Illuminate\Support\Carbon;
|
||||
use App\Interfaces\MarketData\Types\MarketDataType;
|
||||
|
||||
class Split extends MarketDataType
|
||||
{
|
||||
public function setSymbol(string $symbol): self
|
||||
{
|
||||
$this->items['symbol'] = $symbol;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ class Split extends MarketDataType
|
||||
public function setSplitAmount($splitAmount): self
|
||||
{
|
||||
$this->items['split_amount'] = (float) $splitAmount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -30,9 +31,10 @@ class Split extends MarketDataType
|
||||
return $this->items['split_amount'] ?? 0.0;
|
||||
}
|
||||
|
||||
public function setDate(String|DateTime $date): self
|
||||
public function setDate(string|DateTime $date): self
|
||||
{
|
||||
$this->items['date'] = Carbon::parse($date)->format('Y-m-d H:i:s');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -40,4 +42,4 @@ class Split extends MarketDataType
|
||||
{
|
||||
return $this->items['date'] ?? null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,36 +2,39 @@
|
||||
|
||||
namespace App\Interfaces\MarketData;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Scheb\YahooFinanceApi\ApiClient;
|
||||
use App\Interfaces\MarketData\Types\Dividend;
|
||||
use App\Interfaces\MarketData\Types\Ohlc;
|
||||
use App\Interfaces\MarketData\Types\Quote;
|
||||
use App\Interfaces\MarketData\Types\Split;
|
||||
use App\Interfaces\MarketData\Types\Dividend;
|
||||
use Illuminate\Support\Collection;
|
||||
use Scheb\YahooFinanceApi\ApiClient;
|
||||
use Scheb\YahooFinanceApi\ApiClientFactory as YahooFinance;
|
||||
|
||||
class YahooMarketData implements MarketDataInterface
|
||||
{
|
||||
public ApiClient $client;
|
||||
|
||||
public function __construct() {
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
// create yahoo finance client factory
|
||||
$this->client = YahooFinance::createApiClient();
|
||||
}
|
||||
|
||||
public function exists(String $symbol): Bool
|
||||
public function exists(string $symbol): bool
|
||||
{
|
||||
|
||||
return $this->quote($symbol)->isNotEmpty();
|
||||
}
|
||||
|
||||
public function quote(String $symbol): Quote
|
||||
public function quote(string $symbol): Quote
|
||||
{
|
||||
|
||||
$quote = $this->client->getQuote($symbol);
|
||||
|
||||
if (empty($quote)) return collect();
|
||||
if (empty($quote)) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
return new Quote([
|
||||
'name' => $quote->getLongName() ?? $quote->getShortName(),
|
||||
@@ -44,52 +47,52 @@ class YahooMarketData implements MarketDataInterface
|
||||
'market_cap' => $quote->getMarketCap(),
|
||||
'book_value' => $quote->getBookValue(),
|
||||
'last_dividend_date' => $quote->getDividendDate(),
|
||||
'dividend_yield' => $quote->getTrailingAnnualDividendYield() * 100
|
||||
'dividend_yield' => $quote->getTrailingAnnualDividendYield() * 100,
|
||||
]);
|
||||
}
|
||||
|
||||
public function dividends(String $symbol, $startDate, $endDate): Collection
|
||||
public function dividends(string $symbol, $startDate, $endDate): Collection
|
||||
{
|
||||
|
||||
return collect($this->client->getHistoricalDividendData($symbol, $startDate, $endDate))
|
||||
->map(function($dividend) use ($symbol) {
|
||||
|
||||
return new Dividend([
|
||||
'symbol' => $symbol,
|
||||
'date' => $dividend->getDate(),
|
||||
'dividend_amount' => $dividend->getDividends(),
|
||||
]);
|
||||
});
|
||||
->map(function ($dividend) use ($symbol) {
|
||||
|
||||
return new Dividend([
|
||||
'symbol' => $symbol,
|
||||
'date' => $dividend->getDate(),
|
||||
'dividend_amount' => $dividend->getDividends(),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
public function splits(String $symbol, $startDate, $endDate): Collection
|
||||
{
|
||||
public function splits(string $symbol, $startDate, $endDate): Collection
|
||||
{
|
||||
|
||||
return collect($this->client->getHistoricalSplitData($symbol, $startDate, $endDate))
|
||||
->map(function($split) use ($symbol) {
|
||||
$split_amount = explode(':', $split->getStockSplits());
|
||||
->map(function ($split) use ($symbol) {
|
||||
$split_amount = explode(':', $split->getStockSplits());
|
||||
|
||||
return new Split([
|
||||
'symbol' => $symbol,
|
||||
'date' => $split->getDate(),
|
||||
'split_amount' => $split_amount[0] / $split_amount[1],
|
||||
]);
|
||||
});
|
||||
return new Split([
|
||||
'symbol' => $symbol,
|
||||
'date' => $split->getDate(),
|
||||
'split_amount' => $split_amount[0] / $split_amount[1],
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
public function history(String $symbol, $startDate, $endDate): Collection
|
||||
public function history(string $symbol, $startDate, $endDate): Collection
|
||||
{
|
||||
|
||||
return collect($this->client->getHistoricalQuoteData($symbol, ApiClient::INTERVAL_1_DAY, $startDate, $endDate))
|
||||
->mapWithKeys(function($history) use ($symbol) {
|
||||
->mapWithKeys(function ($history) use ($symbol) {
|
||||
|
||||
$date = $history->getDate()->format('Y-m-d');
|
||||
|
||||
return [ $date => new Ohlc([
|
||||
'symbol' => $symbol,
|
||||
'date' => $date,
|
||||
'close' => $history->getClose(),
|
||||
]) ];
|
||||
return [$date => new Ohlc([
|
||||
'symbol' => $symbol,
|
||||
'date' => $date,
|
||||
'close' => $history->getClose(),
|
||||
])];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user