rueckbau
This commit is contained in:
@@ -277,67 +277,39 @@ $mm->registerFunction($moduleName, 'fx_refresh', static function (string $baseCu
|
||||
}
|
||||
});
|
||||
|
||||
$mm->registerFunction($moduleName, 'bavest_request', static function (
|
||||
string $path,
|
||||
array $payload = [],
|
||||
string $accept = 'application/json',
|
||||
string $method = 'POST'
|
||||
$mm->registerFunction($moduleName, 'alpha_vantage_request', static function (
|
||||
string $functionName,
|
||||
array $params = []
|
||||
): array {
|
||||
$settings = modules()->settings('boersenchecker');
|
||||
$apiKey = trim((string) ($settings['bavest_api_key'] ?? ''));
|
||||
$timeout = (int) ($settings['bavest_timeout_sec'] ?? 12);
|
||||
$apiKey = trim((string) ($settings['alpha_vantage_api_key'] ?? ''));
|
||||
$timeout = (int) (($settings['alpha_vantage_timeout_sec'] ?? null) ?: 12);
|
||||
$timeout = $timeout > 0 ? $timeout : 12;
|
||||
$method = strtoupper(trim($method));
|
||||
$method = in_array($method, ['GET', 'POST'], true) ? $method : 'POST';
|
||||
|
||||
if ($apiKey === '') {
|
||||
module_debug_push('boersenchecker', [
|
||||
'label' => 'Bavest Request',
|
||||
'label' => 'Alpha Vantage Request',
|
||||
'type' => 'api:error',
|
||||
'request' => [
|
||||
'method' => $method,
|
||||
'path' => $path,
|
||||
'payload' => $payload,
|
||||
'function' => $functionName,
|
||||
'params' => $params,
|
||||
],
|
||||
'message' => 'Bavest-API-Key fehlt. Bitte im Modul-Setup hinterlegen.',
|
||||
'message' => 'Alpha-Vantage-API-Key fehlt. Bitte im Modul-Setup hinterlegen.',
|
||||
]);
|
||||
return [
|
||||
'ok' => false,
|
||||
'message' => 'Bavest-API-Key fehlt. Bitte im Modul-Setup hinterlegen.',
|
||||
'message' => 'Alpha-Vantage-API-Key fehlt. Bitte im Modul-Setup hinterlegen.',
|
||||
];
|
||||
}
|
||||
|
||||
$url = 'https://api.bavest.co/v2/' . ltrim($path, '/');
|
||||
$jsonPayload = '';
|
||||
if ($method === 'GET') {
|
||||
if ($payload !== []) {
|
||||
$query = http_build_query($payload, '', '&', PHP_QUERY_RFC3986);
|
||||
if ($query !== '') {
|
||||
$url .= (str_contains($url, '?') ? '&' : '?') . $query;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$jsonPayload = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
if (!is_string($jsonPayload)) {
|
||||
return [
|
||||
'ok' => false,
|
||||
'message' => 'Bavest-Payload konnte nicht kodiert werden.',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$headers = [
|
||||
'Accept: ' . $accept,
|
||||
'x-api-key: ' . $apiKey,
|
||||
];
|
||||
if ($method === 'POST') {
|
||||
$headers[] = 'Content-Type: application/json';
|
||||
}
|
||||
$url = 'https://www.alphavantage.co/query?' . http_build_query(array_merge([
|
||||
'function' => $functionName,
|
||||
'apikey' => $apiKey,
|
||||
], $params), '', '&', PHP_QUERY_RFC3986);
|
||||
|
||||
$responseBody = null;
|
||||
$httpCode = 0;
|
||||
$curlError = '';
|
||||
|
||||
if (function_exists('curl_init')) {
|
||||
$ch = curl_init($url);
|
||||
if ($ch !== false) {
|
||||
@@ -346,12 +318,8 @@ $mm->registerFunction($moduleName, 'bavest_request', static function (
|
||||
CURLOPT_FOLLOWLOCATION => true,
|
||||
CURLOPT_TIMEOUT => $timeout,
|
||||
CURLOPT_CONNECTTIMEOUT => min(5, $timeout),
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
CURLOPT_HTTPHEADER => ['Accept: application/json'],
|
||||
]);
|
||||
if ($method === 'POST') {
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonPayload);
|
||||
}
|
||||
$responseBody = curl_exec($ch);
|
||||
$curlError = curl_error($ch);
|
||||
$httpCode = (int) curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
|
||||
@@ -362,38 +330,33 @@ $mm->registerFunction($moduleName, 'bavest_request', static function (
|
||||
if (!is_string($responseBody) || $responseBody === '') {
|
||||
$context = stream_context_create([
|
||||
'http' => [
|
||||
'method' => $method,
|
||||
'method' => 'GET',
|
||||
'timeout' => $timeout,
|
||||
'header' => implode("\r\n", $headers) . "\r\n",
|
||||
'header' => "Accept: application/json\r\n",
|
||||
],
|
||||
]);
|
||||
if ($method === 'POST') {
|
||||
$contextOptions = stream_context_get_options($context);
|
||||
$contextOptions['http']['content'] = $jsonPayload;
|
||||
$context = stream_context_create($contextOptions);
|
||||
}
|
||||
$responseBody = @file_get_contents($url, false, $context);
|
||||
}
|
||||
|
||||
if (!is_string($responseBody) || $responseBody === '') {
|
||||
module_debug_push('boersenchecker', [
|
||||
'label' => 'Bavest Request',
|
||||
'label' => 'Alpha Vantage Request',
|
||||
'type' => 'api:error',
|
||||
'request' => [
|
||||
'method' => $method,
|
||||
'function' => $functionName,
|
||||
'url' => $url,
|
||||
'payload' => $payload,
|
||||
'params' => $params,
|
||||
],
|
||||
'response' => [
|
||||
'http_code' => $httpCode,
|
||||
'curl_error' => $curlError,
|
||||
'body' => null,
|
||||
],
|
||||
'message' => 'Bavest Anfrage fehlgeschlagen.',
|
||||
'message' => 'Alpha-Vantage-Anfrage fehlgeschlagen.',
|
||||
]);
|
||||
return [
|
||||
'ok' => false,
|
||||
'message' => 'Bavest Anfrage fehlgeschlagen.'
|
||||
'message' => 'Alpha-Vantage-Anfrage fehlgeschlagen.'
|
||||
. ($curlError !== '' ? ' ' . $curlError : '')
|
||||
. ($httpCode > 0 ? ' HTTP ' . $httpCode : ''),
|
||||
];
|
||||
@@ -402,35 +365,35 @@ $mm->registerFunction($moduleName, 'bavest_request', static function (
|
||||
$decoded = json_decode($responseBody, true);
|
||||
if (!is_array($decoded)) {
|
||||
module_debug_push('boersenchecker', [
|
||||
'label' => 'Bavest Request',
|
||||
'label' => 'Alpha Vantage Request',
|
||||
'type' => 'api:error',
|
||||
'request' => [
|
||||
'method' => $method,
|
||||
'function' => $functionName,
|
||||
'url' => $url,
|
||||
'payload' => $payload,
|
||||
'params' => $params,
|
||||
],
|
||||
'response' => [
|
||||
'http_code' => $httpCode,
|
||||
'body_preview' => substr($responseBody, 0, 4000),
|
||||
],
|
||||
'message' => 'Bavest Antwort ist kein gueltiges JSON.',
|
||||
'message' => 'Alpha-Vantage-Antwort ist kein gueltiges JSON.',
|
||||
]);
|
||||
return [
|
||||
'ok' => false,
|
||||
'message' => 'Bavest Antwort ist kein gueltiges JSON.',
|
||||
'message' => 'Alpha-Vantage-Antwort ist kein gueltiges JSON.',
|
||||
'raw_body' => $responseBody,
|
||||
];
|
||||
}
|
||||
|
||||
foreach (['error', 'message', 'detail'] as $errorKey) {
|
||||
foreach (['Error Message', 'Information', 'Note'] as $errorKey) {
|
||||
if (isset($decoded[$errorKey]) && is_string($decoded[$errorKey]) && trim($decoded[$errorKey]) !== '') {
|
||||
module_debug_push('boersenchecker', [
|
||||
'label' => 'Bavest Request',
|
||||
'label' => 'Alpha Vantage Request',
|
||||
'type' => 'api:error',
|
||||
'request' => [
|
||||
'method' => $method,
|
||||
'function' => $functionName,
|
||||
'url' => $url,
|
||||
'payload' => $payload,
|
||||
'params' => $params,
|
||||
],
|
||||
'response' => [
|
||||
'http_code' => $httpCode,
|
||||
@@ -447,12 +410,12 @@ $mm->registerFunction($moduleName, 'bavest_request', static function (
|
||||
}
|
||||
|
||||
module_debug_push('boersenchecker', [
|
||||
'label' => 'Bavest Request',
|
||||
'label' => 'Alpha Vantage Request',
|
||||
'type' => 'api:response',
|
||||
'request' => [
|
||||
'method' => $method,
|
||||
'function' => $functionName,
|
||||
'url' => $url,
|
||||
'payload' => $payload,
|
||||
'params' => $params,
|
||||
],
|
||||
'response' => [
|
||||
'http_code' => $httpCode,
|
||||
@@ -470,7 +433,7 @@ $mm->registerFunction($moduleName, 'display_timezone', static function (): \Date
|
||||
return new \DateTimeZone('Europe/Berlin');
|
||||
});
|
||||
|
||||
$mm->registerFunction($moduleName, 'normalize_bavest_timestamp_utc', static function (mixed $value): string {
|
||||
$mm->registerFunction($moduleName, 'normalize_market_timestamp_utc', static function (mixed $value): string {
|
||||
if (is_numeric($value)) {
|
||||
return gmdate('Y-m-d H:i:s', (int) $value);
|
||||
}
|
||||
@@ -502,7 +465,7 @@ $mm->registerFunction($moduleName, 'format_datetime_for_display', static functio
|
||||
$displayTimezone = new \DateTimeZone('Europe/Berlin');
|
||||
$source = trim((string) $source);
|
||||
|
||||
if (str_starts_with($source, 'bavest:')) {
|
||||
if (str_starts_with($source, 'bavest:') || str_starts_with($source, 'alphavantage:')) {
|
||||
$date = \DateTimeImmutable::createFromFormat('Y-m-d H:i:s', $raw, new \DateTimeZone('UTC'));
|
||||
if (!$date instanceof \DateTimeImmutable) {
|
||||
try {
|
||||
@@ -529,155 +492,82 @@ $mm->registerFunction($moduleName, 'local_now_input_value', static function ():
|
||||
return (new \DateTimeImmutable('now', new \DateTimeZone('Europe/Berlin')))->format('Y-m-d\TH:i');
|
||||
});
|
||||
|
||||
$mm->registerFunction($moduleName, 'bavest_extract_quote', static function (array $entry): ?array {
|
||||
$candidates = [$entry];
|
||||
foreach (['quote', 'data', 'result', 'security'] as $nestedKey) {
|
||||
if (isset($entry[$nestedKey]) && is_array($entry[$nestedKey])) {
|
||||
$candidates[] = $entry[$nestedKey];
|
||||
}
|
||||
$mm->registerFunction($moduleName, 'alpha_vantage_extract_global_quote', static function (array $entry): ?array {
|
||||
$quote = is_array($entry['Global Quote'] ?? null) ? $entry['Global Quote'] : $entry;
|
||||
$price = $quote['05. price'] ?? null;
|
||||
if (!is_numeric($price)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($candidates as $candidate) {
|
||||
$price = null;
|
||||
foreach (['price', 'close', 'last', 'lastPrice', 'currentPrice', 'c'] as $priceKey) {
|
||||
if (is_numeric($candidate[$priceKey] ?? null)) {
|
||||
$price = (float) $candidate[$priceKey];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($price === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$timestamp = module_fn(
|
||||
'boersenchecker',
|
||||
'normalize_bavest_timestamp_utc',
|
||||
$candidate['timestamp'] ?? $candidate['time'] ?? $candidate['date'] ?? null
|
||||
);
|
||||
|
||||
return [
|
||||
'symbol' => trim((string) ($candidate['symbol'] ?? $candidate['ticker'] ?? $entry['symbol'] ?? '')),
|
||||
'isin' => trim((string) ($candidate['isin'] ?? $entry['isin'] ?? '')),
|
||||
'price' => $price,
|
||||
'currency' => strtoupper(trim((string) ($candidate['currency'] ?? $candidate['quoteCurrency'] ?? $entry['currency'] ?? 'EUR'))) ?: 'EUR',
|
||||
'fetched_at' => $timestamp,
|
||||
'source' => 'bavest:quote',
|
||||
'raw' => $candidate,
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
return [
|
||||
'symbol' => trim((string) ($quote['01. symbol'] ?? '')),
|
||||
'price' => (float) $price,
|
||||
'currency' => '',
|
||||
'fetched_at' => gmdate('Y-m-d H:i:s'),
|
||||
'market_date' => trim((string) ($quote['07. latest trading day'] ?? '')),
|
||||
'source' => 'alphavantage:global_quote',
|
||||
'raw' => $quote,
|
||||
];
|
||||
});
|
||||
|
||||
$mm->registerFunction($moduleName, 'bavest_fetch_quote_by_isin', static function (string $isin): array {
|
||||
$isin = strtoupper(trim($isin));
|
||||
if ($isin === '') {
|
||||
$mm->registerFunction($moduleName, 'alpha_vantage_fetch_quote_by_symbol', static function (string $symbol): array {
|
||||
$symbol = strtoupper(trim($symbol));
|
||||
if ($symbol === '') {
|
||||
return [
|
||||
'ok' => false,
|
||||
'message' => 'Keine ISIN hinterlegt.',
|
||||
'message' => 'Kein Symbol hinterlegt.',
|
||||
];
|
||||
}
|
||||
|
||||
$response = module_fn('boersenchecker', 'bavest_request', 'timeseries/quote', ['isin' => $isin], 'application/json', 'GET');
|
||||
$response = module_fn('boersenchecker', 'alpha_vantage_request', 'GLOBAL_QUOTE', [
|
||||
'symbol' => $symbol,
|
||||
]);
|
||||
if (empty($response['ok'])) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$data = is_array($response['data'] ?? null) ? $response['data'] : [];
|
||||
if (isset($data['data']) && is_array($data['data'])) {
|
||||
$data = [
|
||||
'isin' => $isin,
|
||||
'data' => $data['data'],
|
||||
];
|
||||
} else {
|
||||
$data['isin'] = $data['isin'] ?? $isin;
|
||||
}
|
||||
$quote = module_fn('boersenchecker', 'bavest_extract_quote', $data);
|
||||
$quote = module_fn('boersenchecker', 'alpha_vantage_extract_global_quote', (array) ($response['data'] ?? []));
|
||||
if (!is_array($quote)) {
|
||||
return [
|
||||
'ok' => false,
|
||||
'message' => 'Bavest lieferte keinen Preis fuer die ISIN ' . $isin . '.',
|
||||
'message' => 'Alpha Vantage lieferte keinen Preis fuer das Symbol ' . $symbol . '.',
|
||||
];
|
||||
}
|
||||
|
||||
return ['ok' => true] + $quote;
|
||||
});
|
||||
|
||||
$mm->registerFunction($moduleName, 'bavest_fetch_bulk_quotes', static function (array $instruments): array {
|
||||
$payloadSymbols = [];
|
||||
$indexByIsin = [];
|
||||
$mm->registerFunction($moduleName, 'alpha_vantage_fetch_quotes', static function (array $instruments): array {
|
||||
$quotes = [];
|
||||
$errors = [];
|
||||
foreach ($instruments as $instrument) {
|
||||
if (!is_array($instrument)) {
|
||||
continue;
|
||||
}
|
||||
$isin = strtoupper(trim((string) ($instrument['isin'] ?? '')));
|
||||
if ($isin === '') {
|
||||
$instrumentId = (int) ($instrument['id'] ?? 0);
|
||||
$symbol = strtoupper(trim((string) ($instrument['symbol'] ?? '')));
|
||||
if ($instrumentId <= 0 || $symbol === '') {
|
||||
continue;
|
||||
}
|
||||
$payloadSymbols[] = ['isin' => $isin];
|
||||
$indexByIsin[$isin] = (int) ($instrument['id'] ?? 0);
|
||||
}
|
||||
|
||||
if ($payloadSymbols === []) {
|
||||
return [
|
||||
'ok' => false,
|
||||
'message' => 'Keine ISIN fuer den Bulk-Abruf verfuegbar.',
|
||||
'quotes' => [],
|
||||
];
|
||||
}
|
||||
|
||||
$response = module_fn('boersenchecker', 'bavest_request', 'bulk', [
|
||||
'symbols' => $payloadSymbols,
|
||||
'endpoint' => 'quote',
|
||||
'params' => new stdClass(),
|
||||
], 'application/json', 'POST');
|
||||
if (empty($response['ok'])) {
|
||||
return $response + ['quotes' => []];
|
||||
}
|
||||
|
||||
$data = $response['data'] ?? [];
|
||||
$items = [];
|
||||
if (is_array($data)) {
|
||||
if (isset($data['data']) && is_array($data['data'])) {
|
||||
$items = $data['data'];
|
||||
} elseif (isset($data['results']) && is_array($data['results'])) {
|
||||
$items = $data['results'];
|
||||
} elseif (array_is_list($data)) {
|
||||
$items = $data;
|
||||
} else {
|
||||
$items = [$data];
|
||||
}
|
||||
}
|
||||
|
||||
$quotes = [];
|
||||
foreach ($items as $offset => $item) {
|
||||
if (!is_array($item)) {
|
||||
$result = module_fn('boersenchecker', 'alpha_vantage_fetch_quote_by_symbol', $symbol);
|
||||
if (empty($result['ok'])) {
|
||||
$errors[] = $symbol . ': ' . (string) ($result['message'] ?? 'API-Abruf fehlgeschlagen.');
|
||||
continue;
|
||||
}
|
||||
$quote = module_fn('boersenchecker', 'bavest_extract_quote', $item);
|
||||
if (!is_array($quote)) {
|
||||
continue;
|
||||
}
|
||||
$isin = strtoupper(trim((string) ($quote['isin'] ?? $item['isin'] ?? '')));
|
||||
$instrumentId = $isin !== '' ? ($indexByIsin[$isin] ?? 0) : 0;
|
||||
if ($instrumentId <= 0 && isset($payloadSymbols[$offset]['isin'])) {
|
||||
$instrumentId = (int) ($indexByIsin[(string) $payloadSymbols[$offset]['isin']] ?? 0);
|
||||
$quote['isin'] = (string) $payloadSymbols[$offset]['isin'];
|
||||
}
|
||||
if ($instrumentId <= 0) {
|
||||
continue;
|
||||
}
|
||||
$quotes[$instrumentId] = $quote + ['instrument_id' => $instrumentId];
|
||||
|
||||
$quotes[$instrumentId] = $result + ['instrument_id' => $instrumentId];
|
||||
}
|
||||
|
||||
return [
|
||||
'ok' => true,
|
||||
'quotes' => $quotes,
|
||||
'message' => count($quotes) . ' Kurse aus Bavest Bulk geladen.',
|
||||
'errors' => $errors,
|
||||
'message' => count($quotes) . ' Kurse ueber Alpha Vantage geladen.',
|
||||
];
|
||||
});
|
||||
|
||||
$mm->registerFunction($moduleName, 'bavest_search_symbols', static function (string $keywords): array {
|
||||
$mm->registerFunction($moduleName, 'alpha_vantage_search_symbols', static function (string $keywords): array {
|
||||
$keywords = trim($keywords);
|
||||
if ($keywords === '') {
|
||||
return [
|
||||
@@ -687,60 +577,40 @@ $mm->registerFunction($moduleName, 'bavest_search_symbols', static function (str
|
||||
];
|
||||
}
|
||||
|
||||
$response = module_fn('boersenchecker', 'bavest_request', 'reference/search/aggregated', [
|
||||
'q' => $keywords,
|
||||
'limit' => 25,
|
||||
], 'application/json', 'GET');
|
||||
$response = module_fn('boersenchecker', 'alpha_vantage_request', 'SYMBOL_SEARCH', [
|
||||
'keywords' => $keywords,
|
||||
]);
|
||||
if (empty($response['ok'])) {
|
||||
return $response + ['results' => []];
|
||||
}
|
||||
|
||||
$data = $response['data'] ?? [];
|
||||
$items = [];
|
||||
if (is_array($data['data']['results'] ?? null)) {
|
||||
$items = $data['data']['results'];
|
||||
} elseif (is_array($data['results'] ?? null)) {
|
||||
$items = $data['results'];
|
||||
}
|
||||
|
||||
$data = is_array($response['data'] ?? null) ? $response['data'] : [];
|
||||
$items = is_array($data['bestMatches'] ?? null) ? $data['bestMatches'] : [];
|
||||
$results = [];
|
||||
foreach ($items as $item) {
|
||||
if (!is_array($item)) {
|
||||
continue;
|
||||
}
|
||||
$name = trim((string) ($item['name'] ?? $item['companyName'] ?? $item['securityName'] ?? ''));
|
||||
$rootTicker = trim((string) ($item['root_ticker'] ?? ''));
|
||||
$listings = is_array($item['listings'] ?? null) ? $item['listings'] : [];
|
||||
|
||||
foreach ($listings as $listing) {
|
||||
if (!is_array($listing)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$symbol = trim((string) ($listing['symbol'] ?? $rootTicker));
|
||||
$isin = strtoupper(trim((string) ($listing['isin'] ?? '')));
|
||||
$region = trim((string) ($listing['exchange'] ?? $listing['region'] ?? ''));
|
||||
$type = trim((string) ($listing['type'] ?? ''));
|
||||
$currency = strtoupper(trim((string) ($listing['currency'] ?? '')));
|
||||
|
||||
if ($symbol === '' && $name === '' && $isin === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$results[] = [
|
||||
'symbol' => $symbol,
|
||||
'name' => $name,
|
||||
'isin' => $isin,
|
||||
'type' => $type,
|
||||
'region' => $region,
|
||||
'currency' => $currency,
|
||||
'match_score' => '',
|
||||
'raw' => [
|
||||
'security' => $item,
|
||||
'listing' => $listing,
|
||||
],
|
||||
];
|
||||
$symbol = trim((string) ($item['1. symbol'] ?? ''));
|
||||
$name = trim((string) ($item['2. name'] ?? ''));
|
||||
$type = trim((string) ($item['3. type'] ?? ''));
|
||||
$region = trim((string) ($item['4. region'] ?? ''));
|
||||
$currency = strtoupper(trim((string) ($item['8. currency'] ?? '')));
|
||||
$matchScore = trim((string) ($item['9. matchScore'] ?? ''));
|
||||
if ($symbol === '' && $name === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$results[] = [
|
||||
'symbol' => $symbol,
|
||||
'name' => $name,
|
||||
'isin' => '',
|
||||
'type' => $type,
|
||||
'region' => $region,
|
||||
'currency' => $currency,
|
||||
'match_score' => $matchScore,
|
||||
'raw' => $item,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
@@ -750,17 +620,17 @@ $mm->registerFunction($moduleName, 'bavest_search_symbols', static function (str
|
||||
];
|
||||
});
|
||||
|
||||
$mm->registerFunction($moduleName, 'bavest_fetch_chart_series', static function (string $isin): array {
|
||||
$isin = strtoupper(trim($isin));
|
||||
if ($isin === '') {
|
||||
return ['ok' => false, 'message' => 'Keine ISIN angegeben.'];
|
||||
$mm->registerFunction($moduleName, 'alpha_vantage_fetch_chart_series', static function (string $symbol): array {
|
||||
$symbol = strtoupper(trim($symbol));
|
||||
if ($symbol === '') {
|
||||
return ['ok' => false, 'message' => 'Kein Symbol angegeben.'];
|
||||
}
|
||||
|
||||
$cacheDir = sys_get_temp_dir() . '/boersenchecker-bavest';
|
||||
$cacheDir = sys_get_temp_dir() . '/boersenchecker-alphavantage';
|
||||
if (!is_dir($cacheDir)) {
|
||||
@mkdir($cacheDir, 0775, true);
|
||||
}
|
||||
$cachePath = $cacheDir . '/' . md5('historical-price|' . $isin) . '.json';
|
||||
$cachePath = $cacheDir . '/' . md5('time_series_daily_adjusted|' . $symbol) . '.json';
|
||||
|
||||
$decoded = null;
|
||||
if (is_file($cachePath) && (time() - filemtime($cachePath)) < (6 * 3600)) {
|
||||
@@ -769,11 +639,10 @@ $mm->registerFunction($moduleName, 'bavest_fetch_chart_series', static function
|
||||
}
|
||||
|
||||
if (!is_array($decoded)) {
|
||||
$response = module_fn('boersenchecker', 'bavest_request', 'timeseries/history', [
|
||||
'isin' => $isin,
|
||||
'from' => date('Y-m-d', strtotime('-6 years')),
|
||||
'to' => date('Y-m-d'),
|
||||
], 'application/json', 'GET');
|
||||
$response = module_fn('boersenchecker', 'alpha_vantage_request', 'TIME_SERIES_DAILY_ADJUSTED', [
|
||||
'symbol' => $symbol,
|
||||
'outputsize' => 'full',
|
||||
]);
|
||||
if (empty($response['ok'])) {
|
||||
return $response;
|
||||
}
|
||||
@@ -781,40 +650,29 @@ $mm->registerFunction($moduleName, 'bavest_fetch_chart_series', static function
|
||||
@file_put_contents($cachePath, json_encode($decoded, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
}
|
||||
|
||||
$rows = [];
|
||||
if (isset($decoded['data']['prices']) && is_array($decoded['data']['prices'])) {
|
||||
$rows = $decoded['data']['prices'];
|
||||
} elseif (isset($decoded['data']) && is_array($decoded['data'])) {
|
||||
$rows = $decoded['data'];
|
||||
} elseif (isset($decoded['results']) && is_array($decoded['results'])) {
|
||||
$rows = $decoded['results'];
|
||||
} elseif (array_is_list($decoded)) {
|
||||
$rows = $decoded;
|
||||
}
|
||||
$rows = is_array($decoded['Time Series (Daily)'] ?? null)
|
||||
? $decoded['Time Series (Daily)']
|
||||
: (is_array($decoded['Time Series (Daily) Adjusted'] ?? null) ? $decoded['Time Series (Daily) Adjusted'] : []);
|
||||
|
||||
$dailyByDate = [];
|
||||
foreach ($rows as $row) {
|
||||
if (!is_array($row)) {
|
||||
$daily = [];
|
||||
foreach ($rows as $date => $row) {
|
||||
if (!is_array($row) || !preg_match('/^\d{4}-\d{2}-\d{2}$/', (string) $date)) {
|
||||
continue;
|
||||
}
|
||||
$date = trim((string) ($row['date'] ?? $row['time'] ?? $row['timestamp'] ?? ''));
|
||||
$close = $row['close'] ?? $row['price'] ?? $row['c'] ?? null;
|
||||
if ($date === '' || !is_numeric($close)) {
|
||||
$close = $row['5. adjusted close'] ?? $row['4. close'] ?? null;
|
||||
if (!is_numeric($close)) {
|
||||
continue;
|
||||
}
|
||||
$normalizedDate = date('Y-m-d', strtotime($date) ?: time());
|
||||
$dailyByDate[$normalizedDate] = [
|
||||
'date' => date('Y-m-d', strtotime($date) ?: time()),
|
||||
$daily[] = [
|
||||
'date' => $date,
|
||||
'close' => (float) $close,
|
||||
];
|
||||
}
|
||||
$daily = array_values($dailyByDate);
|
||||
|
||||
usort($daily, static fn (array $left, array $right): int => strcmp((string) $left['date'], (string) $right['date']));
|
||||
if ($daily === []) {
|
||||
return [
|
||||
'ok' => false,
|
||||
'message' => 'Keine historischen Schlusskurse fuer ' . $isin . ' verfuegbar.',
|
||||
'message' => 'Keine historischen Schlusskurse fuer ' . $symbol . ' verfuegbar.',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -829,11 +687,11 @@ $mm->registerFunction($moduleName, 'bavest_fetch_chart_series', static function
|
||||
|
||||
return [
|
||||
'ok' => true,
|
||||
'isin' => $isin,
|
||||
'symbol' => $symbol,
|
||||
'daily' => $daily,
|
||||
'weekly' => $aggregate($daily, 'o-W'),
|
||||
'monthly' => $aggregate($daily, 'Y-m'),
|
||||
'source' => 'bavest:timeseries/history',
|
||||
'source' => 'alphavantage:time_series_daily_adjusted',
|
||||
];
|
||||
});
|
||||
|
||||
@@ -849,7 +707,7 @@ $mm->registerFunction($moduleName, 'store_market_quote', static function (
|
||||
|
||||
$quotedAt = trim($quotedAt);
|
||||
$currency = strtoupper(trim($currency)) ?: 'EUR';
|
||||
$source = trim($source) !== '' ? trim($source) : 'bavest:quote';
|
||||
$source = trim($source) !== '' ? trim($source) : 'alphavantage:global_quote';
|
||||
|
||||
$checkStmt = $pdo->prepare(
|
||||
'SELECT id
|
||||
|
||||
Reference in New Issue
Block a user