Pull to refresh

Торговый бот на Node.js и Tinkoff API (Часть 1)

Reading time4 min
Views9.2K

Вступление

Предыстория

Все началось несколько лет назад со школьного проекта по Computer science. Моя идея была сделать компьютерную программу которая проанализирует историю рынка, определит комбинации из 4х свечей в кластеры по схожести, запомнит какая свеча шла после этой комбинации и в дальнейшем сможет найти кластер для реальной ситуации на рынке. На странице должна быть отображена ситуация на рынке, найденый кластер комбинаций и его статистика. Если в кластере большой процент комбинаций с последующей зеленой свечей - мы ставим на рост, и соответственно наоборот.

Изначально в качестве API для программы был выбран Forex Oanda. На тот момент это был единственный найденный нами брокер с Open API и кое-какой документацией. В планах сервер который работает с API и фронт для отображения работы
(на тот момент) индикатора, поэтому пишем на Node JS. Проект был доведен до логического завершения, он исправно находил похожие комбинации и собирал их в кластеры, был сделан интерфейс который изображал полу-статичную информацию. Однако протестировать все это мы так и не успели, забросив все после сдачи проекта.

Перерождение

Летом этого года я наконец скачал, так рекламируемое всеми, приложение Тинькофф Инвестиции, но не особо заходил туда, пока осенью я не наткнулся на их API и вспомнил про то что мы уже имели дело с брокерскими API. Окончательно сломило меня наличие готовой SDK для Node JS и протоколом Streaming.

Открыв заброшенный проект, я естественно не имел ни малейшего понятия, спустя столько времени, как что работает и за что отвечает, усугубляла ситуацию ужасная структура проекта со всем бэкендом в одном файле. Я решил начать все с нуля и постепенно подтягивать уже готовые модули из старого проекта.
P.S. Сейчас проект уже на стадии отработки стратегии и до сих пор не все модули используются в новом проекте.

Первые шаги

Соединение с API

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

Пишем все на Typescript. Для начала определяем все необходимые переменные для соединения, а точнее: apiURL, secretToken, socketURL. Подробности авторизации и остальные детали работы с API описаны в Документации.

import OpenAPI from '@tinkoff/invest-openapi-js-sdk';

// определяем apiURL, secretToken, socketURL

const api = new OpenAPI({ apiURL, secretToken, socketURL});

export default api;

В другом файле импортируем api и уже можем работать с рынком. Обратите внимание что для Production и Sandbox окружений используются разные ссылки и настройки.

import api from './api';
let unSub = function (){};
unSub = api.candle({ figi, interval},async (candle) => {
  console.log(candle);
});

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

Сбор базы данных для дальнейшего анализа

Приступим к созданию метода по сбору данных, на ходу было решено записывать все в JSON и установить лимит по количеству объектов в файле, при переполнении создавать новый файл и записывать уже туда. Этот модуль разделен на 2 части: первая часть собирает свечи непосредственно из Tinkoff партиями максимум в 1 день, вторая используется внутри первой и принимает в себя свечи из партии, формирует комбинации и записывает следующую свечу для формирования статистики в дальнейшем. После формирования массива комбинаций она записывает их в нужный файл в зависимости от наполнения. В новый модуль, отвечающий за работу с API пишем первую функцию.

import { CandleResolution } from '@tinkoff/invest-openapi-js-sdk';
import api from './api';

export async function getCandles( 
	// возвращает свечи с даты from до даты to
  from: string,
  to: string,
  figi: string,
  interval?: CandleResolution,
) {
  try {
    return await api.candlesGet({
      from,
      to,
      figi,
      interval,
    });
  } catch (e) {
    return { tr: 1, Error: e };
  }
}

У Tinkoff установлен лимит: максимум 1 день данных по методу api.candlesGet именно поэтому мы пишем свечи такими партиями. Даты - очень капризная вещь, везде разные форматы + разные временные зоны, поэтому убеждаемся что мы передаём в api дату в правильном формате, мной была написана простая функция по преобразованию даты в нужный формат. Пишем ее в модуль с различными часто используемыми функциями.

export function preoDate(date: Date) {
  date.setDate(date.getDate() + 1);
  const rA = date.toISOString().split(':');
  rA.pop();
  const rC = rA.join(':');
  // addToD - GMT+addToD
  return rC + ':00+0' + addtoD + ':00';
}

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

{
  "mLength": 2013,
  "main": [
    {
      "candles": [
        {
          "o": 44.4375,
          "c": 44.4125,
          "h": 44.4375,
          "l": 44.4125,
          "v": 8820,
          "time": "2018-01-23T13:25:00Z",
          "interval": "5min",
          "figi": "BBG000B9XRY4"
        },
        {
          // candle
        },
        {
          // candle
        },
        {
          // candle
        }
      ],
      "afterCandle": {
        // candle
      }
    },
    ...

В объект можно добавлять различные данные связанные с комбинацией, например сейчас разрабатывается метод определения и записи тренда в котором та или иная комбинация находилась.

Заключение

В следующей части мы детальнее рассмотрим структуру проекта и постепенно начнем смотреть самый главный модуль, ответственный за сборку кластеров.

Tags:
Hubs:
Total votes 12: ↑8 and ↓4+4
Comments18

Articles