Vyvíjíme mikroslužbu využívající Tinkoff Invest API k automatizaci práce s makléřskými reporty a kalkulací provizí.

Программирование

Inspirátoři za vývojem statistické služby pro Tinkoff Investments byli:

O čem se bude diskutovat?

  • Pouze aplikovaná část o vývoji.
  • Skutečné znalosti a zkušenosti, které jsou při práci s finančními nástroji velmi důležité.
  • Přehled problémů, na kterých je třeba pracovat

Chci tedy vypočítat obchodní statistiky a udělat to pohodlným způsobem. 

Vývoj statistické služby krok za krokem: 

  1. Připojení k Tinkoff Invest API
  2. Čerpání dat z Tinkoff Invest API v prohlížeči
  3. Příjem makléřských zpráv a transakcí
  4. Výpočet a výstup zájmových informací
  5. Závěry a plány do budoucna

Připojení k Tinkoff Invest API

Pro připojení k API si můžete vzít libovolný sdk z dokumentace https://github.com/Tinkoff/investAPI#sdk . Nebo balíček npm ` tinkoff-sdk-grpc-js `. Je důležité, aby vývojáři aktualizovali balíček na nejnovější verzi. Nainstalujte

npm i tinkoff-sdk-grpc-js

Kontrola

const { createSdk } = require(‘tinkoff-sdk-grpc-js’);   // Token, který lze získat takto  const TOKEN = ‘YOURAPI’;   // Název aplikace, pod kterou vás najdete v protokolech TCS. const appName = ‘tcsstat’;   const sdk = createSdk(TOKEN, název aplikace); (async () => {     console.log(wait sdk.users.getAccounts()); })();

Výsledek: v konzole se zobrazí seznam vašich účtů. Pojďme například analyzovat nuance:Vyvíjíme mikroslužbu využívající Tinkoff Invest API k automatizaci práce s makléřskými reporty a kalkulací provizí.

  • V seznamu účtů je „Investiční banka“, se kterou nelze pracovat pomocí API
  • Vezměte prosím na vědomí, že pole přicházejí v camelCase, zatímco v dokumentaci jsou tato pole uvedena pod_score. 
  • Bude to tak všude, takže nemůžete jen tak vzít a zkopírovat pole z dokumentace.

Užitečný:

  • Tento kód najdete ve větvi projektu

https://github.com/pskucherov/tcsstat/tree/step1 https://github.com/pskucherov/tcsstat/compare/step1   

Čerpání dat z Tinkoff Invest API v prohlížeči

Vzal jsem next.js a socket.io. Toto není silné doporučení, vyberte si podle svého uvážení. 

npx create-next-app@latest npm i socket.io socket.io-client

Okamžitě přejdeme ke kroku přátelství next+socket+investapi a všechny podrobnosti  naleznete v části Užitečné tohoto kroku. Popíšu podrobnosti: 

  • Na straně nodejs (serveru) je soubor pages/api/investapi.js. Zde vytvoříme server socket.io a připojíme se k investapi.
  • Na straně prohlížeče (klienta) se připojíme k serveru přes socket a vyžádáme si od brokera údaje o účtu. 
  • Data obdržíme od brokera na serveru a následně je odešleme klientovi. Když je klient obdrží, zobrazí se v prohlížeči. 

Výsledek:  v konzole prohlížeče můžeme vidět informace o účtech. To znamená, že v posledním kroku jsme viděli informace o účtech v konzoli serveru (nodejs), v aktuálním kroku jsme tyto informace přenesli do klienta (prohlížeče).

Vyvíjíme mikroslužbu využívající Tinkoff Invest API k automatizaci práce s makléřskými reporty a kalkulací provizí.

Nyní to uděláme tak, že si můžete vybrat účet z prohlížeče, a pokud neexistuje žádný token, do konzole se odešle chyba. Práce je jednoduchá a nic nového, proto uvádím pouze odkazy na commity

  1. https://github.com/pskucherov/tcsstat/commit/7e1ac57061e5e971588479015b06d8814d6609a9
  2. https://github.com/pskucherov/tcsstat/commit/b28ac973a57494f5232589b4cb6b9fb13b8af759 

Užitečný:

  • Jak získat přátele další a zásuvku je podrobně popsáno zde
  • Přátelský kód další+socket+investapi:

https://github.com/pskucherov/tcsstat/commit/a443a4ac1bb4f0aa898f638128755fe7391ee381 Pro koho je výše uvedené obtížné, pak zůstáváme v této fázi a zabýváme se kódem. Máte-li dotazy – ptejte se. https://github.com/pskucherov/tcsstat/tree/step2 https://github.com/pskucherov/tcsstat/compare/step1…step2

Příjem makléřských zpráv a transakcí

Existují tři způsoby , jak přijímat makléřské zprávy a transakce

  1. GetBrokerReport
  2. GetDividendsForeignIssuer
  3. GetOperationsByCursor

Od samého začátku je důležité vědět: 

  • Zpráva o zprostředkování je generována v režimu T-3, tzn. obchody se tam zobrazují po jejich skutečném provedení. 
  • Pokud tedy požádáte o tento přehled za poslední dva dny, bude připraven za tři dny. 
  • Pro získání transakcí za poslední dny používáme metodu pro příjem transakcí, ale pamatujte, že jejich ID a obsah se mohou po vygenerování zprávy o zprostředkování změnit.

GetBrokerReport

Chcete-li získat makléřskou zprávu, musíte vzít ID účtu, datum zahájení a datum ukončení zprávy, ale ne více než 31 dní. Požadavek na vygenerování sestavy posíláme do rozhraní API v generování _broker_report_request , jako odpověď získáme taskId. Poté pomocí tohoto taskId získáme data z get _broker_report_response.

Takže dokumentace říká, že ve skutečnosti existují nuance. Pozor na ruce:
  • Musíte uložit TaskID navždy přesně pro tato data. 
  • Vzhledem k tomu, že pokud jej ztratíte, pak pro požadovaná data zpráva nejprve přijde jako odpověď na žádost o generování, 
  • A pak už to nepřijde vůbec.
Začněme psát kód

Metoda pro získání data s přihlédnutím k odečtení od aktuálního data

const getDateSubDay = (subDay = 5, start = true) => {     const date = new Date();     date.setUTCDate(date.getUTCDate() – subDay);       if (start) {         datum.setUTCHours(0, 0, 0, 0);     } else {         datum.setUTCHours(23, 59, 59, 999);     }       datum návratu; };

Požadavek na generování zprávy 

const brokerReport = wait (sdk.operations.getBrokerReport)({         createBrokerReportRequest: {             accountId,             from,             to,         }, });

Výsledek:

  • V důsledku prvního provedení příkazu získáme taskId. 
  • Report se začne generovat na straně brokera. Když je připraveno, není známo, čekáme a pravidelně vytahujeme taskId v očekávání zprávy.
  • Proč? Protože pokud není sestava připravena, vyhodí chybu. Pokud report není na straně brokera připraven, jedná se o chybu ve vašem kódu. Zpracujte prosím: 30058|INVALID_ARGUMENT|úkol ještě není dokončen, zkuste to prosím znovu později

Kód pro čekání a příjem hlášení vypadá asi takto.

const timer = async time => {     return new Promise(resolve => setTimeout(resolve, time)); }   const getBrokerResponseByTaskId = async (taskId, stránka = 0) => {     try {         return wait (sdk.operations.getBrokerReport)({             getBrokerReportRequest: {                 taskId,                 page,             },         });     } catch (e) {         console.log(‘wait’, e);         časovač čekání (10000);         return wait getBrokerResponseByTaskId(taskId, page);     } };

Pak se stane stejné kouzlo. Zastavíme náš skript, spustíme jej znovu, nemáme taskId. Spustíme kód s požadavkem taskId, ale už nedostaneme taskId, ale rovnou report. Kouzlo! A všechno by bylo v pořádku, kdyby to tak bylo pořád. Ale za měsíc tam nebudou vůbec žádná data. Užitečné :

  • Trochu teorie je nastíněno zde a zde .
  • Po sestavení kódu bude koncept vypadat nějak takto.

https://github.com/pskucherov/tcsstat/tree/step3.1 https://github.com/pskucherov/tcsstat/compare/step3.1

  • Pokud na to někdo narazí, tak vítejte v problému . Poté, co toto kouzlo opraví, ztratí svou sílu a bude nějak jiné. Ale v současné chvíli (21.3.2023) to tak funguje.

GetDividendsForeignIssuer

Někdo by si mohl myslet, že metoda je podobná té předchozí a můžete použít jedinou metodu, ve které pouze změníte název operací. Ale neuhádli!  Pojmenování se tam velmi liší jak v metodách, tak ve vrácených informacích. A počet stránek začíná od 0, pak od 1. Abyste se v tom všem nepletli, je jednodušší napsat dvě různé metody. Což je zvláštní, protože logika práce je stejná. Dlouho jsem plival, když jsem se snažil udělat jednu metodu a bylo tam méně kódu. Nebudou zde žádné příklady.

GetOperationsByCursor

Můj nejoblíbenější ze tří. Sice ne nejpřesnější, ale nejadekvátnější. Požadavek provádíme od začátku založení účtu do maximálního možného data (zrušení účtu nebo stávajícího). Dostaneme odpověď, vezmeme kurzor a znovu požádáme, dokud jsou data.  A kód je stručnější než ve výše uvedených příkladech.

const timer = async time => {     return new Promise(resolve => setTimeout(resolve, time)); }   const getOperationsByCursor = async (sdk, accountId, from, to, kurzor = ”) => {     try {         const reqData = {             accountId,             from,             to,             limit: 1000,             state: sdk.OperationState.OPERATION_STATE_EXECUTED,             withoutCommissions: false,             withoutTrades: false,             withoutOvernights: false,             kurzor,         };           return wait sdk.operations.getOperationsByCursor(reqData);     } catch (e) {         wait timer(60000);         return wait getOperationsByCursor(sdk, accountId, from, to, cursor = ”);     } };

Koncept ke spuštění je zde: https://github.com/pskucherov/tcsstat/tree/step3.3 https://github.com/pskucherov/tcsstat/compare/step3.3 Nyní jsme připraveni přidat operace příjmu do naše aplikace. Pokud se to udělá správně, musíte získat zprávy o zprostředkování po celou dobu existence účtu. A pro chybějící data znovu načtěte tytéž T-3 z operací. Ale to lze rozdělit do samostatného článku. Mezi hlavní nuance, se kterými se setkáte, je slepení operací a makléřské zprávy.

  •  Pokud jste dnes obdrželi zprostředkovatelskou zprávu a transakce k požadovaným termínům, vložte to vše do databáze, pak nejsou žádné problémy. 
  • Zítra budete mít problémy, když obdržíte další část dat ze sestavy a operací a rozhodnete se je synchronizovat se stávající databází. 
  • Mnoho nuancí o neshodě nebo změně id po zpracování
  • Pak pro OTC trh se ID vůbec neshodují.
  •  Stejně jako nuance synchronizačních nástrojů, které se opět neshodují, kvůli zvláštnostem API. Ale to je jiný příběh.

Do naší aplikace přidáme získávání informací o operacích. Hlavní otázkou bude, kde budou data zpracována a uložena.

  •  Pokud to uděláte pro sebe, budete spotřebovávat stejná data z různých zařízení. Poté musíte zpracovat a uložit data na serveru.
  • Pokud máte mnoho různých dat spotřebovaných mnoha různými uživateli, musíte se rozhodnout, co je důležitější: rychlost uživatelů nebo úspora železa na vaší straně. Kdokoli si může dovolit nekonečné množství hardwaru, počítá vše na svém serveru a pro uživatele to dělá superrychlým, což šetří uživatelské zdroje, jako je baterie a provoz, což je u telefonů velmi důležité.

Počítání v prohlížeči zase není v zásadě nejoptimálnějším řešením. Co tedy není drahé, to zvažujeme na našem serveru. Zbytek necháme na klientovi. Opravdu chci vzít a vypočítat provizi na serveru. Zde však přichází nuance zvaná „interaktivita“. Řekněme, že máte tisíce operací a jejich přijetí trvá pět minut. Co bude mít uživatel v tuto chvíli? Spinner? Pokrok? Infa o tom, kolik bylo nahráno? Ideální je použít „aktivní čekání“, když uživatel v procesu již něco viděl. Zde je výsledek:Vyvíjíme mikroslužbu využívající Tinkoff Invest API k automatizaci práce s makléřskými reporty a kalkulací provizí.

  • Načítání stránky
  • Všechny faktury jsou požadovány
  • Poté jsou pro všechny účty požadovány všechny transakce s provizí za provedené transakce. Jakmile jsou data přijata, jsou vykreslena v prohlížeči.

Abychom data v událostech nefiltrovali pokaždé, stahujeme pro každý účet vlastní událost. Takhle:

socket.emit(‘sdk:getOperationsCommissionResult_’ + accountId, {                 items: data?.items,                 inProgress: Boolean(nextCursor), });

