Kuriame mikropaslaugą naudodami Tinkoff Invest API, skirtą automatizuoti darbą su tarpininkavimo ataskaitomis ir komisinių skaičiavimu.

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

„Tinkoff Investments“ statistikos tarnybos kūrimo įkvėpėjai buvo:

Kas bus aptariama?

  • Tik taikomoji dalis apie plėtrą.
  • Realios žinios ir patirtis, kurios labai svarbios dirbant su finansiniais instrumentais.
  • Problemų, kurias reikia spręsti, apžvalga

Taigi, noriu skaičiuoti prekybos statistiką ir tai padaryti patogiai. 

Statistikos paslaugos kūrimas žingsnis po žingsnio: 

  1. Prisijungimas prie Tinkoff Invest API
  2. Duomenų piešimas iš Tinkoff Invest API naršyklėje
  3. Tarpininkavimo ataskaitų ir sandorių gavimas
  4. Dominančios informacijos apskaičiavimas ir išvedimas
  5. Išvados ir ateities planai

Prisijungimas prie Tinkoff Invest API

Norėdami prisijungti prie API, galite paimti bet kurį SDK iš dokumentacijos https://github.com/Tinkoff/investAPI#sdk . Arba npm paketą ` tinkoff-sdk-grpc-js `. Svarbu, kad kūrėjai atnaujintų paketą į naujausią versiją. Diegti

npm aš tinkoff-sdk-grpc-js

Tikrinama

const { createSdk } = reikalauti(‘tinkoff-sdk-grpc-js’);   // Žetonas, kurį galima gauti taip  const TOKEN = ‘YOURAPI’;   // Programos, pagal kurią jus galite rasti TCS žurnaluose, pavadinimas. const appName = ‘tcsstat’;   const sdk = sukurtiSdk(TOKEN, programos pavadinimas); (async () => {     console.log(lauk sdk.users.getAccounts()); })();

Rezultatas: konsolėje bus rodomas jūsų paskyrų sąrašas. Pavyzdžiui, išanalizuokime niuansus:Kuriame mikropaslaugą naudodami Tinkoff Invest API, skirtą automatizuoti darbą su tarpininkavimo ataskaitomis ir komisinių skaičiavimu.

  • Sąskaitų sąraše yra „Investicinis bankas“, su kuriuo negalite dirbti naudodami API
  • Atkreipkite dėmesį, kad laukai pateikiami „camelCase“, o dokumentuose šie laukai pateikiami „under_score“. 
  • Taip bus visur, todėl negalite tiesiog paimti ir nukopijuoti lauko iš dokumentacijos.

Naudinga:

  • Šį kodą rasite projekto filiale

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

Duomenų piešimas iš Tinkoff Invest API naršyklėje

Paėmiau next.js ir socket.io. Tai nėra griežta rekomendacija, rinkitės savo nuožiūra. 

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

Nedelsdami pereiname prie draugystės žingsnio next+socket+investapi ir visą informaciją rasite šio žingsnio  skyriuje Naudinga . Aš aprašysiu detales: 

  • Nodejs (serverio) pusėje yra failas pages/api/investapi.js. Čia sukuriame socket.io serverį ir prisijungiame prie investapi.
  • Naršyklės (kliento) pusėje per lizdą jungiamės prie serverio ir iš brokerio prašome sąskaitos duomenų. 
  • Duomenis iš brokerio gauname serveryje, tada siunčiame klientui. Kai jie gaunami kliente, jie rodomi naršyklėje. 

Rezultatas:  naršyklės konsolėje galime matyti informaciją apie paskyras. Tai yra, paskutiniame žingsnyje mes matėme informaciją apie paskyras serverio konsolėje (nodejs), dabartiniame žingsnyje šią informaciją perdavėme klientui (naršyklėje).

Kuriame mikropaslaugą naudodami Tinkoff Invest API, skirtą automatizuoti darbą su tarpininkavimo ataskaitomis ir komisinių skaičiavimu.

Dabar padarykime taip, kad galėtumėte pasirinkti paskyrą iš naršyklės, o jei tokeno nėra, į konsolę siunčiama klaida. Darbas paprastas ir nieko naujo, tad duodu tik nuorodas į įsipareigojimus

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

Naudinga:

  • Kaip susirasti draugų kitą ir lizdą, išsamiai aprašyta čia
  • Draugystės kodas next+socket+investapi:

https://github.com/pskucherov/tcsstat/commit/a443a4ac1bb4f0aa898f638128755fe7391ee381 Kam aukščiau aprašyta yra sudėtinga, liekame šiame etape ir susidorojame su kodu. Jei turite klausimų – klauskite. https://github.com/pskucherov/tcsstat/tree/step2 https://github.com/pskucherov/tcsstat/compare/step1…step2

Tarpininkavimo ataskaitų ir sandorių gavimas

Yra trys būdai gauti tarpininkavimo ataskaitas ir sandorius

  1. GetBrokerReport
  2. GaukDividendsForeignIssuer
  3. GetOperationsByCursor

Nuo pat pradžių svarbu žinoti: 

  • Tarpininkavimo ataskaita generuojama T-3 režimu, t.y. ten rodomi sandoriai po faktinio jų įvykdymo. 
  • Atitinkamai, jei paprašysite šios ataskaitos už pastarąsias dvi dienas, ji bus parengta per tris dienas. 
  • Norėdami sudaryti paskutinių dienų sandorius, naudojame operacijų gavimo metodą, tačiau atminkite, kad jų ID ir turinys gali pasikeisti suformavus tarpininkavimo ataskaitą.

GetBrokerReport

Norėdami gauti tarpininkavimo ataskaitą, turite nurodyti sąskaitos ID, ataskaitos pradžios ir pabaigos datą, bet ne daugiau kaip 31 dieną. Išsiunčiame užklausą sugeneruoti ataskaitą į API generuodami _broker_report_request , atsakydami gauname užduoties ID. Po to, naudodami šį taskId, gauname duomenis iš get _broker_report_response.

Taigi dokumentacijoje rašoma, kad iš tikrųjų yra niuansų. Stebėkite savo rankas:
  • Turite išsaugoti TaskID visam laikui būtent šiomis datomis. 
  • Kadangi jei prarasite, prašomomis datomis ataskaita pirmiausia bus pateikta kaip atsakas į generavimo užklausą, 
  • Ir tada jis visai neateis.
Pradėkime rašyti kodą

Datos gavimo būdas, atsižvelgiant į atimtį iš dabartinės datos

const getDateSubDay = (subDay = 5, pradžia = true) => {     const data = new Data();     data.setUTCDate(data.getUTCDate() – subDay);       if (pradžia) {         data.setUTCHours(0, 0, 0, 0);     } else {         date.setUTCHours(23, 59, 59, 999);     }       grąžinimo data; };

Ataskaitų generavimo užklausa 

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

Rezultatas:

  • Pirmą kartą vykdydami komandą, gauname užduoties ID. 
  • Ataskaita pradedama generuoti tarpininko pusėje. Kai jis paruoštas, nežinoma, laukiame ir periodiškai ištraukiame taskId laukdami ataskaitos.
  • Kodėl? Nes jei ataskaita neparengta, ji išmeta klaidą. Jei ataskaita nėra paruošta tarpininko pusėje, tai yra jūsų kodo klaida. Apdorokite: 30058|INVALID_ARGUMENT|užduotis dar nebaigta, bandykite dar kartą vėliau

Ataskaitos laukimo ir gavimo kodas atrodo maždaug taip.

const laikmatis = async time => {     return new Promise(resolve => setTimeout(resolve, time)); }   const getBrokerResponseByTaskId = async (taskId, page = 0) => {     try {         return laukti (sdk.operations.getBrokerReport)({             getBrokerReportRequest: {                 taskId,                 page,             },         });     } gaudyti (e) {         console.log(‘laukti’, e);         laukti laikmačio (10000);         grįžti laukti getBrokerResponseByTaskId(taskId, page);     } };

Tada vyksta ta pati magija. Sustabdome savo scenarijų, paleidžiame jį iš naujo, neturime užduoties ID. Vykdome kodą su užklausa taskId, bet gauname nebe taskId, o iškart ataskaitą. Magija! Ir viskas būtų gerai, jei taip būtų visada. Tačiau po mėnesio duomenų visai nebus. Naudinga :

  • Šiek tiek teorijos išdėstyta čia ir čia .
  • Sudėjus kodą juodraštis atrodys maždaug taip.

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

  • Jei kas nors su tuo susidurs, sveiki atvykę į šią problemą . Kai jie pataisys šią magiją, ji praras savo galią ir bus kažkaip kitokia. Tačiau šiuo metu (2023-03-21) tai veikia lygiai taip pat.

GaukDividendsForeignIssuer

Kas nors gali manyti, kad metodas yra panašus į ankstesnį ir galite naudoti vieną metodą, kuriame pakeisite tik operacijų pavadinimą. Bet jie neatspėjo!  Įvardijimas ten labai skiriasi tiek metodais, tiek grąžinama informacija. O puslapių skaičius prasideda nuo 0, tada nuo 1. Kad nesusipainiotumėte visame tame, paprasčiau parašyti du skirtingus metodus. Kas keista, nes darbo logika ta pati. Ilgai spjaučiau, kai bandžiau padaryti vieną metodą ir kodo buvo mažiau. Pavyzdžių čia nebus.

GetOperationsByCursor

Mano mėgstamiausia iš trijų. Nors ir ne pats tiksliausias, bet adekvatiausias. Pateikiame užklausą nuo paskyros sukūrimo pradžios iki maksimalios galimos datos (sąskaitos uždarymo ar esamos). Gauname atsakymą, paimame žymeklį ir iš naujo prašome, kol yra duomenų.  Ir kodas yra glaustesnis nei aukščiau pateiktuose pavyzdžiuose.

const laikmatis = 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,             state: sdk.OperationState.OPERATION_STATE_EXECUTED,             beKomisinių: klaidingas             be Prekybos: false,             beOvernights: false,             cursor,         };           grįžti laukti sdk.operations.getOperationsByCursor(reqData);     } gaudyti (e) {         laukti laikmatis (60000);         grįžti laukti getOperationsByCursor(sdk, accountId, from, to, cursor = ”);     } };

Paleisties juodraštis yra čia: https://github.com/pskucherov/tcsstat/tree/step3.3 https://github.com/pskucherov/tcsstat/compare/step3.3 Dabar esame pasirengę pridėti gavimo operacijas mūsų paraiška. Jei tai padaryta teisingai, turite gauti tarpininkavimo ataskaitas už visą sąskaitos egzistavimą. Ir dėl trūkstamų duomenų, tų pačių T-3, iš naujo įkelkite iš operacijų. Bet tai gali būti suskirstyta į atskirą straipsnį. Iš pagrindinių niuansų, su kuriais susidursite, yra operacijų klijavimas ir tarpininkavimo ataskaita.

  •  Jei šiandien gavote tarpininkavimo ataskaitą ir sandorius reikiamomis datomis, sudėkite viską į duomenų bazę, tada problemų nėra. 
  • Rytoj turėsite problemų, kai gausite kitą duomenų dalį iš ataskaitos ir operacijų ir nuspręsite juos sinchronizuoti su esama duomenų baze. 
  • Daug niuansų apie nesutampantį arba pakeistą ID po apdorojimo
  • Tada ne biržos rinkoje ID visiškai nesutampa.
  •  Taip pat ir instrumentų sinchronizavimo niuansai, kurie vėlgi nesutampa, dėl API ypatumų. Bet tai jau kita istorija.

Pridėkime prie programos informacijos apie operacijas. Pagrindinis klausimas bus, kur bus tvarkomi ir saugomi duomenys.

  •  Jei tai padarysite sau, sunaudosite tuos pačius duomenis iš skirtingų įrenginių. Tada turite apdoroti ir saugoti duomenis serveryje.
  • Jei turite daug skirtingų duomenų, kuriuos naudoja daug skirtingų vartotojų, tuomet turite nuspręsti, kas svarbiau: vartotojų greitis ar geležies taupymas jūsų pusėje. Kas gali sau leisti be galo daug aparatūros, skaičiuoja viską savo serveryje ir padaro tai ypač greitą vartotojams, taupydamas vartotojo išteklius, tokius kaip baterija ir srautas, o tai labai svarbu telefonuose.

Savo ruožtu skaičiavimas naršyklėje iš principo nėra pats optimaliausias sprendimas. Todėl tai, kas nėra brangu, laikome savo serveryje. Likusią dalį paliekame klientui. Labai noriu imti ir paskaičiuoti komisinius serveryje. Bet čia atsiranda niuansas, vadinamas „interaktyvumu“. Tarkime, kad turite tūkstančius operacijų ir jas gauti užtrunka penkias minutes. Ką vartotojas turės šiuo metu? Suktukas? Progresas? Infa apie tai, kiek buvo įkelta? Idealu naudoti „aktyvų laukimą“, kai proceso metu vartotojas jau kažką mato. Štai rezultatas:Kuriame mikropaslaugą naudodami Tinkoff Invest API, skirtą automatizuoti darbą su tarpininkavimo ataskaitomis ir komisinių skaičiavimu.

  • Puslapio įkėlimas
  • Prašoma visų sąskaitų faktūrų
  • Po to visose sąskaitose prašoma visų operacijų su komisiniais už įvykdytas operacijas. Kai duomenys gaunami, jie pateikiami naršyklėje.

Kad įvykių duomenys nebūtų filtruojami kiekvieną kartą, kiekvienai paskyrai ištraukiame savo įvykį. Kaip šitas:

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

Paleisties juodraštis yra čia: https://github.com/pskucherov/tcsstat/tree/step3 https://github.com/pskucherov/tcsstat/compare/step2…step3 Judame toliau. Puiku, kad perskaitėte šią eilutę! 

Dominančios informacijos apskaičiavimas ir išvedimas

Priklauso nuo to, kam reikia kokios informacijos. Todėl iš karto papasakosiu pagrindinius niuansus, su kuriais susidursite.

