Razvijamo mikrostoritev z uporabo Tinkoff Invest API za avtomatizacijo dela s posredniškimi poročili in izračunavanjem provizij.

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

Navdihniki za razvoj statistične storitve za Tinkoff Investments so bili:

O čem se bo razpravljalo?

  • Samo aplikativni del o razvoju.
  • Pravo znanje in izkušnje, ki so zelo pomembne pri delu s finančnimi instrumenti.
  • Pregled vprašanj, na katerih je treba delati

Torej želim izračunati trgovinsko statistiko in to narediti na priročen način. 

Razvoj statistične storitve korak za korakom: 

  1. Povezava z API-jem Tinkoff Invest
  2. Črpanje podatkov iz Tinkoff Invest API v brskalniku
  3. Prejemanje posredniških poročil in transakcij
  4. Izračun in izpis zanimivih informacij
  5. Zaključki in načrti za prihodnost

Povezava z API-jem Tinkoff Invest

Za povezavo z API-jem lahko vzamete kateri koli sdk iz dokumentacije https://github.com/Tinkoff/investAPI#sdk . Ali paket npm ` tinkoff-sdk-grpc-js` . Pomembno je, da razvijalci paket posodobijo na najnovejšo različico. Namestite

npm in tinkoff-sdk-grpc-js

Preverjanje

const { createSdk } = require(‘tinkoff-sdk-grpc-js’);   // Žeton, ki ga je mogoče pridobiti na ta način  const TOKEN = ‘YOURAPI’;   // Ime aplikacije, po kateri vas je mogoče najti v dnevnikih TCS. const appName = ‘tcsstat’;   const sdk = createSdk(TOKEN, appName); (async () => {     console.log(await sdk.users.getAccounts()); })();

Rezultat: v konzoli bo prikazan seznam vaših računov. Na primer, analizirajmo nianse:Razvijamo mikrostoritev z uporabo Tinkoff Invest API za avtomatizacijo dela s posredniškimi poročili in izračunavanjem provizij.

  • Na seznamu računov je »Investicijska banka«, s katero ne morete delati z uporabo API-ja
  • Upoštevajte, da so polja v obliki camelCase, medtem ko so v dokumentaciji ta polja predstavljena v under_score. 
  • Povsod bo tako, zato ne morete kar vzeti in kopirati polja iz dokumentacije.

Uporabno:

  • To kodo najdete v veji projekta

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

Črpanje podatkov iz Tinkoff Invest API v brskalniku

Vzel sem next.js in socket.io. To ni močno priporočilo, izberite po lastni presoji. 

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

Takoj nadaljujemo s korakom prijateljstva next+socket+investapi in si za vse podrobnosti  oglejte razdelek Uporabno tega koraka. Opisal bom podrobnosti: 

  • Na strani nodejs (strežnik) je datoteka pages/api/investapi.js. Tukaj ustvarimo strežnik socket.io in se povežemo z investapi.
  • Na strani brskalnika (odjemalca) se prek vtičnice povežemo s strežnikom in od posrednika zahtevamo podatke o računu. 
  • Podatke prejmemo od posrednika na strežniku, nato pa jih pošljemo stranki. Ko jih prejme odjemalec, se prikažejo v brskalniku. 

Rezultat:  v konzoli brskalnika lahko vidimo podatke o računih. Se pravi, da smo v zadnjem koraku videli podatke o računih v strežniški konzoli (nodejs), v trenutnem koraku smo te podatke prenesli v odjemalca (brskalnik).

Razvijamo mikrostoritev z uporabo Tinkoff Invest API za avtomatizacijo dela s posredniškimi poročili in izračunavanjem provizij.

Zdaj pa naredimo tako, da lahko izberete račun iz brskalnika in če ni žetona, se na konzolo pošlje napaka. Delo je preprosto in nič novega, zato dajem le povezave do komitov

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

Uporabno:

  • Kako se spoprijateljiti z naslednjim in vtičnico, je podrobno opisano tukaj
  • Koda prijateljstva next+socket+investapi:

