Created
October 22, 2020 00:09
-
-
Save amendoncabh/5f00fbe2c551d59aaf7a0d064d3ef25b to your computer and use it in GitHub Desktop.
PHP classes to get stock data from various Yahoo finance APIs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Get historic stock symbol information from Yahoo | |
* | |
* Based on https://code.google.com/p/yahoo-finance-managed/wiki/csvHistQuotesDownload | |
*/ | |
class YahooHistoricStockApi | |
{ | |
const QUOTE_INTERVAL_DAY = 'd'; | |
const QUOTE_INTERVAL_WEEK = 'w'; | |
const QUOTE_INTERVAL_MONTH = 'm'; | |
/** | |
* Period of each data point | |
* @var string | |
*/ | |
protected $quotesInterval = null; | |
/** | |
* Columns names to parse into PHP variables | |
* If this is null, all available columns are parsed. | |
* @see limitColumns method for details | |
* @var array | |
*/ | |
protected $limitColumns = null; | |
/** | |
* Get data about a stock symbol within a period. | |
* $to and $from must be a format accepted by strtotime | |
* @param string $symbol | |
* @param string $from | |
* @param string $to | |
*/ | |
public function fetchHistoricData($symbol, $from = null, $to = null) | |
{ | |
$url = $this->makeUrl($symbol, $from, $to); | |
curl_setopt_array($ch = curl_init(), array( | |
CURLOPT_URL => $url, | |
CURLOPT_RETURNTRANSFER => true | |
) | |
); | |
$response = curl_exec($ch); | |
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE); | |
curl_close($ch); | |
if ($status != 200) { | |
throw new ErrorException("Request to $url returned status $status"); | |
} | |
return $this->parseStockCsv($response); | |
} | |
/** | |
* Convert CSV data into a PHP data | |
* | |
* CSV schema is expected to be: | |
* Date,Open,High,Low,Close,Volume,Adj Close | |
* | |
* @param string $csv - CSV from ichart.finance.yahoo.com | |
* @return array | |
*/ | |
protected function parseStockCsv($csv) | |
{ | |
$data = array(); | |
$rows = explode("\n", trim($csv)); | |
$headers = explode(',', array_shift($rows)); | |
if (count($rows) < 1 || !count($headers)) { | |
throw new UnexpectedValueException('Input data not in a readable format'); | |
} | |
if (is_array($this->limitColumns)) { | |
foreach ($headers as &$columnName) { | |
if (!in_array($columnName, $this->limitColumns)) { | |
$columnName = false; | |
} | |
} | |
} | |
foreach ($rows as $row) { | |
$cols = explode(',', $row); | |
$rowData = array(); | |
if (count($cols) <= 1) { | |
continue; | |
} | |
foreach ($cols as $index => $value) { | |
if ($headers[$index]) { | |
$rowData[$headers[$index]] = $value; | |
} | |
} | |
$data[] = $rowData; | |
unset($cols); | |
} | |
return $data; | |
} | |
/** | |
* Create the URL for an API request | |
* @inheritdoc from __construct | |
*/ | |
protected function makeUrl($symbol, $from = null, $to = null) | |
{ | |
$url = 'http://ichart.finance.yahoo.com/table.csv?s='; | |
$url .= urlencode($symbol); | |
if ($from) { | |
list($fromYear, $fromMonth, $fromDay) = explode(',', date('Y,n,j', strtotime($from))); | |
$url .= sprintf( | |
'&a=%s&b=%s&c=%s', | |
--$fromMonth, | |
$fromDay, | |
$fromYear | |
); | |
} | |
if ($to) { | |
list($toYear, $toMonth, $toDay) = explode(',', date('Y,n,j', strtotime($to))); | |
$url .= sprintf( | |
'&d=%s&e=%s&f=%s', | |
--$toMonth, | |
$toDay, | |
$toYear | |
); | |
} | |
if ($this->quotesInterval) { | |
$url .= '&g=' . $this->quotesInterval; | |
} | |
return $url . '&ignore=.csv'; | |
} | |
/** | |
* Set the column names to extract from CSV data | |
* If you only need one field, specify it to avoid populating arrays with other fields that won't be used. | |
* Setting this to null will cause all columns to be returned | |
* | |
* Default is all fields, which is equivalent to: array( | |
* "Date", "Open", "High", "Low", "Close", "Volume", "Adj Close" | |
* ) | |
* | |
* @param array $columns | |
*/ | |
public function limitColumns($columns) | |
{ | |
$this->limitColumns = $columns; | |
} | |
public function getLimitColumns() | |
{ | |
return $this->limitColumns; | |
} | |
public function setQuotesInterval($quotesInterval) | |
{ | |
$this->quotesInterval = $quotesInterval; | |
} | |
public function getQuotesInterval() | |
{ | |
return $this->quotesInterval; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Get real-time/20 minute delayed stock information from Yahoo | |
* | |
* Based on http://www.gummy-stuff.org/Yahoo-data.htm | |
*/ | |
class YahooRealTimeStockApi | |
{ | |
const AFTER_HOURS_CHANGE_RT = 'c8'; | |
const ANNUALIZED_GAIN = 'g3'; | |
const ASK = 'a'; | |
const ASK_RT = 'b2'; | |
const ASK_SIZE = 'a5'; | |
const AVERAGE_DAILY_VOLUME = 'a2'; | |
const BID = 'b'; | |
const BID_RT = 'b3'; | |
const BID_SIZE = 'b6'; | |
const BOOK_VALUE = 'b4'; | |
const CHANGE = 'c1'; | |
const CHANGE_AND_PERCENT_CHANGE = 'c'; | |
const CHANGE_FROM_200_DAY_MOVING_AVERAGE = 'm5'; | |
const CHANGE_FROM_50_DAY_MOVING_AVERAGE = 'm7'; | |
const CHANGE_FROM_52_WEEK_HIGH = 'k4'; | |
const CHANGE_FROM_52_WEEK_LOW = 'j5'; | |
const CHANGE_IN_PERCENT = 'p2'; | |
const CHANGE_PERCENT_RT = 'k2'; | |
const CHANGE_RT = 'c6'; | |
const COMMISSION = 'c3'; | |
const DAYS_HIGH = 'h'; | |
const DAYS_LOW = 'g'; | |
const DAYS_RANGE = 'm'; | |
const DAYS_RANGE_RT = 'm2'; | |
const DAYS_VALUE_CHANGE = 'w1'; | |
const DAYS_VALUE_CHANGE_RT = 'w4'; | |
const DIVIDEND_OR_SHARE = 'd'; | |
const DIVIDEND_PAY_DATE = 'r1'; | |
const DIVIDEND_YIELD = 'y'; | |
const EARNINGS_OR_SHARE = 'e'; | |
const EBITDA = 'j4'; | |
const EPS_ESTIMATE_CURRENT_YEAR = 'e7'; | |
const EPS_ESTIMATE_NEXT_QUARTER = 'e9'; | |
const EPS_ESTIMATE_NEXT_YEAR = 'e8'; | |
const ERROR_INDICATION = 'e1'; // for symbol changed / invalid | |
const EX_DIVIDEND_DATE = 'q'; | |
const FIFTY_DAY_MOVING_AVERAGE = 'm3'; | |
const FIFTY_TWO_WEEK_HIGH = 'k'; | |
const FIFTY_TWO_WEEK_LOW = 'j'; | |
const FIFTY_TWO_WEEK_RANGE = 'w'; | |
const FLOAT_SHARES = 'f6'; | |
const HIGH_LIMIT = 'l2'; | |
const HOLDINGS_GAIN = 'g4'; | |
const HOLDINGS_GAIN_PERCENT = 'g1'; | |
const HOLDINGS_GAIN_PERCENT_RT = 'g5'; | |
const HOLDINGS_GAIN_RT = 'g6'; | |
const HOLDINGS_VALUE = 'v1'; | |
const HOLDINGS_VALUE_RT = 'v7'; | |
const LAST_TRADE_DATE = 'd1'; | |
const LAST_TRADE_PRICE_ONLY = 'l1'; | |
const LAST_TRADE_RT_WITH_TIME = 'k1'; | |
const LAST_TRADE_SIZE = 'k3'; | |
const LAST_TRADE_TIME = 't1'; | |
const LAST_TRADE_WITH_TIME = 'l'; | |
const LOW_LIMIT = 'l3'; | |
const MARKET_CAPITALIZATION = 'j1'; | |
const MARKET_CAP_RT = 'j3'; | |
const MORE_INFO = 'i'; | |
const NAME = 'n'; | |
const NOTES = 'n4'; | |
const ONE_YR_TARGET_PRICE = 't8'; | |
const OPEN = 'o'; | |
const ORDER_BOOK_RT = 'i5'; | |
const PEG_RATIO = 'r5'; | |
const PERCENT_CHANGE_FROM_200_DAY_MOVING_AVERAGE = 'm6'; | |
const PERCENT_CHANGE_FROM_50_DAY_MOVING_AVERAGE = 'm8'; | |
const PERCENT_CHANGE_FROM_52_WEEK_HIGH = 'k5'; | |
const PERCENT_CHANGE_FROM_52_WEEK_LOW = 'j6'; | |
const PREVIOUS_CLOSE = 'p'; | |
const PRICE_OR_BOOK = 'p6'; | |
const PRICE_OR_EPS_ESTIMATE_CURRENT_YEAR = 'r6'; | |
const PRICE_OR_EPS_ESTIMATE_NEXT_YEAR = 'r7'; | |
const PRICE_OR_SALES = 'p5'; | |
const PRICE_PAID = 'p1'; | |
const P_OR_E_RATIO = 'r'; | |
const P_OR_E_RATIO_RT = 'r2'; | |
const SHARES_OWNED = 's1'; | |
const SHORT_RATIO = 's7'; | |
const STOCK_EXCHANGE = 'x'; | |
const SYMBOL = 's'; | |
const TICKER_TREND = 't7'; | |
const TRADE_DATE = 'd2'; | |
const TRADE_LINKS = 't6'; | |
const TWO_HUNDRED_DAY_MOVING_AVERAGE = 'm4'; | |
const VOLUME = 'v'; | |
/** | |
* Fetch the latest data for a list of symbols | |
* @param array $symbols | |
* @param array $format - array of constants from this class | |
* @return array | |
*/ | |
public function fetch($symbols, $format) { | |
$url = $this->makeUrl($symbols, $format); | |
curl_setopt_array($ch = curl_init(), array( | |
CURLOPT_URL => $url, | |
CURLOPT_RETURNTRANSFER => true | |
) | |
); | |
$response = curl_exec($ch); | |
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE); | |
curl_close($ch); | |
if ($status != 200) { | |
throw new RuntimeException("Request to $url returned status $status"); | |
} | |
return $this->parseStockCsv($symbols, $format, $response); | |
} | |
/** | |
* Convert CSV data into PHP vals | |
* @param string $csv - CSV from ichart.finance.yahoo.com | |
* @return array | |
*/ | |
protected function parseStockCsv($symbols, $format, $csv) | |
{ | |
$data = array(); | |
$rows = explode("\n", trim($csv)); | |
$colCount = count($format); | |
foreach ($rows as $rowIndex => $row) { | |
$cols = explode(',', $row); | |
$symbol = $symbols[$rowIndex]; | |
if (count($cols) != $colCount) { | |
throw new RuntimeException('CSV not in expected format'); | |
continue; | |
} | |
$symbolData = array(); | |
foreach ($cols as $colIndex => $value) { | |
$symbolData[$format[$colIndex]] = trim($value,'" '); | |
} | |
$data[$symbol] = $symbolData; | |
} | |
return $data; | |
} | |
/** | |
* Create the URL for an API request | |
* @inheritdoc from {fetch} | |
*/ | |
protected function makeUrl($symbols, $format) | |
{ | |
return sprintf( | |
'http://download.finance.yahoo.com/d/?s=%s&f=%s', | |
urlencode(implode('+', $symbols)), | |
urlencode(implode('', $format)) | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Get stock symbol information from Yahoo iCharts. | |
* This uses the same API the finance charts on finance.yahoo.com use. | |
*/ | |
class YahooStockApi | |
{ | |
const PERIOD_DAYS = 'd'; | |
const PERIOD_WEEKS = 'w'; | |
const PERIOD_MONTHS = 'm'; | |
const PERIOD_YEARS = 'y'; | |
const TYPE_QUOTE = 'quote'; | |
const TYPE_CLOSE = 'close'; | |
const TYPE_SMA = 'sma'; | |
/** | |
* Get data about a stock symbol to a period limit. | |
* @param string $symbol | |
* @param string $periodCount - The number of periods to return | |
* @param string $periodType - type of period, one of YahooStockApi::PERIOD_* | |
* @param string $dataType - one of YahooStockApi::TYPE_* | |
*/ | |
public function fetch($symbol, $periodCount, $periodType = self::PERIOD_DAYS, $dataType = self::TYPE_QUOTE) | |
{ | |
$url = $this->makeUrl($symbol, $periodCount, $periodType, $dataType); | |
curl_setopt_array($ch = curl_init(), array( | |
CURLOPT_URL => $url, | |
CURLOPT_RETURNTRANSFER => true | |
) | |
); | |
$response = curl_exec($ch); | |
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE); | |
curl_close($ch); | |
if ($status != 200) { | |
throw new ErrorException("Request to $url returned status $status"); | |
} | |
return $this->parseStockCsv($response); | |
} | |
/** | |
* Convert CSV data into a PHP data | |
* | |
* @param string $csv - CSV from ichart.finance.yahoo.com | |
* @return array | |
*/ | |
protected function parseStockCsv($csv) | |
{ | |
$data = array( | |
'series' => array() | |
); | |
$rows = explode("\n", trim($csv)); | |
if (count($rows) < 2) { | |
throw new UnexpectedValueException('Input data not in a readable format'); | |
} | |
foreach ($rows as $row) { | |
// Check if row has header | |
$colonPos = strpos($row, ':'); | |
if ($colonPos !== false) { | |
$header = substr($row, 0, $colonPos); | |
$row = substr($row, $colonPos+1); | |
} else { | |
$header = false; | |
} | |
$cols = explode(',', $row); | |
if ($header) { | |
$data[$header] = $cols; | |
} else { | |
$data['series'][] = $cols; | |
} | |
unset($cols); | |
} | |
return $data; | |
} | |
/** | |
* Create the URL for an API request | |
* @inheritdoc from {fetch} | |
*/ | |
protected function makeUrl($symbol, $periodCount, $periodType, $dataType) | |
{ | |
return sprintf( | |
'http://chartapi.finance.yahoo.com/instrument/1.0/%s/chartdata;type=%s;range=%s;/csv', | |
urlencode($symbol), | |
$dataType, | |
$periodCount . $periodType | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment