Глобальные фондовые рынки все больше влияют на жизнь каждого, нравится нам это или нет.
Инвесторы ищут финансовую отдачу от прибыльных компаний, а работникам может быть легче договориться о новых рабочих местах или повышении заработной платы, когда рынки находятся на подъеме, по крайней мере, если они обладают теми навыками, которые пользуются спросом. Экономисты и политики также используют цены, чтобы судить о степени доверия к крупнейшим предприятиям страны или отрасли.
Этот пост покажет вам, как получить информацию об акциях конкретной компании с помощью Go.
Источники информации
Существуют коммерчески доступные API, которые будут предоставлять надежные и регулярно обновляемые источники информации — часто в форматах файлов JSON или XML — о движении цен на мировых фондовых рынках. Если вы создаете что-то критически важное, вам, вероятно, следует использовать один из них. Две компании, которые предоставляют одни из лучших API, — это Alpha Vantage и IEX Cloud . Но подписки на доступ к этим API стоят денег или имеют ограничительные ограничения для бесплатных учетных записей.
Поскольку мы просто собираемся загрузить некоторую базовую информацию о цене одной акции, нам не нужно прилагать все эти усилия. Мы можем просто собрать общедоступную информацию из интернета. Источником, который я собираюсь использовать, является Yahoo Finance .
Загрузка HTML страницы
Сейчас одной из крупнейших компаний на Нью-Йоркской фондовой бирже является Tesla. Итак, давайте воспользуемся этим в нашем примере кода, и мы сможем увидеть, удалось ли Илону сегодня поднять или обрушить цену акций своим троллингом в Твиттере .
Каждая крупная акция имеет свой собственный символ, который обычно состоит из трех или четырех букв и помогает однозначно идентифицировать рассматриваемую компанию. Биржевой символ Tesla — TSLA . Мы будем использовать это в URL-адресе веб-страницы, с которой мы собираемся извлечь нашу информацию.
В приведенном выше примере мы просто выполняем HTTP-запрос GET, используя клиент из стандартной библиотеки Go. Затем мы распечатываем весь HTML-код страницы, просто чтобы проверить, работает ли он, или выходим из программы с фатальной ошибкой, если по какой-либо причине мы не можем загрузить страницу. Перед запуском программы проверьте подключение к Интернету, чтобы убедиться, что у вас есть доступ в Интернет. Вы даже можете попробовать загрузить страницу Yahoo в свой веб-браузер, чтобы знать, как она выглядит.
Получение рыночной цены
Теперь, когда мы смогли загрузить веб-страницу, мы собираемся использовать ее для получения необходимой информации.
Мы могли бы использовать пакет HTML-parsing, созданный командой Go ( golang.org/x/net/html ), но есть гораздо более простой вариант, который мы собираемся использовать. Goquery — это пакет Golang, который разработан для работы аналогично проверенной и надежной библиотеке Javascript jQuery : другими словами, он позволяет очень легко находить определенные элементы HTML на странице с помощью селекторов и изменять их или получать их атрибуты или содержание.
Вы можете видеть в приведенном выше коде, как мы просто создаем документ в Goquery, используя тело нашего HTTP-запроса, который предоставляет HTML-код веб-страницы, а затем используем метод для выбора Find определенного элемента. В этом случае мы хотим проверить биржевую цену Tesla, поэтому мы выбираем элемент на странице, который содержит цену, а затем сохраняем его как сильный с помощью метода (аналогично свойству Javascript или методу Text в innerTextjQuery text) .
Помните, что вам нужно будет запустить команды go mod init и go mod tidy в каталоге, где находится ваш код Go, если вы еще не установили модуль и не загрузили необходимый пакет.
Если бы все работало успешно, приведенный выше код должен был распечатать текущую цену Tesla, используя последние данные с фондовых рынков США. Мы сохранили marketPrice переменную в виде строки, но вы могли легко преобразовать ее в число с плавающей запятой64 или два целых числа (одно для долларов, а другое для центов, используя десятичный разряд в качестве разделителя). Однако мы хотим только отображать число в нашей консоли, а не манипулировать им, поэтому нам не нужно анализировать строку: мы просто распечатаем ее.
Теперь у нас есть программа, которая подключается к Интернету, загружает страницу, содержащую информацию о конкретной компании на фондовом рынке, анализирует эту страницу, получает цену и выводит ее на экран. Надеюсь, вы так же, как и я, впечатлены тем, как легко это было сделать!
Создание вспомогательной функции
На данный момент мы просто впихиваем все в нашу основную функцию, но давайте создадим вспомогательную функцию, чтобы навести порядок. Мы отделим код, который загружает веб-страницу, от кода, который ее анализирует.
Функция downloadStockWebpageBody выполняет только одну задачу: подключается к Yahoo, загружает веб-страницу, содержащую необходимую информацию о фондовом рынке, и возвращает тело ответа HTTP (чтобы мы могли передать его в goquery). Обратите внимание, что есть одно небольшое, но важное различие между нашим кодом здесь и кодом, который у нас был в функции main: мы больше не используем defer ключевое слово для закрытия тела ответа, потому что, если бы мы это сделали, его нельзя было бы использовать, когда мы вернул его вызывающей функции, что лишило бы смысла возвращать его полностью. Поэтому мы сохраним defer вызов в main функции.
Дополнительная информация
Теперь мы можем использовать вспомогательную функцию, которую мы только что определили с нашим кодом ниже, чтобы получить доступ к еще большему количеству информации с той же страницы, которую мы загрузили ранее. Разделив код HTTP-клиента на downloadStockWebpageBody функцию, мы можем более четко видеть, какую информацию мы собираем здесь:
package main
import (
"fmt"
"io"
"log"
"net/http"
"github.com/PuerkitoBio/goquery"
)
// downloadStockWebpageBody загружает страницу по указанному URL
func downloadStockWebpageBody(symbol string) io.ReadCloser {
res, err := http.Get("https://finance.yahoo.com/quote/" + symbol)
if err != nil {
log.Fatalln(err)
}
if res.StatusCode != 200 {
log.Fatalf("status code %d: %s", res.StatusCode, res.Status)
}
return res.Body
}
const (
symbol = "TSLA"
)
// main точка входа в программу
func main() {
body := downloadStockWebpageBody(symbol)
defer body.Close()
doc, err := goquery.NewDocumentFromReader(body)
if err != nil {
log.Fatalln(err)
}
getTextByField := func(field string) string {
s := "[data-field=" + field + "][data-symbol=" + symbol + "]"
return doc.Find(s).Text()
}
marketPrice := getTextByField("regularMarketPrice")
marketChange := getTextByField("regularMarketChange")
marketChangePercent := getTextByField("regularMarketChangePercent")
if marketPrice == "" || marketChange == "" || marketChangePercent == "" {
log.Fatalln("cannot access market price")
}
fmt.Printf(
"%s\n%s\n\t %s\n\t%s\n",
symbol,
marketPrice,
marketChange,
marketChangePercent,
)
}
Здесь вы можете видеть, что мы создали лямбда-функцию и сохранили ее в getTextByField переменной внутри основной функции, поскольку это уменьшает необходимость вводить один и тот же код, когда мы пытаемся получить доступ к очень похожим элементам HTML: все, что их отличает, это значение атрибута данных , которое мы принимаем в качестве аргумента функции.