はじめに
ESP32を使って株価情報や為替情報を表示させてみたいと思いました。
その際、APIをいろいろ調査しました。それらの情報をこちらにコミットしておきます。
Yahoo! finance APIで為替情報を取得するには
次のAPIにアクセスしてください。
https://query1.finance.yahoo.com/v8/finance/chart/USDJPY=X?interval=1d
対円通貨コード一覧表(ex.USDJPY=X)はこちら
東証の株価を取得するには
次のAPIにアクセスしてください。
https://query1.finance.yahoo.com/v8/finance/chart/4442.T?interval=1d
XXXX.Tの.Tは東証のことです。
日経平均株価を取得するには
次のAPIにアクセスしてください。
https://query1.finance.yahoo.com/v8/finance/chart/^N225?interval=1d
^N225は日経平均の証券コードです。
サンプルソース
サンプルソースはこちらです。M5Stackで動作確認を行いました。
動作風景はこちら
とりあえず、M5Unifiedを使って、表示してみた。
— riraosan (@riraosan_0901) October 27, 2023
Yahoo!financeAPIを叩いて、為替と日経平均株価と、ある企業の株価を表示してみました。
次はRCAモジュールを使って、テレビに表示してみます。画面デザイン力はない。。#M5Stack pic.twitter.com/g8fSn7yjzC
#include <memory>
#include <Arduino.h>
#include <SD.h>
#include <SPIFFS.h>
#include <M5ModuleRCA.h>
#include <M5Unified.h>
// basic
#include <WiFi.h>
#include <HTTPClient.h>
#include <Ticker.h>
#define HTTP_BUFFER 1024 * 2
// github
#include <ArduinoJson.h>
#include <StreamUtils.h>
// yahoo finance (yahoo.com) Root Certificate
constexpr const char *ca = R"(-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
+OkuE6N36B9K
-----END CERTIFICATE-----
)";
const char *ssid = "your ssid"; // Enter SSID
const char *password = "your password"; // Enter Password
// Yahoo! finance API endpoint
String endpoint("https://query1.finance.yahoo.com/v8/finance/chart/{code}?interval=1d");
DynamicJsonDocument _doc(HTTP_BUFFER);
float _regularMonyOrder = 0.0;
float _reqularStockPrice = 0.0;
// APIにリクエストを送る→Jsonレスポンス取得
long doHttpGet(String url, const char *ca) {
log_i("[HTTP] GET begin...\n");
HTTPClient http;
http.begin(url, ca);
log_i("[HTTP] GET...");
// start connection and send HTTP header
int httpCode = http.GET();
unsigned long index = 0;
// httpCode will be negative on error
if (httpCode > 0) {
// HTTP header has been send and Server response header has been handled
log_i("[HTTP] GET... code: %d", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK) {
ReadLoggingStream loggingStream(http.getStream(), Serial);
DeserializationError error = deserializeJson(_doc, loggingStream);
if (error) {
log_e("deserializeJson() failed: %s", error.f_str());
http.end();
return -1;
}
} else {
http.end();
log_e("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
return -1;
}
} else {
http.end();
log_e("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
return -1;
}
http.end();
return 0;
}
// Mony order code is ex. USDJPY=X. etc...
float getMonyOrder(String monyordercode) {
String api(endpoint);
api.replace("{code}", monyordercode);
if (doHttpGet(api, ca)) {
log_e("fail to load json data.");
}
JsonObject chart_result_0 = _doc["chart"]["result"][0];
if (chart_result_0.isNull() == false) {
JsonObject chart_result_0_meta = chart_result_0["meta"];
if (chart_result_0_meta.isNull() == false) {
return chart_result_0_meta["regularMarketPrice"];
}
}
return -1;
}
float getStockPrice(String stockcode) {
String api(endpoint);
api.replace("{code}", stockcode);
if (doHttpGet(api, ca)) {
log_e("fail to load json data.");
}
JsonObject chart_result_0 = _doc["chart"]["result"][0];
if (chart_result_0.isNull() == false) {
JsonObject chart_result_0_meta = chart_result_0["meta"];
if (chart_result_0_meta.isNull() == false) {
return chart_result_0_meta["regularMarketPrice"];
}
}
return -1;
}
void initWifi(void) {
// Connect to wifi)
WiFi.begin(ssid, password);
log_i(" WiFi connecting");
// Wait some time to connect to wifi
for (int i = 0; i < 30 && WiFi.status() != WL_CONNECTED; i++) {
log_i(".");
delay(1000);
}
log_i("\n Connected!");
}
void setup(void) {
auto cfg = M5.config();
cfg.external_display.module_rca = true; // default=true. use ModuleRCA VideoOutput
// setting for Module RCA.
cfg.module_rca.logical_width = 320;
cfg.module_rca.logical_height = 240;
cfg.module_rca.output_width = 320;
cfg.module_rca.output_height = 240;
cfg.module_rca.signal_type = M5ModuleRCA::signal_type_t::NTSC_J; // NTSC / NTSC_J / PAL_M / PAL_N
cfg.module_rca.use_psram = M5ModuleRCA::use_psram_t::psram_no_use; // psram_no_use / psram_half_use
cfg.module_rca.pin_dac = GPIO_NUM_26;
cfg.module_rca.output_level = 128;
// begin M5Unified.
M5.begin(cfg);
// Get the number of available displays
int display_count = M5.getDisplayCount();
for (int i = 0; i < display_count; ++i) {
int textsize = M5.Displays(i).height() / 60;
if (textsize == 0) {
textsize = 1;
}
M5.Displays(i).setTextSize(textsize);
M5.Displays(i).printf("No.%d\n", i);
}
// If an external display is to be used as the main display, it can be listed in order of priority.
M5.setPrimaryDisplayType({m5::board_t::board_M5ModuleRCA});
// The primary display can be used with M5.Display.
M5.Display.print("primary display\n");
M5.delay(5000);
initWifi();
float monyorder = getMonyOrder("USDJPY=X");
float nikkeiavg = getStockPrice("^N225");
float stockprice = getStockPrice("4442.T");
M5.Displays(0).setCursor(0, 0);
M5.Displays(0).printf("USD-JPY\n %05.1f[JPY]\n", monyorder);
M5.Displays(0).printf("NIKKEI AVG\n %05.1f[JPY]\n", nikkeiavg);
M5.Displays(0).printf("4442.T\n %05.1f[JPY]\n", stockprice);
}
void loop(void) {
M5.delay(1);
}
さいごに
HttpClientライブラリでリクエストを投げてください。
ArduinoJsonライブラリを使ってレスポンスのJSONをパースして各種数値を取得すれば、ESP32でTickerを作れると思います。
(了)