Darbas su kainomis 

Kiekvienas, kuris dirba su finansais, žino, kad pinigų operacijos turėtų būti atliekamos tik su sveikais skaičiais. Dėl reikšmių netikslumo po kablelio ir kaupiamosios klaidos atliekant daugybę operacijų. Todėl visos kainos pateikiamos tokiu MoneyValue formatuKuriame mikropaslaugą naudodami Tinkoff Invest API, skirtą automatizuoti darbą su tarpininkavimo ataskaitomis ir komisinių skaičiavimu.

lauketipoapibūdinimas
valiutastygaEilutės ISO valiutos kodas
vienetųint64Sveikoji sumos dalis, gali būti neigiamas skaičius
nanoint32Trupmeninė sumos dalis gali būti neigiamas skaičius

Mes apdorojame juos atskirai, tada pateikiame juos į kainos vertę:

citata.vienetai + citata.nano / 1e9

Ateities sandorių kaina

Ateities sandorių kaina pateikiama taškais, kai turite valiutos ateities sandorį, turite žinoti kursą. Ir žinoma kaina taškais ir kainos žingsnis. Kai skaičiuojate pelną iš sandorių, tai gali šaudyti, nes. jei bendrą sumą skaičiuosite kainą padaugindami iš kiekio. Čia reikia būti atsargiems. Kol kas žiūrėsime, kaip seksis. Tai taikoma valiutos ateities sandoriams, kitose vietose viskas yra gerai.Kuriame mikropaslaugą naudodami Tinkoff Invest API, skirtą automatizuoti darbą su tarpininkavimo ataskaitomis ir komisinių skaičiavimu.Kuriame mikropaslaugą naudodami Tinkoff Invest API, skirtą automatizuoti darbą su tarpininkavimo ataskaitomis ir komisinių skaičiavimu.

OTC rinka

Ši rinka turi daug ypatumų, todėl panagrinėkime operacijas joje atskirai. Pradėjus sinchronizuoti operacijas paaiškės, kad norint teisingai suderinti instrumentą, reikia perkelti figi / ticker į tą pačią formą. Pradėjus tai sinchronizuoti su tarpininkavimo ataskaita, paaiškės, kad tos pačios operacijos tradeID sandorių pradžioje turi raides, o tarpininkavimo ataskaitoje jų nėra. Todėl jų negalima lyginti… ahem-ahem… palyginimu! Suderinau prekybos laiką, žymą ir atitikimą, kad vienas prekybos ID yra kitame. Teisingai, aš nežinau. Kas su tuo susiduria ir kam tai rūpi, spręskite problemą arba pradėkite naują.Kuriame mikropaslaugą naudodami Tinkoff Invest API, skirtą automatizuoti darbą su tarpininkavimo ataskaitomis ir komisinių skaičiavimu.

Matematinės operacijos su įrankiais

Neįmanoma atlikti matematinių operacijų su visu sąrašu. Kad nepridėtų šilto prie minkšto, visada tikriname valiutą ir apdorojame tik įsitikinę, kad valiuta sutampa, o taškai konvertuojami į norimą valiutą. Turėdami žinių apie darbą su banko numeriais, apskaičiuosime komisinius, išleistus kiekvienai sąskaitai. Taip: https://github.com/pskucherov/tcsstat/tree/step4 https://github.com/pskucherov/tcsstat/compare/step3…step4Kuriame mikropaslaugą naudodami Tinkoff Invest API, skirtą automatizuoti darbą su tarpininkavimo ataskaitomis ir komisinių skaičiavimu.   

Mikroservisas paruoštas!

https://github.com/pskucherov/tcsstat Kaip namų darbus galite patikrinti, ar paslauga veikia esant lėtam ryšiui, kada nutrūksta ryšiai, kada atjungiamas internetas, kada brokeriui pasitaiko klaidų ar pasibaigė limitai. 

Išvados ir ateities planai

  • Sužinojote apie pagrindines operacijas ir darbą su Invest API
  • Laikas praleistas ~ 10 val
  • Sunkumo lygis ~ junior+ / žemas vidurinis 

Jei ir toliau tobulinsite mikropaslaugą, gali atsirasti kažkas panašaus

https://opexbot.info

  Tai mano tobulėjimas, skirtas tiems, kurie tingi suprasti, bėgti ir skaičiuoti patys. Vartotojų pageidavimu planuoju ten pridėti analizę. Jei jums patiko straipsnis, užsiprenumeruokite mano telegramos kanalą . Kuriame mikropaslaugą naudodami Tinkoff Invest API, skirtą automatizuoti darbą su tarpininkavimo ataskaitomis ir komisinių skaičiavimu.

Pavel
Rate author
Add a comment

  1. Isakiiev

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

    Reply