Razvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju brokerskih izvještaja i obračuna provizije.

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

Inspiratori za razvoj statističkog servisa za Tinkoff Investments bili su:

O čemu će se raspravljati?

  • Samo primijenjeni dio o razvoju.
  • Pravo znanje i iskustvo, koji su veoma važni u radu sa finansijskim instrumentima.
  • Pregled problema na kojima treba raditi

Dakle, želim da izračunam trgovinsku statistiku i da to uradim na zgodan način. 

Razvoj statističkog servisa korak po korak: 

  1. Veza na Tinkoff Invest API
  2. Crtanje podataka iz Tinkoff Invest API-ja u pretraživaču
  3. Primanje brokerskih izvještaja i transakcija
  4. Izračunavanje i izlaz informacija od interesa
  5. Zaključci i planovi za budućnost

Veza na Tinkoff Invest API

Da biste se povezali 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. Instaliraj

npm i tinkoff-sdk-grpc-js

Provjeravam

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

Rezultat: lista vaših naloga će biti prikazana na konzoli. Na primjer, analizirajmo nijanse:Razvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju brokerskih izvještaja i obračuna provizije.

  • Na listi računa nalazi se „Investiciona banka“ sa kojom ne možete raditi koristeći API
  • Imajte na umu da polja dolaze u CamelCase-u, dok su u dokumentaciji ova polja prikazana u under_score. 
  • Tako će biti svuda, tako da ne možete samo uzeti i kopirati polje iz dokumentacije.

Korisno:

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

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

Crtanje podataka iz Tinkoff Invest API-ja u pretraživaču

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

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

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

  • Na strani nodejs (server) nalazi se datoteka pages/api/investapi.js. Ovdje kreiramo socket.io server i povezujemo se na investapi.
  • Na strani pretraživača (klijenta) povezujemo se sa serverom preko socketa i tražimo podatke o računu od brokera. 
  • Podatke od brokera primamo na server, a zatim ih šaljemo klijentu. Kada ih primi klijent, oni se prikazuju u pretraživaču. 

Rezultat:  u konzoli pretraživača možemo vidjeti informacije o nalozima. Odnosno, u poslednjem koraku smo videli informacije o nalozima u konzoli servera (nodejs), u trenutnom koraku smo te informacije preneli na klijenta (pretraživač).

Razvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju brokerskih izvještaja i obračuna provizije.

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

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

Korisno:

  • Kako steći prijatelje i utičnicu je detaljno opisano ovdje
  • Šifra 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štaja i transakcija

Postoje tri načina za primanje brokerskih izvještaja i transakcija

  1. GetBrokerReport
  2. GetDividendsForeignIssuer
  3. GetOperationsByCursor

Od samog početka važno je znati: 

  • Brokerski izvještaj se generiše u T-3 modu, tj. trgovine se tamo prikazuju nakon njihovog stvarnog izvršenja. 
  • Shodno tome, ako zatražite ovaj izvještaj za posljednja dva dana, on će biti gotov za tri dana. 
  • Za sklapanje poslova za posljednje dane koristimo metodu za primanje operacija, ali imajte na umu da se njihov ID i sadržaj mogu promijeniti nakon formiranja brokerskog izvještaja.

GetBrokerReport

Da biste dobili brokerski izvještaj, potrebno je uzeti ID računa, datum početka i datum završetka izvještaja, ali ne duže od 31 dan. Šaljemo zahtjev za generiranje izvještaja API-ju u generiranju _broker_report_request , dobijamo taskId kao odgovor. Nakon toga, koristeći ovaj taskId, dobijamo podatke iz get _broker_report_response.

Tako dokumentacija kaže, u stvarnosti postoje nijanse. Pazite ruke:

  • Za ove datume morate zauvijek sačuvati TaskID. 
  • Pošto ako ga izgubite, onda će za tražene datume izvještaj prvo doći kao odgovor na zahtjev za generiranje, 
  • A onda uopšte neće doći.

Počnimo pisati kod

Metoda za dobijanje datuma, uzimajući u obzir oduzimanje od trenutnog datuma

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

Zahtjev za generiranje izvještaja 

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

rezultat:

  • Kao rezultat prvog izvršavanja naredbe, dobijamo taskId. 
  • Izvještaj počinje da se generiše na strani brokera. Kada je spreman nije poznato, čekamo i periodično povlačimo taskId u iščekivanju izvještaja.
  • Zašto? Jer ako izvještaj nije spreman, javlja se greška. Ako izvještaj nije spreman na strani brokera, onda je ovo greška u vašem kodu. Obradite: 30058|INVALID_ARGUMENT|zadatak još nije završen, pokušajte ponovo kasnije

Kod za čekanje i prijem izvještaja izgleda otprilike ovako.

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

Tada se dešava ista magija. Zaustavljamo našu skriptu, pokrećemo je ponovo, nemamo taskId. Izvršavamo kod sa zahtjevom taskId, ali više ne dobijamo taskId, već odmah izvještaj. Magic! I sve bi bilo u redu da je uvijek ovako. Ali za mjesec dana neće biti nikakvih podataka. Korisno :

  • Malo teorije je izloženo ovdje i ovdje .
  • Stavljajući kod zajedno, nacrt će izgledati otprilike ovako.

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

  • Ako neko naiđe na ovo, dobrodošli u temu . Nakon što poprave ovu magiju, ona će izgubiti snagu i bit će nekako drugačija. Ali u sadašnjem trenutku (21.03.2023.) radi baš tako.

GetDividendsForeignIssuer

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

GetOperationsByCursor

