mirror of
https://github.com/seigler/cryptohistory.org
synced 2025-07-26 01:06:12 +00:00
⚡ Change data API from Poloniex to CryptoCompare.com
This commit is contained in:
parent
a6784a0240
commit
5ebec31d80
3 changed files with 93 additions and 79 deletions
|
@ -18,7 +18,7 @@ $router->map('GET', '/', function() {
|
|||
});
|
||||
|
||||
// map cryptocurrency stuff
|
||||
$router->map( 'GET', '/charts/[dark|light|sparkline|candlestick|filled:theme]/[a:curA]-[btc|usdt:curB]/[a:duration]/[svg|png:format]', function($theme, $curA, $curB, $duration, $format) {
|
||||
$router->map( 'GET', '/charts/[dark|light|sparkline|candlestick|filled:theme]/[a:curA]-[a:curB]/[a:duration]/[svg|png:format]', function($theme, $curA, $curB, $duration, $format) {
|
||||
require __DIR__ . '/views/chart.php';
|
||||
return renderChart(
|
||||
$theme,
|
||||
|
@ -38,11 +38,5 @@ if( !$match || !is_callable( $match['target'] ) || false === call_user_func_arra
|
|||
header( $_SERVER["SERVER_PROTOCOL"] . ' 404 Not Found');
|
||||
echo '<h1>404 Not Found</h1><p>Page not found</p>';
|
||||
}
|
||||
try {
|
||||
} catch (Exception $e) {
|
||||
header($_SERVER["SERVER_PROTOCOL"]." 500 Server Error", true, 500);
|
||||
echo '<h1>500 Server Error</h1><p>There was a problem generating this page</p>';
|
||||
return true;
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
148
views/chart.php
148
views/chart.php
|
@ -45,33 +45,8 @@ function renderChart(
|
|||
$format = 'svg'
|
||||
) {
|
||||
|
||||
$durations = [
|
||||
/*
|
||||
valid resolutions in seconds:
|
||||
300 5m
|
||||
900 15m
|
||||
1800 30m
|
||||
7200 2h
|
||||
14400 4h
|
||||
86400 24h
|
||||
*/
|
||||
'1y'=> [
|
||||
'duration' => 60 * 60 * 24 * 365,
|
||||
'resolution' => 86400 // 24h
|
||||
],
|
||||
'30d'=> [
|
||||
'duration' => 60 * 60 * 24 * 30,
|
||||
'resolution' => 14400 // 4h
|
||||
],
|
||||
'7d'=> [
|
||||
'duration' => 60 * 60 * 24 * 7,
|
||||
'resolution' => 7200 // 2h
|
||||
],
|
||||
'24h' => [
|
||||
'duration' => 60 * 60 * 24 * 1,
|
||||
'resolution' => 900 // 15m
|
||||
]
|
||||
];
|
||||
$currencyA = strtoupper($currencyA);
|
||||
$currencyB = strtoupper($currencyB);
|
||||
|
||||
$themes = [
|
||||
'light'=>[
|
||||
|
@ -137,47 +112,89 @@ function renderChart(
|
|||
return false;
|
||||
}
|
||||
|
||||
$durations = [
|
||||
/* day, hour, minute */
|
||||
'1y'=> [
|
||||
'resolution' => 'day',
|
||||
'limit' => 365,
|
||||
'aggregate' => 7,
|
||||
'cacheTimeSeconds' => 7 * 24 * 60 * 60
|
||||
],
|
||||
'30d'=> [
|
||||
'resolution' => 'day',
|
||||
'limit' => 30,
|
||||
'aggregate' => 1,
|
||||
'cacheTimeSeconds' => 24 * 60 * 60
|
||||
],
|
||||
'7d'=> [
|
||||
'resolution' => 'hour',
|
||||
'limit' => 7 * 24,
|
||||
'aggregate' => 4,
|
||||
'cacheTimeSeconds' => 4 * 24 * 60 * 60
|
||||
],
|
||||
'24h' => [
|
||||
'resolution' => 'minute',
|
||||
'limit' => 24 * 60,
|
||||
'aggregate' => 15,
|
||||
'cacheTimeSeconds' => 15 * 60
|
||||
]
|
||||
];
|
||||
|
||||
if (array_key_exists($duration, $durations)) {
|
||||
$dataDuration = $durations[$duration]['duration'];
|
||||
$dataResolution = $durations[$duration]['resolution'];
|
||||
$resolution = $durations[$duration]['resolution'];
|
||||
$limit = $durations[$duration]['limit'];
|
||||
$aggregate = $durations[$duration]['aggregate'];
|
||||
$cacheTimeSeconds = $durations[$duration]['cacheTimeSeconds'];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
$supportedCurrencies = CacheManager::get('poloniex-supported-currencies');
|
||||
if (is_null($supportedCurrencies)) {
|
||||
$supportedCurrenciesJson = getJson('https://poloniex.com/public?command=returnCurrencies');
|
||||
foreach ($supportedCurrenciesJson as $key => $value) {
|
||||
if ($value->delisted == 0) {
|
||||
$supportedCurrencies[] = strtolower($key);
|
||||
}
|
||||
}
|
||||
CacheManager::set('poloniex-supported-currencies', $supportedCurrencies, 60 * 60 * 24 * 7); // asking once a week doesn't seem like too much
|
||||
}
|
||||
if (!in_array($currencyB, ['btc', 'usdt']) || !in_array($currencyA, $supportedCurrencies)) {
|
||||
return false;
|
||||
}
|
||||
// $supportedCurrencies = CacheManager::get('cryptocompare-supported-currencies');
|
||||
// if (is_null($supportedCurrencies)) {
|
||||
// $supportedCurrenciesJson = getJson('https://min-api.cryptocompare.com/data/all/coinlist');
|
||||
// $supportedCurrencies = [
|
||||
// 'USD',
|
||||
// 'EUR',
|
||||
|
||||
$pair = strtoupper($currencyB . '_' . $currencyA); // poloniex you strange
|
||||
// ];
|
||||
// foreach ($supportedCurrenciesJson->Data as $key => $value) {
|
||||
// if ($value->IsTrading == 1) {
|
||||
// $supportedCurrencies[] = $key;
|
||||
// }
|
||||
// }
|
||||
// CacheManager::set('cryptocompare-supported-currencies', $supportedCurrencies, 60 * 60 * 24); // asking once a day seems reasonable
|
||||
// }
|
||||
|
||||
$chartCacheKey = 'poloniex-'.$theme.'-'.$pair.'-'.$dataDuration.'-'.$format;
|
||||
// $currencyA = strtoupper($currencyA);
|
||||
// $currencyB = strtoupper($currencyB);
|
||||
|
||||
$result = CacheManager::get($chartCacheKey);
|
||||
// if (!in_array($currencyA, $supportedCurrencies) || !in_array($currencyB, $supportedCurrencies)) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
$chartCacheKey = 'cryptocompare-'.$theme.'-'.$currencyA.'-'.$currencyB.'-'.$duration.'-'.$format;
|
||||
|
||||
$result = null;//CacheManager::get($chartCacheKey);
|
||||
|
||||
if (is_null($result)) {
|
||||
$startTime = time() - $dataDuration;
|
||||
$poloniexUrl = 'https://poloniex.com/public?command=returnChartData¤cyPair=' . $pair . '&start=' . $startTime . '&end=9999999999&period=' . $dataResolution;
|
||||
$dataCacheKey = 'cryptocompare-'.$currencyA.'-'.$currencyB.'-'.$duration;
|
||||
$cryptocompareJson = CacheManager::get($dataCacheKey);
|
||||
|
||||
$poloniexJson = CacheManager::get('poloniex-json-'.$pair.'-'.$dataDuration);
|
||||
if(is_null($cryptocompareJson)) {
|
||||
$cryptocompareJson = getJson('https://min-api.cryptocompare.com/data/histo'.
|
||||
"$resolution?fsym=$currencyA&tsym=$currencyB&limit=$limit&aggregate=$aggregate");
|
||||
|
||||
if(is_null($poloniexJson)) {
|
||||
$poloniexJson = getJson($poloniexUrl);
|
||||
// Write to cache for next time
|
||||
// Expires either in a minute, or 60s after the next data point is supposed to be available
|
||||
$cacheTimeSeconds = max(60, end($poloniexJson)->date + $dataResolution - time() + 60);
|
||||
CacheManager::set('poloniex-json-'.$pair.'-'.$dataDuration, $poloniexJson, $cacheTimeSeconds);
|
||||
if ($cryptocompareJson->Response == 'Error') {
|
||||
CacheManager::set($dataCacheKey, $cryptocompareJson, 60);
|
||||
return false;
|
||||
} else {
|
||||
// Write to cache for next time
|
||||
// Expires either in a minute, or 60s after the next data point is supposed to be available
|
||||
$cacheTimeSeconds = max(60, $cryptocompareJson->TimeTo + $cacheTimeSeconds - time() + 60);
|
||||
CacheManager::set($dataCacheKey, $cryptocompareJson, $cacheTimeSeconds);
|
||||
}
|
||||
} else {
|
||||
$cacheTimeSeconds = max(60, end($poloniexJson)->date + $dataResolution - time() + 60);
|
||||
$cacheTimeSeconds = max(60, $cryptocompareJson->TimeTo + $cacheTimeSeconds - time());
|
||||
}
|
||||
|
||||
if ($format == 'svg') {
|
||||
|
@ -192,16 +209,20 @@ function renderChart(
|
|||
}
|
||||
|
||||
if ($theme == 'candlestick') {
|
||||
$poloniexChart = new NeatCharts\CandlestickChart($poloniexJson, $chartOptions);
|
||||
$chartData = $cryptocompareJson->Data;
|
||||
foreach ($chartData as $item) {
|
||||
$item->date = $item->time;
|
||||
}
|
||||
$neatChart = new NeatCharts\CandlestickChart($chartData, $chartOptions);
|
||||
} else {
|
||||
$chartData = [];
|
||||
foreach ($poloniexJson as $item) {
|
||||
$chartData[$item->date] = $item->weightedAverage;
|
||||
foreach ($cryptocompareJson->Data as $item) {
|
||||
$chartData[$item->time] = ($item->high + $item->low + $item->close) / 3;
|
||||
}
|
||||
$poloniexChart = new NeatCharts\LineChart($chartData, $chartOptions);
|
||||
$neatChart = new NeatCharts\LineChart($chartData, $chartOptions);
|
||||
}
|
||||
$result = '<?xml version="1.0" standalone="no"?>' . PHP_EOL;
|
||||
$result .= $poloniexChart->render();
|
||||
$result .= $neatChart->render();
|
||||
|
||||
if ($format == 'png') {
|
||||
$im = new Imagick();
|
||||
|
@ -215,19 +236,18 @@ function renderChart(
|
|||
CacheManager::set($chartCacheKey, $result, $cacheTimeSeconds);
|
||||
$resultExpires = time() + $cacheTimeSeconds;
|
||||
} else {
|
||||
$resultExpires = CacheManager::getInfo($chartCacheKey)[ 'expired_time' ];
|
||||
$resultExpires = CacheManager::getInfo($chartCacheKey)['expired_time'];
|
||||
// TODO cache an object that has the data and a when-expired timestamp to avoid this cache-info lookup
|
||||
$startTime = $resultExpires - $dataDuration;
|
||||
}
|
||||
|
||||
header('Expires: '.gmdate(DateTime::RFC1123, $resultExpires));
|
||||
if ($format == 'png') {
|
||||
header('Content-Type: image/png');
|
||||
header('Content-Disposition: inline; filename="Dash-chart-' . gmdate('Y-m-d\THis+0', $startTime) . '--' . gmdate('Y-m-d\THis+0') . '.png"');
|
||||
header('Content-Disposition: inline; filename="Dash-chart-' . gmdate('Y-m-d\THis+0', $resultExpires) . '--' . gmdate('Y-m-d\THis+0') . '.png"');
|
||||
echo $result;
|
||||
} else if ($format == 'svg') {
|
||||
header('Content-type: image/svg+xml; charset=utf-8');
|
||||
header('Content-Disposition: inline; filename="Dash-chart-' . gmdate('Y-m-d\THis+0', $startTime) . '--' . gmdate('Y-m-d\THis+0') . '.svg"');
|
||||
header('Content-Disposition: inline; filename="Dash-chart-' . gmdate('Y-m-d\THis+0', $resultExpires) . '--' . gmdate('Y-m-d\THis+0') . '.svg"');
|
||||
$result = str_replace([
|
||||
'@lineColor',
|
||||
'@markerColor',
|
||||
|
|
|
@ -72,8 +72,8 @@
|
|||
<section>
|
||||
<h2>Transparent SVG and PNG charts with your favorite cryptocurrencies</h2>
|
||||
<figure>
|
||||
<img src="/charts/candlestick/dash-usdt/7d/svg" alt="Poloniex Dash/BTC price">
|
||||
<figcaption>7 day Dash price candlesticks in USDT (Tether USD) <code><a href="/charts/candlestick/dash-usdt/7d/svg">https://cryptohistory.org/charts/candlestick/dash-usdt/7d/svg</a></code></figcaption>
|
||||
<img src="/charts/candlestick/dash-usd/7d/svg" alt="Dash/USD price">
|
||||
<figcaption>7 day Dash price candlesticks in USD <code><a href="/charts/candlestick/dash-usdt/7d/svg">https://cryptohistory.org/charts/candlestick/dash-usd/7d/svg</a></code></figcaption>
|
||||
</figure>
|
||||
<p>Sparklines too! ETH/BTC 7 days: <img src="/charts/sparkline/eth-btc/7d/svg" alt="ETH 7d chart" style="vertical-align: bottom;">
|
||||
<code><img src="https://cryptohistory.org/charts/sparkline/eth-btc/7d/svg" alt="ETH/BTC 7d chart" style="vertical-align: bottom;"></code>
|
||||
|
@ -82,9 +82,9 @@
|
|||
<section>
|
||||
<h2>Build your own chart:</h2>
|
||||
<p>The URL is flexible:<br>
|
||||
<code>https://cryptohistory.org/charts/{theme}/{currency}-{btc|usdt}/{timespan}/{format}</code></p>
|
||||
<code>https://cryptohistory.org/charts/{theme}/{currencyA}-{currencyB}/{timespan}/{format}</code></p>
|
||||
<p>Theme: <code>dark</code>, <code>light</code>, or <code>sparkline</code>.</p>
|
||||
<p>Currency: anything active on Poloniex. Supports prices in Bitcoin or Tether USD.</p>
|
||||
<p>Currency: anything supported by CryptoCompare.com, including fiat.</p>
|
||||
<p>Timespan: <code>1y</code>, <code>30d</code>, <code>7d</code>, or <code>24h</code>.</p>
|
||||
<p>Format: <code>svg</code> (best) or <code>png</code>.</p>
|
||||
<p>If you use svg format, you can control some of the colors with GET parameters: <code>lineColor</code>, <code>markerColor</code>, <code>risingColor</code>, <code>fallingColor</code>. Some examples: <code><a href="/charts/dark/maid-btc/7d/svg?lineColor=5593D7&markerColor=29578A">https://cryptohistory.com/charts/dark/maid-btc/7d/svg?lineColor=5593D7&markerColor=29578A</a></code> <code><a href="/charts/candlestick/fct-btc/7d/svg?risingColor=FE8534&fallingColor=00BAE9">https://cryptohistory.org/charts/candlestick/fct-btc/7d/svg?risingColor=FE8534&fallingColor=00BAE9</a></code>
|
||||
|
@ -92,13 +92,13 @@
|
|||
</section>
|
||||
<section>
|
||||
<h2>Examples:</h2>
|
||||
<p>Ethereum 24h, dark SVG: <code><a href="/charts/dark/eth-btc/24h/svg" target="_blank">https://cryptohistory.org/charts/dark/eth-btc/24h/svg</a></code></p>
|
||||
<p>Litecoin 30d, light PNG: <code><a href="/charts/light/ltc-btc/30d/png" target="_blank">https://cryptohistory.org/charts/light/ltc-btc/30d/png</a></code></p>
|
||||
<p>Doge 1y, dark SVG, yellow line: <code><a href="/charts/dark/doge-btc/1y/svg?lineColor=BB9F32" target="_blank">https://cryptohistory.org/charts/dark/doge-btc/1y/svg?lineColor=BB9F32</a></code></p>
|
||||
<p>Ethereum/Bitcoin 24h, dark SVG: <code><a href="/charts/dark/eth-btc/24h/svg" target="_blank">https://cryptohistory.org/charts/dark/eth-btc/24h/svg</a></code></p>
|
||||
<p>Litecoin/Bitcoin 30d, light PNG: <code><a href="/charts/light/ltc-btc/30d/png" target="_blank">https://cryptohistory.org/charts/light/ltc-btc/30d/png</a></code></p>
|
||||
<p>Doge/USD 1y, dark SVG, yellow line: <code><a href="/charts/dark/doge-usd/1y/svg?lineColor=BB9F32" target="_blank">https://cryptohistory.org/charts/dark/doge-usd/1y/svg?lineColor=BB9F32</a></code></p>
|
||||
</section>
|
||||
</main>
|
||||
<footer>
|
||||
Made by <a href="https://joshua.seigler.net/">Joshua Seigler</a> using <a href="https://github.com/seigler/neat-charts">seigler/neat-charts</a>, <a href="http://altorouter.com/">AltoRouter</a>, and <a href="http://www.phpfastcache.com/">phpfastcache</a> with data from the <a href="https://poloniex.com/support/api/">Poloniex public API</a>.
|
||||
Made by <a href="https://joshua.seigler.net/">Joshua Seigler</a> using <a href="https://github.com/seigler/neat-charts">seigler/neat-charts</a>, <a href="http://altorouter.com/">AltoRouter</a>, and <a href="http://www.phpfastcache.com/">phpfastcache</a> with data from the <a href="https://www.cryptocompare.com/api/">CryptoCompare public API</a>.
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue