Фінансовий Telegram-бот за 30 хвилин з Market Data API

Зазвичай у статтях про фінтех пишуть про те, як працюють біржі, які обробляють величезні обсяги даних на величезних швидкостях, про те, як геніальні трейдери і кванти використовують відточені алгоритми, щоб заробляти (або втрачати, буває всяке) мільярди доларів, або про роботу блокчейна, забезпеченої складними математичними викладками. Все це створює враження, ніби рівень входу в фінтех-розробку вкрай високий. І почасти воно правдиво — вимоги до розробників високонавантажених фінансових додатків суворі і специфічні.

Але всі починали з малого, і ми вважаємо, що будь-який зацікавлений людина здатна створити додаток в фінансовій сфері. Спробуємо розробити власний невеликий додаток, яке стане корисним для користувачів вже через півгодини.



оглядів сучасних технологій взаємодії з користувачами видно, як швидко набирають популярність всілякі боти і помічники, які розуміють запити на природній мові. Підтримаємо цей тренд і створимо простого Telegram-бота, який зможе щось розповісти користувачеві про ринок за запитом.

Доступ до даних
Почнемо з простої ситуації: додаток буде використовувати поточні та історичні дані про торги, а не відправляти на біржу власні заявки. Ці дані (т. зв. market data, або біржову інформацію можна отримувати у ряду компаній за відносно невелику плату або взагалі безкоштовно. З відправленням заявок все значно складніше (як мінімум — дорожче), і ми розглянемо цей процес детальніше в наступних статтях.

Які існують технології для отримання біржових даних? Список їх не надто великий: це FIX-протокол (реалізації можуть дещо відрізнятися від постачальника до постачальника),FAST, ITCH і кілька варіантів бінарних і HTTP API (наприклад, CQG, EXANTE або MOEX). Втім, універсалізація тут не так принципова: набір надаваних даних може сильно розрізнятися, і в будь-якому випадку при інтеграції доведеться розібратися з особливостями конкретного постачальника.


Ми будемо використовувати нещодавно з'явився EXANTE Market Data API: почати розробку з ним можна просто і швидко, реєстрація в системі не вимагає додаткових підтверджень, а доступ до даних безкоштовний. Поки API працює в режимі Tech Preview, але доступ відкритий для всіх бажаючих.

Функціональність
Визначивши спектр можливостей, потрібно вирішити, що саме буде робити наш чат-бот. Існує маса варіантів: від відображення курсів валют до аналітики торгових стратегій за запитом на конкретний біржовий інструмент. Поки що не будемо заглиблюватися в деталі фінансових алгоритмів і спробуємо зробити щось корисне, але при цьому досить просте.

Один з найбільш зрозумілих фінансових інструментів — це акції компаній, що торгуються на фондових біржах. З ними і будемо працювати, обравши для простоти фондовий ринок США, оскільки за нього найлегше отримати фундаментальні дані, і торги там найбільш активні.

Що цікавить початківця інвестора? Звичайно ж, вибір портфеля акцій, вклавши кошти в які, він зможе отримати прибуток. Існує багато способів вибирати акції: можна читати обзорыможна орієнтуватися на портфелі кращих інвесторів, на зразок Уоррена Баффета або Білла Екмана, а можна користуватися аналітичними методами. Один із загальноприйнятих і найбільш поширених методів — це оцінка компанії за метрикою P/E (коефіцієнт ціна/прибуток). P/E розраховується як відношення ціни акції компанії до показника Earning Per Share (EPS, прибуток на акцію).

Таким чином, наш чат-бот буде допомагати інвестору вирішити, чи включати акції певної компанії фондового ринку США в свій портфель, виходячи з поточної оцінки коефіцієнта ціна/прибуток. Високий P/E щодо інших компаній цієї галузі покаже, що у акцій є потенціал зростання. Низький ж, навпаки, дасть зрозуміти, що в майбутньому компанія може зіткнутися з проблемами.

Архітектура
Отже, в якості основного джерела біржової інформації виберемо EXANTE Market Data API (MD API). Для отримання фундаментальної інформації — інформації про загальний стан фінансів компанії — будемо використовувати відкритий джерело даних datatables.org, з яким можна працювати через YQL (Yahoo! Query Language).

Для реалізації самого бота візьмемо Python 3, а щоб запустити його максимально швидко, застосуємо фреймворк, що підтримує всі необхідні методи Telegram: python-telegram-bot.

Для роботи з Telegram будемо використовувати полінг нових повідомлень з сервера, т. к. в прототипі ми не розраховуємо на великий обсяг трафіку.

Заздалегідь подумаємо про те, щоб програма могла працювати не тільки з одним клієнтом. Для цього будемо обробляти запити в окремих потоках. Для синхронізації та запуску потоків використовуємо вбудовані можливості фреймворка python-telegram-bot та примітиви синхронізації, доступні в Python.

Всі вибрані зовнішні сервіси доступні по HTTP, так що для роботи з ними будемо використовувати відомий модуль Requests.

Напевно багато інвестори будуть цікавитися одними і тими ж акціями, які на слуху, так що додамо шар кешування, щоб ефективніше використовувати ресурси.

MD API вимагає авторизації запитів з допомогою JSON Web Token, для генерації токенів візьмемо бібліотеку PyJWT.

Підключення до API
Для початку роботи з MD API потрібно зареєструватися на сайті EXANTE для розробників.

Після реєстрації на порталі стає доступним дэшборд з даними для доступу і управління додатками. Створимо там додаток для нашого бота:



Самого бота заведемо так, як описано у документації до Telegram, через листування з роботом BotFather:



Реалізація
Почнемо з того, що навчимо бота обробляти отримані запити. З кожного повідомлення будемо намагатися виділити курси акцій і видавати по ним інформацію, щоб діалог може виглядати так:

— Привіт, робот, сьогодні в новинах чув про AAPL, здається, це якась фруктова компанія, думаю вкласти туди гроші, що скажеш?
— Акції AAPL (Apple Inc, біржа NASDAQ) мають поточну оцінку P/E 14, ціна акції $117,06
— Дякую, а що щодо NVDA і GOOG?
— NVDA (Nvidia Corp., NASDAQ): P/E 69, ціна $105.7
GOOG (Alphabet Inc., NASDAQ): P/E 29, ціна $796.42

Ініціалізуємо бота і створюємо обробники повідомлень:

# -*- coding:utf-8 -*-

re import
from import sys path

from configparser import ConfigParser

from telegram import ParseMode, Emoji
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters


config = ConfigParser()
config.read_file(open('config.ini'))

# Create telegram poller with token settings from
up = Updater(token=config['Api']['token'])
dispatcher = up.dispatcher

# Welcome message
def start(bot, update):
msg = "Hello {user_name}! I'm {bot_name}. Ask me about stocks!"

# Send the message
bot.send_message(chat_id=update.message.chat_id,
text=msg.format(
user_name=update.message.from_user.first_name,
bot_name=bot.name))

def process(bot, update):
msg = "I will try to show info on {tickers}"
tickers = re.findall(r'[A-Z]{1,4}', update.message.text)

bot.send_message(chat_id=update.message.chat_id,
text=msg.format(tickers=", ".join(tickers)))

def main():
# Add handlers to dispatcher
dispatcher.add_handler(CommandHandler("start", start))
dispatcher.add_handler(MessageHandler(Filters.text, process))

# Start the program
up.start_polling()

up.idle()

if __name__ == '__main__':
main()

Зараз наш бот вже вміє виділяти курси акцій, але нічого з ними зробити не може.

Напишемо інтерфейс для роботи з Market Data API і генерації токенів. Використовуємо документацію і керівництво по авторизації.

import jwt

# token expiration time in seconds
EXPIRATION = 3600

class MDApiConnector():
token = (None, None)
algo = "HS256"

def __init__(self, client_id, app_id, key):
self.client_id = client_id
self.app_id = app_id
self.key = key

def __get_token(self):
now = datetime.now()

# if there is easy and it's not yet been removed
if self.token[0] and (now - self.token[1]).total_seconds() < EXPIRATION:
return self.token[0]

claims = {
"iss": self.client_id,
"sub": self.app_id,
"aud": ["symbols", "ohlc"], # NB: only allowed scopes can be accessed
"iat": int(now.timestamp()),
"exp": int(now.timestamp()) + EXPIRATION
}

new_token = str(jwt.encode(claims, self.key, self.algo), 'utf-8')
self.token = (new_token, now)

return new_token

Повний код всіх модулів доступний в репозиторії: github.com/exante/telegram-bot-with-md-api

Додамо окремий потік, який буде періодично запитувати об'ємні дані по акціях:

class DataStorage(Thread):
def __init__(self, connector):
super().__init__()
self.connector = connector
self.stocks = {}

def run(self):
while True:
timeout = 15 * 60 # 15 minutes
try:
self.stocks = connector.get_stocks()
except as Exception e:
logger.error(e)
timeout = 30 # re-read in case of exception

time.sleep(timeout)

Метод роботи з API для отримання списку акцій США може виглядати так:

def get_stocks(self):
stocks = self.__request("/types/STOCK")
return {x['ticker']: {"id": x["id"], 
"exchange": x["exchange"], 
"description": x["description"]}
for x in stocks if x.get("country") == "US"}

Після запуску цього потоку і звернення до нього з обробника повідомлення, бот зможе вивести більше корисних даних (P/E тут поки ще заглушка):


Додамо запит Earning Per Share, для цього зробимо невелику обгортку над YQL з кешуванням (в недалекому майбутньому ми зможемо замінити цей виклик на аналогічний, з MD API), яка запросить значення «EarningsShare» для обраної акції.

Тепер ми можемо вивести отриманий показник EPS:


Залишилося останнє: отримати поточну ціну акції. Для більшої продуктивності нам слід було б підписатися на потік оновлень з цінами, але для прототипу можна вибрати більш простий спосіб: запитувати останню денну «свічку» — так називають елемент графіка цін, найпопулярнішого серед трейдерів.


Приклад свічкового графіка співвідношення індексу DJI і ціни на золото по роках

«Свічка» будується для певного періоду (наприклад, дні або години) і на одному малюнку об'єднує чотири цифри: ціну на початок періоду, максимальну та мінімальну ціну за період і ціну на момент закінчення періоду. Скорочення OHLC, що позначає таку свічку, як раз і розшифровується як Open-High-Low-Close. Ціна Close самої останньої свічки буде відповідати поточній ціні акції.

Метод отримання останньої свічки може виглядати так:

def get_last_ohlc_bar(self, symbolId):
# NB: we use internal symbolId, not ticker

# 86400 (sec) - day duration
ohlc = self.__request("/ohlc/%s/86400" % symbolId, {"size": 1})
return ohlc[0]

Зібравши разом всі виклики, ми отримаємо такий код обробки одного тікера:

stock = storage.stocks.get(ticker)
eps = fundamendal_api.request(ticker).get('EarningsShare')

price = api.get_last_ohlc_bar(stock['id'])
ratio = Decimal("%.4f" % price['close']) / Decimal(eps)

msg = "{ticker} ({name}, {exchange}): EPS {eps}, P/E {ratio}, ціна ${price} \n".format(
ticker = ticker,
name = stock['description'],
exchange = stock['exchange'],
ratio = "%.2f" % ratio,
price = price['close'],
eps = eps
)

І тепер наш бот став справді корисний! Він може розповісти про поточний стан справ на ринку акцій і навіть дещо порадити:



Розвиток проекту
Поточний проект можна знайти за адресою github.com/exante/telegram-bot-with-md-api

Подальший розвиток можливо за багатьма напрямками. Наприклад, можна скористатися потоком даних про нинішній ціні акції з MD API (
/md/1.0/feed
) і не запитувати ціну кожного разу з «свічок», а просто брати її з внутрішнього кеша, куди та буде потрапляти при оновленні потоку.

Можна додати боту моніторинг і аналітику (наприклад через ботан.io), а також розгорнути його на якому-небудь хмарному хостингу, начебто Heroku або Google App Engine.

Бота можна зробити більш «живим», додавши більше варіантів відповідей, а також навчити його відображати графіки зміни цін, щоб дати інвестору ще більше інформації для аналізу. Можна додати будь-які інші метрики для оцінки акцій, зберігати портфель в даних робота, щоб тримати інвестора в курсі всіх змін, і розширити функціональність — наприклад, на російський ринок акцій.

Висновок
Підключивши EXANTE Market Data API і скориставшись відкритої фундаментальної інформацією, за короткий термін ми розробили функціонального робота, який допоможе користувачу швидко оцінити ситуацію на ринку. В процесі роботи ми дізналися про деякі способи оцінки акцій на ринку і про термінологію, яка використовується в біржовій торгівлі.

Крім того, ми розглянули можливості розвитку, і навіть у такого невеликого робота їх чимало. Є ще багато способів застосування market data — і багато користувачів, які зацікавляться вашими фінансовими додатками.

У лютому EXANTE проведе хакатон, присвячений роботі з ринковими даними з допомогою EXANTE Market Data API. Автори кращих чат-ботів та додатків отримають призи, і зараз якраз є час підготуватися :) Детальніше про захід напишемо трохи пізніше.

А які API використовуєте ви? Що б ви хотіли робити з ринковими даними?
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.