Moj favorit od tri. Iako ne najtačniji, ali najadekvatniji. Zahtjev pravimo od početka kreiranja računa do maksimalnog mogućeg datuma (zatvaranje računa ili tekućeg). Dobijamo odgovor, uzimamo kursor i ponovo tražimo sve dok postoje podaci.  I kod je sažetiji nego u primjerima iznad.

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,             bezCommissions: false,             beztrgovina: lažno,             bez noćenja: lažno,             kursor,         };           return await sdk.operations.getOperationsByCursor(reqData);     } catch (e) {         tajmer čekanja (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 za dodavanje operacija prijema u našu aplikaciju. Ako je urađeno ispravno, onda morate dobiti brokerske izvještaje za cijelo postojanje računa. A za podatke koji nedostaju, te iste T-3, ponovo učitajte iz operacija. Ali ovo se može izdvojiti u poseban članak. Od glavnih nijansi na koje ćete se susresti je ljepljenje operacija i brokerski izvještaj.

  •  Ako ste danas dobili brokerski izvještaj i transakcije za tražene datume, sve to stavite u bazu podataka, onda nema problema. 
  • Sutra ćete imati problema kada dobijete sljedeći dio podataka iz izvještaja i operacija i odlučite ih sinkronizirati sa postojećom bazom podataka. 
  • Mnogo nijansi o neusklađenim ili promjeni ID-a nakon obrade
  • Onda za OTC tržište, id-ovi se uopće ne poklapaju.
  •  Kao i nijanse sinkronizirajućih instrumenata, koje se opet ne poklapaju, zbog specifičnosti API-ja. Ali to je druga priča.

Dodajmo dobijanje informacija o operacijama našoj aplikaciji. Glavno pitanje će biti gdje će se podaci obrađivati ​​i čuvati.

  •  Ako to učinite za sebe, potrošit ćete iste podatke s različitih uređaja. Zatim morate obraditi i pohraniti podatke na server.
  • Ako imate mnogo različitih podataka koje troše mnogo različitih korisnika, onda morate odlučiti što je važnije: brzina korisnika ili ušteda željeza na vašoj strani. Ko može priuštiti beskonačnu količinu hardvera, broji sve na svom serveru i čini ga super brzim za korisnike, štedeći korisničke resurse, poput baterije i saobraćaja, što je veoma važno na telefonima.

Zauzvrat, brojanje u pretraživaču u principu nije najoptimalnije rješenje. Dakle, ono što nije skupo smatramo na našem serveru. Ostalo prepuštamo klijentu. Zaista želim uzeti i izračunati proviziju na serveru. Ali ovdje dolazi do nijanse koja se zove “interaktivnost”. Recimo da imate hiljade operacija i potrebno vam je pet minuta da ih primite. Šta će korisnik imati u ovom trenutku? Spinner? Napredak? Infa o tome koliko je postavljeno? 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 brokerskih izvještaja i obračuna provizije.

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

Kako ne bismo svaki put filtrirali podatke u događajima, povlačimo vlastiti događaj za svaki račun. Volim 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. Divno je što ste pročitali ovaj red! 

Izračunavanje i izlaz informacija od interesa

Zavisi kome su potrebne informacije. Stoga vam odmah kažem glavne nijanse na koje ćete se susresti.

Rad sa cijenama 

Svi koji se bave finansijama znaju da se novčane transakcije trebaju obavljati samo cijelim brojevima. Zbog nepreciznosti vrijednosti nakon decimalnog zareza i kumulativne greške sa velikim brojem operacija. Zbog toga su sve cijene prikazane u sljedećem formatu MoneyValueRazvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju brokerskih izvještaja i obračuna provizije.

polje tip Opis
valuta string Niz ISO koda valute
jedinice int64 Cjelobrojni dio zbira, može biti negativan broj
nano int32 Razlomak iznosa, može biti negativan broj

Obrađujemo ih posebno, zatim ih dovodimo do cjenovne vrijednosti:

quotation.units + quotation.nano / 1e9

Troškovi fjučers ugovora

Cijena fjučersa je prikazana u bodovima, kada imate valutnu fjučersu, morate znati kurs. I naravno cijena u bodovima i korak cijene. Kada izračunate zaradu od transakcija, ovo može pucati, jer. ako ukupan iznos izračunate množenjem cijene sa količinom. Ovdje morate biti oprezni. Za sada ćemo vidjeti kako će biti. Ovo se odnosi na valutne fjučerse, na drugim mjestima je sve u redu s ovim.Razvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju brokerskih izvještaja i obračuna provizije. Razvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju brokerskih izvještaja i obračuna provizije.

OTC tržište

Ovo tržište ima dosta posebnosti, pa hajde da proučimo operacije na njemu odvojeno.Kada počnete da sinhronizujete operacije, ispostaviće se da je potrebno da dovedete sliku/tiker u isti oblik kako biste ispravno uskladili instrument. Kada počnete da sinhronizujete ovo sa brokerskim izveštajem, ispostaviće se da tradeID iste transakcije ima slova na početku u transakcijama i da ih nema u brokerskom izveštaju. Dakle, ne mogu se porediti… hm-hm… poređenjem! Upario sam vrijeme trgovine, ticker i podudaranje da je jedan tradeId sadržan u drugom. Dobro, ne znam. Ko naiđe na ovo i kome je stalo do toga, dođite do problema ili započnite novi.Razvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju brokerskih izvještaja i obračuna provizije.

Matematičke operacije nad alatima

Nemoguće je, bez gledanja, izvršiti matematičke operacije sa cijelom listom. Da ne bismo dodali toplo meko, uvijek provjeravamo valutu i obrađujemo samo ako smo sigurni da se valuta poklapa, a bodovi se konvertuju u željenu valutu. Naoružani znanjem o radu sa bankovnim brojevima, izračunać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 brokerskih izvještaja i obračuna provizije.    

Mikroservis je spreman!

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

Zaključci i planovi za budućnost

  • Naučio o osnovnim operacijama i radu sa Invest API-jem
  • Utrošeno vrijeme ~ 10 sati
  • Nivo težine ~ junior+ / niski srednji 

Ako nastavite da usavršavate mikroservis, mogli biste završiti s nečim poput ovoga

https://opexbot.info

  Ovo je moj razvoj, za one koji su previše lijeni da sami razumiju, trče i računaju. Planiram da dodam analitiku tamo na zahtjev korisnika. Ako vam se svidio članak, pretplatite se na moj telegram kanal . Razvijamo mikroservis koristeći Tinkoff Invest API za automatizaciju brokerskih izvještaja i obračuna provizije.

Pavel
Rate author
Add a comment

  1. Isakiiev

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

    Reply