Razvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju rada s brokerskim izvješćima i izračun provizija.

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

Inspiratori razvoja statističke usluge za Tinkoff Investments bili su:

O čemu će se razgovarati?

  • Samo primijenjeni dio o razvoju.
  • Stvarno znanje i iskustvo, koji su vrlo važni u radu s financijskim instrumentima.
  • Pregled problema na kojima treba raditi

Dakle, želim izračunati trgovinsku statistiku i to na prikladan način. 

Razvoj statističke usluge korak po korak: 

  1. Povezivanje s Tinkoff Invest API-jem
  2. Crtanje podataka iz Tinkoff Invest API-ja u pregledniku
  3. Primanje brokerskih izvješća i transakcija
  4. Izračun i izlaz informacija od interesa
  5. Zaključci i planovi za budućnost

Povezivanje s Tinkoff Invest API-jem

Za spajanje na API, možete uzeti bilo koji sdk iz dokumentacije https://github.com/Tinkoff/investAPI#sdk . Ili npm paket ” tinkoff-sdk-grpc-js “. Važno je da programeri ažuriraju paket na najnoviju verziju. Instalirati

npm i tinkoff-sdk-grpc-js

Provjeravanje

const { createSdk } = require(‘tinkoff-sdk-grpc-js’);   // Token koji se može dobiti ovako  const TOKEN = ‘YOURAPI’;   // Naziv aplikacije po kojoj vas je moguće pronaći u TCS zapisima. const appName = ‘tcsstat’;   const sdk = createSdk(TOKEN, appName); (async () => {     console.log(await sdk.users.getAccounts()); })();

Rezultat: na konzoli će se prikazati popis vaših računa. Na primjer, analizirajmo nijanse:Razvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju rada s brokerskim izvješćima i izračun provizija.

  • Na popisu računa nalazi se “Investicijska banka”, s kojom ne možete raditi pomoću API-ja
  • Imajte na umu da polja dolaze u camelCase formatu, dok su u dokumentaciji ova polja prikazana u under_score. 
  • Tako će biti svugdje, tako da ne možete samo uzeti i kopirati polje iz dokumentacije.

Koristan:

  • Ovaj kod možete pronaći u ogranku projekta

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

Crtanje podataka iz Tinkoff Invest API-ja u pregledniku

Uzeo sam next.js i socket.io. Ovo nije jaka preporuka, odaberite po vlastitom nahođenju. 

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

Odmah prelazimo na korak prijateljstva next+socket+investapi i pogledajte odjeljak Korisno ovog koraka za sve detalje.  Opisat ću detalje: 

  • Na nodejs (poslužiteljskoj) strani nalazi se datoteka pages/api/investapi.js. Ovdje kreiramo socket.io server i spajamo se na investapi.
  • Na strani preglednika (klijenta), spajamo se na poslužitelj putem utičnice i tražimo podatke o računu od brokera. 
  • Podatke primamo od brokera na serveru, zatim ih šaljemo klijentu. Kada ih primi klijent, prikazuju se u pregledniku. 

Rezultat:  u konzoli preglednika možemo vidjeti podatke o računima. Odnosno, u zadnjem koraku vidjeli smo informacije o računima u konzoli poslužitelja (nodejs), u trenutnom koraku smo te informacije prenijeli na klijenta (preglednik).

Razvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju rada s brokerskim izvješćima i izračun provizija.

Sada napravimo tako da možete odabrati račun iz preglednika, a ako nema tokena, šalje se pogreška na konzolu. Rad je jednostavan i ništa novo, pa dajem samo linkove na komitove

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

Koristan:

  • Ovdje je detaljno opisano kako napraviti prijatelje pored i utičnicu
  • Kod prijateljstva next+socket+investapi:

https://github.com/pskucherov/tcsstat/commit/a443a4ac1bb4f0aa898f638128755fe7391ee381 Kome je gore navedeno teško, ostajemo u ovoj fazi i bavimo se kodom. Ako imate pitanja – pitajte. https://github.com/pskucherov/tcsstat/tree/step2 https://github.com/pskucherov/tcsstat/compare/step1…step2

Primanje brokerskih izvješća i transakcija

Postoje tri metode za primanje brokerskih izvješća i transakcija

  1. GetBrokerReport
  2. GetDividendsForeignIssuer
  3. GetOperationsByCursor

Od samog početka važno je znati: 

  • Brokersko izvješće se generira u T-3 modu, tj. trgovine se tamo prikazuju nakon njihovog stvarnog izvršenja. 
  • Sukladno tome, ako tražite ovaj izvještaj za posljednja dva dana, bit će spreman za tri dana. 
  • Da bismo dobili transakcije za posljednje dane, koristimo metodu za primanje transakcija, ali zapamtite da se njihov ID i sadržaj mogu promijeniti nakon generiranja brokerskog izvješća.

GetBrokerReport

Da biste dobili brokersko izvješće, morate uzeti ID računa, datum početka i datum završetka izvješća, ali ne više od 31 dana. Šaljemo zahtjev za generiranje izvješća API-ju u generiranju _broker_report_requesta , dobivamo taskId kao odgovor. Nakon toga, koristeći ovaj taskId, dobivamo podatke iz get _broker_report_response.

Dakle, dokumentacija kaže, u stvarnosti postoje nijanse. Pazite na ruke:
  • Morate zauvijek spremiti TaskID točno za ove datume. 
  • Budući da ako ga izgubite, tada će za tražene datume izvješće prvo doći kao odgovor na zahtjev za generiranje, 
  • A onda uopće neće doći.
Počnimo pisati kod

Metoda dobivanja datuma, uzimajući u obzir oduzimanje od tekućeg datuma

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

Zahtjev za generiranje izvješća 

const brokerReport = čekaj (sdk.operations.getBrokerReport)({         generirajBrokerReportRequest: {             accountId,             from,             to,         }, });

Proizlaziti:

  • Kao rezultat prvog izvršavanja naredbe dobivamo taskId. 
  • Izvješće se počinje generirati na strani brokera. Nije poznato kada je spreman, čekamo i povremeno povlačimo taskId u iščekivanju izvješća.
  • Zašto? Jer ako izvješće nije spremno, javlja se pogreška. Ako izvješće nije spremno na strani brokera, to je pogreška u vašem kodu. Obradite: 30058|INVALID_ARGUMENT|zadatak još nije dovršen, pokušajte ponovno kasnije

Kod za čekanje i primanje izvješća izgleda otprilike ovako.

const timer = async time => {     return new Promise(resolve => setTimeout(resolve, time)); }   const getBrokerResponseByTaskId = async (taskId, page = 0) => {     try {         return await (sdk.operations.getBrokerReport)({             getBrokerReportRequest: {                 taskId,                 page,             },         });     } catch (e) {         console.log(‘wait’, e);         mjerač čekanja (10000);         return await getBrokerResponseByTaskId(taskId, stranica);     } };

Tada se događa ista magija. Zaustavljamo našu skriptu, pokrećemo je ponovno, nemamo taskId. Izvršavamo kod sa taskId zahtjevom, ali više ne dobivamo taskId, nego odmah izvještaj. Magija! I sve bi bilo u redu da je uvijek ovako. Ali za mjesec dana neće biti nikakvih podataka. Korisno :

  • Malo teorije izneseno je ovdje i ovdje .
  • Sastavljanjem koda, nacrt će izgledati otprilike ovako.

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

  • Ako netko naiđe na ovo, onda dobrodošao u problem . Nakon što poprave ovu magiju, ona će izgubiti snagu i bit će nekako drugačija. Ali u trenutnom trenutku (21.3.2023.) radi baš tako.

GetDividendsForeignIssuer

Netko bi mogao pomisliti da je metoda slična prethodnoj i da možete koristiti jednu metodu u kojoj samo mijenjate nazive operacija. Ali nisu pogodili!  Imenovanje je vrlo različito iu metodama iu vraćenim informacijama. I broj stranica počinje od 0, pa od 1. Da se ne bi zabunili u svemu tome, lakše je napisati dvije različite metode. Što je čudno, jer logika rada je ista. Dugo sam pljuvao kad sam pokušao napraviti jednu metodu i bilo je manje koda. Ovdje neće biti primjera.

GetOperationsByCursor

Moj favorit od njih tri. Iako ne najprecizniji, ali najadekvatniji. Zahtjev vršimo od početka kreiranja računa do maksimalno mogućeg datuma (zatvaranje računa ili tekućeg). Dobivamo odgovor, uzimamo kursor i ponovno tražimo sve dok ima podataka.  A kôd je koncizniji nego u gornjim primjerima.

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

Nacrt za pokretanje je ovdje: https://github.com/pskucherov/tcsstat/tree/step3.3 https://github.com/pskucherov/tcsstat/compare/step3.3 Sada smo spremni dodati operacije primanja u našu aplikaciju. Ako je učinjeno ispravno, tada morate dobiti brokerska izvješća za cijelo postojanje računa. A za podatke koji nedostaju, ti isti T-3, ponovno učitavanje iz operacija. Ali to se može izdvojiti u poseban članak. Od glavnih nijansi s kojima ćete se susresti je spajanje operacija i brokerskog izvješća.

  •  Ako ste danas dobili brokersko izvješće i transakcije za tražene datume, sve to stavite u bazu, onda nema problema. 
  • Probleme ćete imati sutra kada dobijete sljedeću porciju podataka iz izvješća i poslovanja i odlučite ih sinkronizirati s postojećom bazom. 
  • Puno nijansi o nepodudaranju ili promjeni ID-a nakon obrade
  • Onda za OTC tržište, id-ovi se uopće ne podudaraju.
  •  Kao i nijanse sinkronizacije instrumenata, koje se opet ne podudaraju, zbog osobitosti API-ja. Ali to je druga priča.

Dodajmo našoj aplikaciji dobivanje informacija o operacijama. Glavno pitanje bit će gdje će se podaci obrađivati ​​i pohranjivati.

  •  Ako to radite za sebe, trošit ćete iste podatke s različitih uređaja. Zatim trebate obraditi i pohraniti podatke na poslužitelj.
  • Ako imate puno različitih podataka koje konzumira mnogo različitih korisnika, tada morate odlučiti što je važnije: brzina korisnika ili ušteda željeza na vašoj strani. Tko god si može priuštiti beskonačnu količinu hardvera, sve broji na svom serveru i čini ga super brzim za korisnike, štedeći korisničke resurse, poput baterije i prometa, što je jako bitno na telefonima.

Zauzvrat, brojanje u pregledniku u načelu nije najoptimalnije rješenje. Stoga ono što nije skupo smatramo na našem poslužitelju. Ostalo prepuštamo klijentu. Stvarno želim uzeti i izračunati proviziju na serveru. Ali ovdje dolazi nijansa zvana “interaktivnost”. Recimo da imate tisuće operacija i potrebno je pet minuta da ih primite. Što će korisnik imati u ovom trenutku? Spinner? Napredak? Informacije o tome koliko je uploadano? Idealno je koristiti “aktivno čekanje” kada korisnik u procesu već može nešto vidjeti. Evo rezultata:Razvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju rada s brokerskim izvješćima i izračun provizija.

  • Stranica se učitava
  • Sve fakture su tražene
  • Nakon toga se za sve račune traže sve transakcije s provizijama za izvršene transakcije. Kako se podaci primaju, oni se prikazuju u pregledniku.

Kako ne bismo svaki put filtrirali podatke u događajima, povlačimo vlastiti događaj za svaki račun. Kao ovo:

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

Nacrt za pokretanje je ovdje: https://github.com/pskucherov/tcsstat/tree/step3 https://github.com/pskucherov/tcsstat/compare/step2…step3 Idemo dalje. Sjajno je što ste pročitali ovaj redak! 

