[Перевод] API Токийской фондовой биржи Jquants

gyjjcq13klmmfzgclogngvsf8jc.png


Недавно вышедшая бета-версия jquants-api позволяет получать массивы суточных финансовых данных от более чем четырёх тысяч компаний, представленных на Токийской фондовой бирже.

На данный момент через API доступны следующие массивы данных:


В будущем добавятся новые массивы данных.

Хотя текущие исторические данные доступны только начиная с 2017 года, поощряется отправка пользователями отзывов об API через обычные каналы github (и т. п.), чтобы разработчики могли подробнее понять особенности его использования.

В настоящий момент API бесплатен для личного пользования, для доступа к нему достаточно потратить несколько секунд на регистрацию и создание аккаунта на официальном веб-сайте с указанием адреса электронной почты, пароля и основных сведений.

qlwawipwpk5whuboblqqcgoqxly.png


Участники сообщества уже предложили создать обёртки вокруг http-вызовов для упрощения анализа данных.

Часть этих обёрток доступна в github JQuants, в основном дата-саентисты использовали языки наподобие R и Python.

В этой статье мы расскажем о доступе к JQuants API при помощи языка JavaVM, в частности, Java и Clojure, посредством проекта jquant-api-jvm.

▍ Доступ к JQuants API при помощи Java


После настройки пароля имени пользователя в онлайн-форме нужно выполнить одно из следующих действий:

  • Создать файл в $HOME/.config/jquants/login.edn со следующим содержимым:
{:mailaddress "john@doe.com", :password "johndoe"}


Или

  • Вызвать функцию login объекта jquantsapi.
jquantsapi api = new jquantsapi();
api.login("john@doe.com", "johndoe");


Стоит заметить, что второй способ, по сути, выполнит то же самое, что и ручной процесс выше, и создаст файл login.edn с вашими учётными данными.

▍ Простой вызов API для получения суточных данных

Map result = api.daily(code, "20220301");
System.out.println(result);


Полученный от API результат в виде map, состоящей из нескольких map — это отдельная суточная запись, соответствующая спецификациям JQuants API.

{
    "daily_quotes": [
        {
            "Code": "86970",
            "Close": 2178.0,
            "Date": "20220301",
            "AdjustmentHigh": 2204.5,
            "Volume": 1180200.0,
            "TurnoverValue": 2575637550.0,
            "AdjustmentClose": 2178.0,
            "AdjustmentLow": 2172.5,
            "Low": 2172.5,
            "High": 2204.5,
            "Open": 2183.5,
            "AdjustmentOpen": 2183.5,
            "AdjustmentFactor": 1.0,
            "AdjustmentVolume": 1180200.0
        }
    ]
}


Также можно удобно запрашивать этот объект при помощи jxpath.

JXPathContext context = JXPathContext.newContext(result);
Double open = (Double) context.getValue("/daily_quotes[1]/Open");
System.out.printf("Quote for %s on day %s is %f\n", code, date, open);

// OUTPUT
// Quote for 24130 on day 20220301 is 4315.000000


При вызове calling jquants можно также указать диапазон дат получаемых котировок:

Map result = api.daily(code, from, to);
JXPathContext context = JXPathContext.newContext(result);
System.out.println(context.selectNodes("//Open"));

// OUTPUT
// [4315.0, 4455.0, 4595.0, 4479.0]


Получение информации о котировках или финансовой отчётности можно также выполнить как показано в примере ниже:

Map listedInfo = api.listedInfo(code);
JXPathContext context = JXPathContext.newContext(listedInfo);
System.out.printf("Code %s is for companyName %s\n", code, context.getValue("//CompanyNameFull"));

// OUTPUT
// Code 24130 is for companyName エムスリー

Map statements = api.statements(code, "20220727");
JXPathContext context2 = JXPathContext.newContext(statements);
System.out.printf("Profit: %s for Code %s\n", context2.getValue("//Profit"), code);

// OUTPUT
// Profit: 12127000000 for Code 24130


Вместо того, чтобы использовать код для доступа к суточным данным, Java-обёртка также позволяет использовать метод dailyFuzzy, при помощи которого можно напрямую использовать EnglishName компании вместо её кода.

Для этого она создаёт локальный кэш, поэтому первый вызов будет немного медленным, однако потом вы сможете, например, выполнять запросы котировок по названию компании:

Map m = Map.of("CompanyNameEnglish","Japan Exchange","from", "20220301","to", "20220401");
Map result = api.dailyFuzzy(m);
System.out.println(result);


Этот фрагмент кода возвращает такой же тип результатов, что и стандартная функция суточных результатов.

{
    "daily_quotes"[
        {
            "Volume"1180200.0,
            "AdjustmentOpen"2183.5,
            "Open"2183.5,
            "Close"2178.0,
            "AdjustmentClose"2178.0,
            "Date""20220301",
            "AdjustmentVolume"1180200.0,
            "High"2204.5,
            "AdjustmentHigh"2204.5,
            "Low"2172.5,
            "Code""86970",
            "AdjustmentFactor"1.0,
            "TurnoverValue"2.57563755E9,
            "AdjustmentLow"2172.5
        } 
...
		{
            "Volume"1150000.0,
            "AdjustmentOpen"2273.5,
            "Open"2273.5,
            "Close"2323.5,
            "AdjustmentClose"2323.5,
            "Date""20220401",
            "AdjustmentVolume"1150000.0,
            "High"2330.5,
            "AdjustmentHigh"2330.5,
            "Low"2253.5,
            "Code""86970",
            "AdjustmentFactor"1.0,
            "TurnoverValue"2.659037E9,
            "AdjustmentLow"2253.5
        }
    ]
}


В подпроекте JavaSample на github можно также найти краткий пример того, как создавать график возвращаемых котировок при помощи quickchart.io.

```java
Map result = api.daily(code, "20220301", "20220505");
JXPathContext context = JXPathContext.newContext(result);

QuickChart chart = new QuickChart();
chart.setWidth(500);
chart.setHeight(300);
String config =
        format("{type: 'line',data: {labels: %s , datasets: [{label: 'Open', data:%s ,fill: false}, {label: 'Close', data:%s ,fill: false}]}}",
                context.selectNodes("//Date"),
                context.selectNodes("//Open"),
                context.selectNodes("//Close"));
chart.setConfig(config);

System.out.println(chart.getUrl());


API quickchart.io с базовой функциональностью бесплатен и довольно удобен для демонстрации сгенерированного графика. Конфигурация самого графика является стандартной конфигурацией JSON.

При выполнении приведённого выше кода будет получен URL графика, который можно использовать для многократного доступа к сгенерированному графику.

o3b-n-jhinormmbotlqasnceuxw.png


Другие примеры кода можно найти в коде; например, там есть пример генерации графика скользящего среднего за три дня суточных котировок на момент открытия…

sihvcjkv3du6pzhcjdgu6fguqec.png


Полный код на Java для этого есть на github.

▍ Доступ к JQuants API при помощи Clojure


Код самой оболочки внутри написан на Clojure, поэтому доступ к JQuants API при помощи Clojure удобен в том смысле, что вы можете получать map, заполненные обычными ключевыми словами формата edn вместо строк.

Функции обёртки соответствуют функциям на Java. Для получения суточных котировок нужно выполнить следующее:

(require '[hellonico.jquants-api :as api])

(def raw (api/daily {:code 2413 :from 20220301 :to 20220328}))
(def data (raw :daily_quotes))


Дополнительное преимущество использования Clojure в JVM заключается в том, что для запросов данных требуется внешняя библиотека.

(-> data first :Open)
; 4315.0


Здесь для обёртки снова есть понятный пример того, как создавать график скользящего среднего суточных котировок при помощи обёртки JQuants и библиотеки для построения графиков oz.

Из суточных котировок, полученных от JQuants API, сначала вычисляется пятидневное скользящее среднее:

(defn average [coll]
  (/ (reduce + coll)
     (count coll)))

(defn ma [period coll]
  (lazy-cat (repeat (dec period) nil)
            (map average (partition period 1  coll))))
(def ma-5 (partial ma 5))

(def _data 
   (map #(assoc %1 :ma %2) data (ma-5 (map :High data))))


Таким образом, данные дополняются записью : ma для каждой котировки, и используются в конфигурации графика:

(def data-plot
  {:data {:values _data}
   :encoding {:x {:field "Date" :type "ordinal"}
              :y {:field "ma" :type "quantitative"}
              :color {:field "Code" :type "nominal"}}
   :mark "line"})


Всё это можно отобразить на графике при помощи синтаксиса в стиле hiccup.

(def viz
  [:div
   [:h1 "5 days Moving average"]
   [:p "Entity code 24130"]
   [:p "from 20220301 to 20220328"]
   [:vega-lite data-plot]
   ;[:h2 "If ever, oh ever a viz there was, the vizard of oz is one because, because, because..."]
   [:p (str (java.util.Date.))]
   ])


Что приводит к созданию следующего графика:

mmbkhdlwy5v37i6op4zwypurgou.png


Чтобы всё это было ещё полезнее и интереснее, можно воспользоваться сторонними проектами, например, готовым примером Jupyter Notebook из IJava.

jquants-api-jvm доступен по дружественной к опенсорсу лицензии Eclipse. Разработчики приглашают обсуждать новые массивы данных для jquants API и делиться ими с сообществом.

Telegram-канал с полезностями и уютный чат

sz7jpfj8i1pa6ocj-eia09dev4q.png

© Habrahabr.ru