Návrh ke spuštění je zde: https://github.com/pskucherov/tcsstat/tree/step3 https://github.com/pskucherov/tcsstat/compare/step2…step3 Jdeme dál. Je skvělé, že jste si přečetli tento řádek! 

Výpočet a výstup zájmových informací

Záleží na tom, kdo jaké informace potřebuje. Proto vám okamžitě řeknu hlavní nuance, se kterými se setkáte.

Práce s cenami 

Každý, kdo pracuje s financemi, ví, že peněžní transakce by se měly provádět pouze s celými čísly. Kvůli nepřesnosti hodnot za desetinnou čárkou a kumulativní chybě s velkým počtem operací. Proto jsou všechny ceny prezentovány v následujícím formátu MoneyValueVyvíjíme mikroslužbu využívající Tinkoff Invest API k automatizaci práce s makléřskými reporty a kalkulací provizí.

poletypPopis
měnatětivaŘetězec ISO kód měny
Jednotkyint64Celá část součtu může být záporné číslo
nanoint32Zlomková část částky může být záporné číslo

Zpracováváme je samostatně a poté je dorovnáme na cenovou hodnotu:

kotace.jednotky + kotace.nano / 1e9

Náklady na futures kontrakty

Cena futures je uvedena v bodech, když máte měnový future, musíte znát kurz. A samozřejmě cena v bodech a cenový stupeň. Když počítáte zisk z transakcí, může to vystřelit, protože. pokud vypočítáte celkovou částku vynásobením ceny množstvím. Zde je třeba být opatrný. Zatím uvidíme, jak to půjde. To platí pro měnové futures, jinde je s tímto vše v pořádku.Vyvíjíme mikroslužbu využívající Tinkoff Invest API k automatizaci práce s makléřskými reporty a kalkulací provizí.Vyvíjíme mikroslužbu využívající Tinkoff Invest API k automatizaci práce s makléřskými reporty a kalkulací provizí.

OTC trh

Tento trh má mnoho zvláštností, takže si na něm prostudujeme operace zvlášť. Když začnete synchronizovat operace, ukáže se, že musíte uvést figi / ticker do stejné formy, abyste správně spárovali nástroj. Když to začnete synchronizovat se zprávou o zprostředkování, ukáže se, že tradeID stejné transakce má v transakcích na začátku písmena a ve zprávě o zprostředkování nejsou. Proto je nelze srovnávat … ehm-ehm … srovnáním! Porovnal jsem čas obchodu, ticker a shodu, že jedno tradeId je obsaženo v jiném. Jasně, já nevím. Kdo se s tím setká a koho to zajímá, přijďte na vydání nebo založte nové.Vyvíjíme mikroslužbu využívající Tinkoff Invest API k automatizaci práce s makléřskými reporty a kalkulací provizí.

Matematické operace na nástrojích

Bez pohledu není možné provádět matematické operace s celým seznamem. Abychom nepřidávali teplé do měkkého, měnu kontrolujeme a zpracováváme vždy pouze v případě, že jsme si jisti, že měna odpovídá, a body jsou převedeny na požadovanou měnu. Vyzbrojeni znalostmi o práci s bankovními čísly spočítáme provizi vynaloženou na každý z účtů. Asi takto: https://github.com/pskucherov/tcsstat/tree/step4 https://github.com/pskucherov/tcsstat/compare/step3…step4Vyvíjíme mikroslužbu využívající Tinkoff Invest API k automatizaci práce s makléřskými reporty a kalkulací provizí.   

Mikroservis je připraven!

https://github.com/pskucherov/tcsstat Jako domácí úkol si můžete zkontrolovat, zda služba funguje s pomalým připojením, při přerušení připojení, odpojení internetu, při chybách nebo vypršení limitů na straně brokera. 

Závěry a plány do budoucna

  • Naučili jste se základní operace a práci s Invest API
  • Čas strávený ~ 10 hodin
  • Úroveň obtížnosti ~ junior+ / nízká střední 

Pokud budete pokračovat ve zdokonalování mikroslužby, můžete skončit s něčím takovým

https://opexbot.info

  To je můj vývoj, pro ty, kteří jsou příliš líní pochopit, běhat a počítat sami. Plánuji tam přidat analytiku na žádost uživatelů. Pokud se vám článek líbil, přihlaste se k odběru mého telegramového kanálu . Vyvíjíme mikroslužbu využívající Tinkoff Invest API k automatizaci práce s makléřskými reporty a kalkulací provizí.

Pavel
Rate author
Add a comment

  1. Isakiiev

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

    Reply