Izračun i izlaz informacija od interesa

Ovisi kome koja informacija treba. Stoga vam odmah kažem glavne nijanse s kojima ćete se susresti.

Rad s cijenama 

Svi koji se bave financijama znaju da se novčane transakcije smiju obavljati samo s cijelim brojevima. Zbog netočnosti vrijednosti iza decimalne točke i kumulativne pogreške s velikim brojem operacija. Zbog toga su sve cijene prikazane u sljedećem MoneyValue formatuRazvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju rada s brokerskim izvješćima i izračun provizija.

poljetipOpis
valutanizString ISO kod valute
jediniceint64Cjelobrojni dio zbroja, može biti negativan broj
nanoint32Razlomak iznosa, može biti negativan broj

Posebno ih obrađujemo, a zatim dovodimo do cjenovne vrijednosti:

kotacija.jedinice + kotacija.nano / 1e9

Trošak terminskih ugovora

Cijena fjučersa prikazana je u bodovima, kada imate valutni fjučers, morate znati stopu. I naravno cijena u bodovima i cjenovni korak. Kada izračunate dobit od transakcija, ovo može pucati, jer. ako ukupni iznos izračunate množenjem cijene s količinom. Ovdje morate biti oprezni. Za sada ćemo vidjeti kako će ići. Ovo se odnosi na valutne fjučerse, na drugim mjestima s ovim je sve u redu.Razvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju rada s brokerskim izvješćima i izračun provizija.Razvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju rada s brokerskim izvješćima i izračun provizija.

OTC tržište

Ovo tržište ima puno posebnosti, pa proučimo operacije na njemu posebno.Kada počnete sinkronizirati operacije, ispostavit će se da trebate dovesti figi / ticker u isti oblik kako biste ispravno uskladili instrument. Kada to počnete sinkronizirati s brokerskim izvješćem, ispostavit će se da tradeID iste transakcije ima slova na početku u transakcijama, a nema ih u brokerskom izvješću. Stoga se ne mogu uspoređivati ​​… ajme-ajme … usporedbom! Usporedio sam vrijeme trgovine, ticker i podudaranje da je jedan tradeId sadržan u drugom. Da, ne znam. Tko se s tim susreće i kome je stalo do toga, neka dođe na broj ili započne novi.Razvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju rada s brokerskim izvješćima i izračun provizija.

Matematičke operacije na alatima

Nemoguće je, bez gledanja, izvesti matematičke operacije s cijelim popisom. Kako ne bismo dodavali toplo na meko, uvijek provjeravamo valutu i obrađujemo samo ako smo sigurni da valuta odgovara, a bodovi se pretvaraju u željenu valutu. Naoružani znanjem o radu s bankovnim brojevima, izračunat ćemo proviziju potrošenu na svakom od računa. Ovako: https://github.com/pskucherov/tcsstat/tree/step4 https://github.com/pskucherov/tcsstat/compare/step3…step4Razvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju rada s brokerskim izvješćima i izračun provizija.   

Mikroservis je spreman!

https://github.com/pskucherov/tcsstat Kao domaću zadaću možete provjeriti radi li usluga sa sporom vezom, kada su veze prekinute, kada je internet prekinut, kada su pogreške ili istekli limiti od strane brokera. 

Zaključci i planovi za budućnost

  • Naučili o osnovnim operacijama i radu s Invest API-jem
  • Utrošeno vrijeme ~ 10 sati
  • Razina težine ~ junior+ / niska srednja 

Ako nastavite usavršavati mikroservis, mogli biste završiti s nečim ovakvim

https://opexbot.info

  Ovo je moj razvoj, za one koji su previše lijeni da razumiju, trče i računaju sami. Planiram tamo dodati analitiku na zahtjev korisnika. Ako vam se članak svidio, pretplatite se na moj telegram kanal . Razvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju rada s brokerskim izvješćima i izračun provizija.

Pavel
Rate author
Add a comment

  1. Isakiiev

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

    Reply