https://github.com/pskucherov/tcsstat/commit/a443a4ac1bb4f0aa898f638128755fe7391ee381 Za tiste, ki jim je zgornje težko, ostanemo na tej stopnji in se ukvarjamo s kodo. Če imate vprašanja – vprašajte. https://github.com/pskucherov/tcsstat/tree/step2 https://github.com/pskucherov/tcsstat/compare/step1…step2

Prejemanje posredniških poročil in transakcij

Obstajajo trije načini za prejemanje posredniških poročil in transakcij

  1. GetBrokerReport
  2. GetDividendsForeignIssuer
  3. GetOperationsByCursor

Že od samega začetka je pomembno vedeti: 

  • Borzno poročilo se ustvari v načinu T-3, t.j. posli so tam prikazani po njihovi dejanski izvedbi. 
  • V skladu s tem, če zahtevate to poročilo za zadnja dva dni, bo pripravljeno v treh dneh. 
  • Za pridobitev transakcij za zadnje dni uporabljamo metodo za prejemanje transakcij, vendar ne pozabite, da se lahko njihov ID in vsebina spremenita, ko je ustvarjeno posredniško poročilo.

GetBrokerReport

Če želite pridobiti posredniško poročilo, morate vzeti ID računa, začetni in končni datum poročila, vendar ne več kot 31 dni. API-ju pošljemo zahtevo za ustvarjanje poročila v create _broker_report_request , v odgovor prejmemo taskId. Nato z uporabo tega taskId pridobimo podatke iz get _broker_report_response.

Tako pravi dokumentacija, v resnici obstajajo nianse. Pazite na roke:
  • Natančno za te datume morate za vedno shraniti TaskID. 
  • Ker če ga izgubite, bo poročilo za zahtevane datume najprej prišlo kot odgovor na zahtevo za generiranje, 
  • In potem sploh ne pride.
Začnimo pisati kodo

Metoda za pridobitev datuma z upoštevanjem odštevanja od trenutnega datuma

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

Zahteva za ustvarjanje poročila 

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

rezultat:

  • Kot rezultat prve izvedbe ukaza dobimo taskId. 
  • Poročilo se začne generirati na strani posrednika. Ko je pripravljen, ni znano, čakamo in občasno potegnemo taskId v pričakovanju poročila.
  • Zakaj? Ker če poročilo ni pripravljeno, vrže napako. Če poročilo ni pripravljeno na strani posrednika, je to napaka v vaši kodi. Obdelajte: 30058|INVALID_ARGUMENT|opravilo še ni dokončano, poskusite znova pozneje

Koda za čakanje in prejem poročila izgleda nekako takole.

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);         čakalni časovnik (10000);         return await getBrokerResponseByTaskId(taskId, stran);     } };

Potem se zgodi ista čarovnija. Ustavimo naš skript, ga znova zaženemo, nimamo TaskId. Izvedemo kodo z zahtevo taskId, vendar ne dobimo več taskId, ampak takoj poročilo. Čarovnija! In vse bi bilo v redu, če bi bilo vedno tako. Čez en mesec pa podatkov sploh ne bo. Uporabno :

  • Nekaj ​​teorije je opisanega tukaj in tukaj .
  • Če kodo sestavimo, bo osnutek videti nekako takole.

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

  • Če kdo naleti na to, potem dobrodošli v temi . Ko popravijo to magijo, bo izgubila svojo moč in bo nekako drugačna. A v tem trenutku (21.3.2023) deluje ravno tako.

GetDividendsForeignIssuer

Nekdo bi lahko mislil, da je metoda podobna prejšnji in lahko uporabite eno samo metodo, v kateri spremenite samo ime operacij. A niso uganili!  Poimenovanje se zelo razlikuje tako v metodah kot v vrnjenih informacijah. In štetje strani se začne od 0, nato od 1. Da se ne bi zmedli pri vsem tem, je lažje napisati dve različni metodi. Kar je čudno, saj logika dela je enaka. Dolgo sem pljuval, ko sem poskušal narediti eno metodo in je bilo manj kode. Tu ne bo primerov.

GetOperationsByCursor

Moja najljubša od treh. Čeprav ni najbolj natančen, vendar najbolj primeren. Zahtevo izvajamo od začetka ustvarjanja računa do najdaljšega možnega datuma (zaprtje računa ali tekočega). Dobimo odgovor, vzamemo kazalec in ponovno zahtevamo, dokler so podatki.  In koda je bolj jedrnata kot v zgornjih primerih.

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 = ”);     } };

Osnutek za zagon je tukaj: https://github.com/pskucherov/tcsstat/tree/step3.3 https://github.com/pskucherov/tcsstat/compare/step3.3 Zdaj smo pripravljeni dodati operacije prejemanja v našo aplikacijo. Če je opravljeno pravilno, potem morate pridobiti posredniška poročila za celoten obstoj računa. In za manjkajoče podatke, isti T-3, znova naložite iz operacij. Toda to je mogoče ločiti v ločenem članku. Od glavnih odtenkov, s katerimi se boste srečali, je povezovanje operacij in posredniškega poročila.

  •  Če ste danes prejeli posredniško poročilo in transakcije za zahtevane datume, vse to vnesite v bazo, potem ni težav. 
  • Težave boste imeli jutri, ko boste prejeli naslednji del podatkov iz poročila in poslovanja ter se odločili, da jih sinhronizirate z obstoječo bazo. 
  • Veliko nians glede neusklajenega ali spreminjanja ID-ja po obdelavi
  • Za OTC trg se id-ji sploh ne ujemajo.
  •  Kot tudi nianse sinhronizacije instrumentov, ki spet ne sovpadajo zaradi posebnosti API-ja. Toda to je druga zgodba.

Dodajmo naši aplikaciji pridobivanje informacij o operacijah. Glavno vprašanje bo, kje se bodo podatki obdelovali in shranjevali.

  •  Če to storite zase, boste porabili iste podatke iz različnih naprav. Nato morate podatke obdelati in shraniti na strežnik.
  • Če imate veliko različnih podatkov, ki jih porabi veliko različnih uporabnikov, potem se morate odločiti, kaj je bolj pomembno: hitrost uporabnikov ali prihranek železa na vaši strani. Kdor si lahko privošči neskončno veliko strojne opreme, šteje vse na svojem strežniku in uporabnikom naredi super hitro ter prihrani uporabniška sredstva, kot sta baterija in promet, kar je na telefonih zelo pomembno.

Po drugi strani pa štetje v brskalniku načeloma ni najbolj optimalna rešitev. Torej, kar ni drago, upoštevamo na našem strežniku. Ostalo prepustimo naročniku. Resnično želim vzeti in izračunati provizijo na strežniku. Toda tu se pojavi odtenek, imenovan »interaktivnost«. Recimo, da imate na tisoče operacij in traja pet minut, da jih prejmete. Kaj bo imel uporabnik v tem trenutku? Spinner? Napredek? Infa o tem, koliko je bilo naloženo? Idealno je uporabiti “aktivno čakanje”, ko uporabnik v procesu že lahko nekaj vidi. Tukaj je rezultat:Razvijamo mikrostoritev z uporabo Tinkoff Invest API za avtomatizacijo dela s posredniškimi poročili in izračunavanjem provizij.

  • Nalaganje strani
  • Vsi računi so zahtevani
  • Nato se za vse račune zahtevajo vse transakcije s provizijami za izvršene transakcije. Ko so podatki prejeti, se upodobijo v brskalniku.

Da ne bi vsakič filtrirali podatkov v dogodkih, za vsak račun potegnemo svoj dogodek. Všečkaj to:

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

Osnutek za lansiranje je tukaj: https://github.com/pskucherov/tcsstat/tree/step3 https://github.com/pskucherov/tcsstat/compare/step2…step3 Nadaljujemo. Super je, da ste prebrali to vrstico! 

Izračun in izpis zanimivih informacij

Odvisno od tega, kdo potrebuje kakšne informacije. Zato vam takoj povem glavne nianse, s katerimi se boste srečali.

Delo s cenami 

Vsi, ki se ukvarjajo s financami, vedo, da je treba denarne transakcije izvajati samo s celimi števili. Zaradi netočnosti vrednosti za decimalno vejico in kumulativne napake pri velikem številu operacij. Zato so vse cene predstavljene v naslednjem formatu MoneyValueRazvijamo mikrostoritev z uporabo Tinkoff Invest API za avtomatizacijo dela s posredniškimi poročili in izračunavanjem provizij.

poljevrstaOpis
valutavrvicaNiz kode valute ISO
enoteint64Celo število vsote je lahko negativno število
nanoint32Ulomek zneska je lahko negativno število

Obdelamo jih posebej, nato jih pripeljemo do cenovne vrednosti:

kotacija.enote + kotacija.nano / 1e9

Stroški terminskih pogodb

Cena terminskih pogodb je predstavljena v točkah, ko imate valutno terminsko pogodbo, morate poznati tečaj. In seveda cena v točkah in cenovni korak. Ko računate dobiček iz transakcij, lahko to izstreli, saj. če izračunate skupni znesek tako, da pomnožite ceno s količino. Tukaj morate biti previdni. Zaenkrat bomo videli, kako bo. To velja za valutne terminske pogodbe, drugje je s tem vse v redu.Razvijamo mikrostoritev z uporabo Tinkoff Invest API za avtomatizacijo dela s posredniškimi poročili in izračunavanjem provizij.Razvijamo mikrostoritev z uporabo Tinkoff Invest API za avtomatizacijo dela s posredniškimi poročili in izračunavanjem provizij.

OTC trg

Ta trg ima veliko posebnosti, zato preučimo operacije na njem ločeno.Ko začnete sinhronizirati operacije, se bo izkazalo, da morate figi / ticker prinesti v isto obliko, da se pravilno ujema z instrumentom. Ko začnete to sinhronizirati s poročilom o posredovanju, se bo izkazalo, da ima tradeID iste transakcije črke na začetku v transakcijah in jih ni v poročilu o posredovanju. Zato jih ni mogoče primerjati … ah-ah … s primerjavo! Ujemal sem čas trgovanja, oznako in ujemanje, da je en tradeId vsebovan v drugem. Prav, ne vem. Kdor se s tem srečuje in ga to zanima, naj pride na temo ali začne novo.Razvijamo mikrostoritev z uporabo Tinkoff Invest API za avtomatizacijo dela s posredniškimi poročili in izračunavanjem provizij.

Matematične operacije na orodjih

Brez pogleda je nemogoče izvesti matematične operacije s celotnim seznamom. Da ne dodajamo toplo k mehkemu, vedno preverimo valuto in obdelamo le, če smo prepričani, da se valuta ujema, in točke pretvorimo v želeno valuto. Oboroženi z znanjem o delu z bančnimi številkami bomo izračunali provizijo, porabljeno za vsakega od računov. Takole: https://github.com/pskucherov/tcsstat/tree/step4 https://github.com/pskucherov/tcsstat/compare/step3…step4Razvijamo mikrostoritev z uporabo Tinkoff Invest API za avtomatizacijo dela s posredniškimi poročili in izračunavanjem provizij.   

Mikroservis je pripravljen!

https://github.com/pskucherov/tcsstat Kot domačo nalogo lahko preverite, ali storitev deluje s počasno povezavo, ko so povezave prekinjene, ko je internetna povezava prekinjena, ko so napake ali potekle omejitve s strani posrednika. 

Zaključki in načrti za prihodnost

  • Spoznal osnovne operacije in delo z API-jem Invest
  • Porabljen čas ~ 10 ur
  • Težavnostna stopnja ~ junior+ / nizka srednja 

Če nadaljujete z izpopolnjevanjem mikrostoritve, lahko na koncu dobite nekaj takega

https://opexbot.info

  To je moj razvoj, za tiste, ki so preleni, da bi razumeli, tekali in računali sami. Tam nameravam dodati analitiko na zahtevo uporabnikov. Če vam je bil članek všeč, se naročite na moj telegram kanal . Razvijamo mikrostoritev z uporabo Tinkoff Invest API za avtomatizacijo dela s posredniškimi poročili in izračunavanjem provizij.

Pavel
Rate author
Add a comment

  1. Isakiiev

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

    Reply