Ni disvolvas mikroservon uzante la Tinkoff Invest API por aŭtomatigi laboradon kun kurtaĝaj raportoj kaj kalkulado de komisionoj.

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

La inspirantoj malantaŭ la evoluo de la statistika servo por Tinkoff Investments estis:

Pri kio oni diskutos?

  • Nur la aplikata parto pri evoluo.
  • Reala scio kaj sperto, kiuj estas tre gravaj por labori kun financaj instrumentoj.
  • Superrigardo de aferoj por labori

Do, mi volas kalkuli komercajn statistikojn kaj fari ĝin en oportuna maniero. 

Evoluigante statistikan servon paŝon post paŝo: 

  1. Konekto al Tinkoff Invest API
  2. Desegnante datumojn de Tinkoff Invest API en retumilo
  3. Ricevante kurtaĝajn raportojn kaj transakciojn
  4. Kalkulo kaj eligo de interesaj informoj
  5. Konkludoj kaj planoj por la estonteco

Konekto al Tinkoff Invest API

Por konektiĝi al la API, vi povas preni ajnan sdk el la dokumentado https://github.com/Tinkoff/investAPI#sdk . Aŭ npm-pakaĵo ` tinkoff-sdk-grpc-js `. Gravas, ke la pakaĵo estas ĝisdatigita al la plej nova versio de la programistoj. Instali

npm i tinkoff-sdk-grpc-js

Kontrolado

const { createSdk } = require(‘tinkoff-sdk-grpc-js’);   // Token kiu povas esti akirita tiel  const TOKEN = ‘YOURAPI’;   // La nomo de la aplikaĵo per kiu vi troviĝas en la protokoloj de TCS. const appName = ‘tcsstat’;   const sdk = createSdk(TOKEN, appName); (async () => {     console.log (atendo sdk.users.getAccounts ()); })();

Rezulto: listo de viaj kontoj estos montrata en la konzolo. Ekzemple, ni analizu la nuancojn:Ni disvolvas mikroservon uzante la Tinkoff Invest API por aŭtomatigi laboradon kun kurtaĝaj raportoj kaj kalkulado de komisionoj.

  • En la listo de kontoj estas “Investa banko”, kun kiu vi ne povas labori uzante la API
  • Bonvolu noti, ke la kampoj venas en camelCase, dum en la dokumentaro ĉi tiuj kampoj estas prezentitaj en sub_poentaro. 
  • Ĉie estos tiel, do vi ne povas simple preni kaj kopii kampon el la dokumentaro.

Utila:

  • Vi povas trovi ĉi tiun kodon en la projektbranĉo

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

Desegnante datumojn de Tinkoff Invest API en retumilo

Mi prenis next.js kaj socket.io. Ĉi tio ne estas forta rekomendo, elektu laŭ via bontrovo. 

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

Ni tuj iras al la amikeca paŝo sekva+socket+investapi, kaj vidu la Utilan sekcion de ĉi tiu paŝo por ĉiuj detaloj.  Mi priskribos la detalojn: 

  • Ĉe la flanko nodejs (servilo), estas dosiero pages/api/investapi.js. Ĉi tie ni kreas la servilon socket.io kaj konektas al investapi.
  • Ĉe la retumilo (kliento), ni konektas al la servilo per ingo kaj petas kontajn datumojn de la makleristo. 
  • Ni ricevas datumojn de la makleristo sur la servilo, poste sendas ĝin al la kliento. Kiam ili estas ricevitaj sur la kliento, ili estas montrataj en la retumilo. 

Rezulto:  en la retumila konzolo ni povas vidi informojn pri kontoj. Tio estas, en la lasta paŝo, ni vidis informojn pri kontoj en la servila konzolo (nodejs), en la nuna paŝo, ni transdonis ĉi tiun informon al la kliento (retumilo).

Ni disvolvas mikroservon uzante la Tinkoff Invest API por aŭtomatigi laboradon kun kurtaĝaj raportoj kaj kalkulado de komisionoj.

Nun ni faru ĝin tiel, ke vi povas elekti konton el la retumilo, kaj se ne ekzistas signo, tiam eraro estas sendita al la konzolo. La laboro estas simpla kaj nenio nova, do mi donas nur ligilojn al kommits

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

Utila:

  • Kiel fari amikojn poste kaj socket estas priskribita detale ĉi tie
  • Amikeca kodo sekva+socket+investapi:

https://github.com/pskucherov/tcsstat/commit/a443a4ac1bb4f0aa898f638128755fe7391ee381 Por kiuj la supre estas malfacila, tiam ni restas en ĉi tiu etapo kaj traktas la kodon. Se vi havas demandojn – demandu. https://github.com/pskucherov/tcsstat/tree/step2 https://github.com/pskucherov/tcsstat/compare/step1…step2

Ricevante kurtaĝajn raportojn kaj transakciojn

Estas tri metodoj por ricevi kurtaĝajn raportojn kaj transakciojn

  1. GetBrokerRaport
  2. GetDividendsForeignIssuer
  3. GetOperationsByCursor

De la komenco estas grave scii: 

  • La kurtaga raporto estas generita en la T-3-reĝimo, t.e. komercoj estas montrataj tie post sia reala ekzekuto. 
  • Sekve, se vi petos ĉi tiun raporton dum la lastaj du tagoj, ĝi estos preta post tri tagoj. 
  • Por akiri transakciojn dum la lastaj tagoj, ni uzas la metodon por ricevi transakciojn, sed memoru, ke ilia identigilo kaj enhavo povas ŝanĝiĝi post kiam la kurtaĝa raporto estas generita.

GetBrokerRaport

Por ricevi kurtagan raporton, vi devas preni la kontan identigilon, komencan daton kaj findaton de la raporto, sed ne pli ol 31 tagojn. Ni sendas peton por generi raporton al la API en generate _broker_report_request , ricevas taskId en respondo. Post tio, uzante ĉi tiun taskId, ni ricevas datumojn de get _broker_report_response.

Do diras la dokumentaro, fakte estas nuancoj. Gardu viajn manojn:
  • Vi devas konservi la TaskID por ĉiam ĝuste por ĉi tiuj datoj. 
  • Ĉar se vi perdos ĝin, tiam por la petitaj datoj la raporto unue venos responde al la generacia peto, 
  • Kaj tiam ĝi tute ne venos.
Ni komencu skribi kodon

Metodo por ricevi la daton, konsiderante la subtraho de la aktuala dato

const getDateSubTay = (subTay = 5, start = true) => {     const dato = nova Dato ();     dato.setUTCDate (date.getUTCDate () – subTago);       if (komenco) {         dato.setUTCHours (0, 0, 0, 0);     } else {         date.setUTCHours (23, 59, 59, 999);     }       revendato; };

Peto pri generado de raporto 

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

Rezulto:

  • Kiel rezulto de la unua ekzekuto de la komando, ni ricevas la taskId. 
  • La raporto komencas esti generita flanke de la makleristo. Kiam ĝi estas preta estas nekonata, ni atendas kaj periode tiras la taskId en antaŭĝojo de la raporto.
  • Kial? Ĉar se la raporto ne estas preta, ĝi ĵetas eraron. Se la raporto ne estas preta flanke de la makleristo, tiam ĉi tio estas eraro en via kodo. Bonvolu procesi: 30058|INVALID_ARGUMENT|tasko ankoraŭ ne kompletigita, bonvolu provi denove poste

La kodo por atendi kaj ricevi raporton aspektas kiel ĉi tio.

const timer = nesinkrona tempo => {     return new Promise (solvi => setTimeout (solvi, tempo)); }   const getBrokerResponseByTaskId = async (taskId, paĝo = 0) => {     provu {         return await (sdk.operations.getBrokerReport)({             getBrokerReportRequest: {                 taskId,                 paĝo,             },         });     } catch (e) {         console.log(‘atendu’, e);         atendi tempigilon (10000);         reveni atendu getBrokerResponseByTaskId (taskId, paĝo);     } };

Tiam la sama magio okazas. Ni ĉesas nian skripton, rekomencu ĝin, ni ne havas taskId. Ni plenumas la kodon kun la peto taskId, sed ni ne plu ricevas la taskId, sed tuj la raporton. Magio! Kaj ĉio estus bone, se ĉiam estus tiel. Sed post monato tute ne estos datumoj. Utila :

  • Iom da teorio estas skizita ĉi tie kaj ĉi tie .
  • Kunigante la kodon, la skizo aspektos io tiel.

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

  • Se iu renkontas ĉi tion, do bonvenon al la afero . Post kiam ili riparos ĉi tiun magion, ĝi perdos sian potencon kaj estos iel malsama. Sed en la nuna momento (21/03/2023) ĝi funkcias ĝuste tiel.

GetDividendsForeignIssuer

Iu povus pensi, ke la metodo similas al la antaŭa kaj vi povas uzi ununuran metodon, en kiu vi nur ŝanĝas la nomon de la operacioj. Sed ili ne divenis!  La nomado tie estas tre malsama kaj en la metodoj kaj en la redonitaj informoj. Kaj la paĝkalkulo komenciĝas de 0, poste de 1. Por ne konfuziĝi pri ĉio ĉi, estas pli facile skribi du malsamajn metodojn. Kio estas stranga, ĉar la logiko de laboro estas la sama. Mi kraĉis longe, kiam mi provis fari unu metodon kaj estis malpli da kodo. Ne estos ekzemploj ĉi tie.

GetOperationsByCursor

Mia plej ŝatata el la tri. Kvankam ne la plej preciza, sed la plej taŭga. Ni faras peton de la komenco de kreado de konto ĝis la maksimuma ebla dato (fermo de konto aŭ la nuna). Ni ricevas la respondon, prenu la kursoron kaj re-petas tiel longe kiel estas datumoj.  Kaj la kodo estas pli konciza ol en la supraj ekzemploj.

const timer = nesinkrona tempo => {     return new Promise (solvi => setTimeout (solvi, tempo)); }   const getOperationsByCursor = async (sdk, accountId, from, to, cursor = ”) => {     provu {         const reqData = {             accountId,             from,             to,             limit: 1000,             state: sdk.OperationState.OPERATION_STATE_EXECUTED,             withoutCommissions: false,             senKomercoj: falsa,             senTranoktoj: falsa,             kursoro,         };           return await sdk.operations.getOperationsByCursor (reqData);     } catch (e) {         atendi timer(60000);         return await getOperationsByCursor (sdk, accountId, from, to, kursoro = ”);     } };

La malneto rulebla estas ĉi tie: https://github.com/pskucherov/tcsstat/tree/step3.3 https://github.com/pskucherov/tcsstat/compare/step3.3 Nun ni pretas aldoni ricevajn operaciojn al nia aplikaĵo. Se farite ĝuste, tiam vi devas ricevi kurtaĝajn raportojn por la tuta ekzisto de la konto. Kaj por la mankantaj datumoj, tiuj samaj T-3s, reŝargi de operacioj. Sed ĉi tio povas esti apartigita en apartan artikolon. El la ĉefaj nuancoj, kiujn vi renkontos, estas glui operaciojn kaj kurtaĝan raporton.

  •  Se hodiaŭ vi ricevis kurtaĝan raporton kaj transakciojn por la postulataj datoj, metu ĉion en la datumbazon, tiam ne estas problemoj. 
  • Vi havos problemojn morgaŭ kiam vi ricevos la sekvan parton de datumoj de la raporto kaj operacioj kaj decidos sinkronigi ilin kun la ekzistanta datumbazo. 
  • Multaj nuancoj pri misagordado aŭ ŝanĝado de identigilo post prilaborado
  • Tiam por la OTC-merkato, la identigiloj tute ne kongruas.
  •  Same kiel la nuancoj de sinkronigaj instrumentoj, kiuj denove ne koincidas, pro la proprecoj de la API. Sed tio estas alia historio.

Ni aldonu ricevi informojn pri operacioj al nia aplikaĵo. La ĉefa demando estos kie la datumoj estos prilaboritaj kaj stokitaj.

  •  Se vi faras ĝin por vi mem, vi konsumos la samajn datumojn de malsamaj aparatoj. Tiam vi devas prilabori kaj stoki datumojn sur la servilo.
  • Se vi havas multajn malsamajn datumojn konsumitaj de multaj malsamaj uzantoj, tiam vi devas decidi kio estas pli grava: la rapideco de la uzantoj aŭ la ŝparado de fero sur via flanko. Kiu povas pagi senfinan kvanton da aparataro, kalkulas ĉion sur sia servilo kaj faras ĝin superrapida por uzantoj, ŝparante la uzantrimedojn, kiel kuirilaron kaj trafikon, kio estas tre grava ĉe telefonoj.

Siavice, kalkuli en la retumilo principe ne estas la plej optimuma solvo. Tial, kio ne estas multekosta, ni konsideras ĝin sur nia servilo. La reston ni lasas al la kliento. Mi vere volas preni kaj kalkuli la komisionon sur la servilo. Sed jen venas la nuanco nomata “interagado”. Ni diru, ke vi havas milojn da operacioj kaj necesas kvin minutoj por ricevi ilin. Kion havos la uzanto ĉi-momente? Ŝpinisto? Ĉu progreso? Infa pri kiom estis alŝutita? Estas ideale uzi “aktivan atendon” kiam la uzanto en la procezo jam povis vidi ion. Jen la Rezulto:Ni disvolvas mikroservon uzante la Tinkoff Invest API por aŭtomatigi laboradon kun kurtaĝaj raportoj kaj kalkulado de komisionoj.

  • Paĝa ŝarĝo
  • Ĉiuj fakturoj estas petitaj
  • Post tio, ĉiuj transakcioj kun komisionoj por efektivigitaj transakcioj estas petitaj por ĉiuj kontoj. Ĉar datumoj estas ricevitaj, ĝi estas prezentita en la retumilo.

Por ne filtri la datumojn en la eventoj ĉiufoje, ni tiras nian propran eventon por ĉiu konto. Kiel tio:

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

La malneto por lanĉi estas ĉi tie: https://github.com/pskucherov/tcsstat/tree/step3 https://github.com/pskucherov/tcsstat/compare/step2…step3 Plu. Estas bonege, ke vi legis ĉi tiun linion! 

Kalkulo kaj eligo de interesaj informoj

Dependas de kiu bezonas kiajn informojn. Tial mi tuj rakontas al vi la ĉefajn nuancojn, kiujn vi renkontos.

Laborante kun prezoj 

Ĉiuj, kiuj laboras kun financo, scias, ke montransakcioj devas esti faritaj nur per tutaj nombroj. Pro la malprecizeco de valoroj post la dekuma punkto kaj la akumula eraro kun granda nombro da operacioj. Tial ĉiuj prezoj estas prezentitaj en la sekva MoneyValue- formatoNi disvolvas mikroservon uzante la Tinkoff Invest API por aŭtomatigi laboradon kun kurtaĝaj raportoj kaj kalkulado de komisionoj.

kampotajpuPriskribo
valutoŝnuroŜnuro ISO-valutkodo
unuojint64Entjera parto de la sumo, povas esti negativa nombro
nanoint32Frakcia parto de la kvanto, povas esti negativa nombro

Ni procesas ilin aparte, tiam alportas ilin al la prezvaloro:

citaĵo.unuoj + citaĵo.nano / 1e9

La kosto de estontaj kontraktoj

La prezo de estontecoj estas prezentita en punktoj, kiam vi havas valutan estontecon, vi devas scii la kurzon. Kaj kompreneble la prezo en punktoj kaj la prezo paŝo. Kiam vi kalkulas la profiton de transakcioj, ĉi tio povas pafi, ĉar. se vi kalkulas la totalan kvanton multobligante la prezon per la kvanto. Ĉi tie vi devas esti singarda. Nuntempe, ni vidos kiel ĝi iras. Ĉi tio validas por valutaj estontecoj, en aliaj lokoj ĉio estas en ordo kun ĉi tio.Ni disvolvas mikroservon uzante la Tinkoff Invest API por aŭtomatigi laboradon kun kurtaĝaj raportoj kaj kalkulado de komisionoj.Ni disvolvas mikroservon uzante la Tinkoff Invest API por aŭtomatigi laboradon kun kurtaĝaj raportoj kaj kalkulado de komisionoj.

OTC-merkato

Ĉi tiu merkato havas multajn proprecojn, do ni studu operaciojn sur ĝi aparte. Kiam vi komencos sinkronigi operaciojn, montriĝos, ke vi devas alporti figi / ticker al la sama formo por ĝuste kongrui kun la instrumento. Kiam vi komencas sinkronigi ĉi tion kun la raporto pri kurtaĝo, montros, ke la tradeID de la sama transakcio havas literojn komence en la transakcioj kaj ili ne estas en la raporto pri kurtaĝo. Sekve, ili ne povas esti kompareblaj … ahem-ahem … kompare! Mi kongruis kun la komerca tempo, ticker kaj kongruo, ke unu tradeId estas enhavita en alia. Prave, mi ne scias. Kiu renkontas ĉi tion kaj kiu zorgas pri ĝi, venu al la afero aŭ komencu novan.Ni disvolvas mikroservon uzante la Tinkoff Invest API por aŭtomatigi laboradon kun kurtaĝaj raportoj kaj kalkulado de komisionoj.

Matematikaj operacioj pri iloj

Estas neeble, sen rigardi, fari matematikajn operaciojn kun la tuta listo. Por ne aldoni varman al mola, ni ĉiam kontrolas la valuton kaj procesas nur se ni estas certaj, ke la valuto kongruas, kaj la punktoj estas konvertitaj al la dezirata valuto. Armitaj kun scio pri laborado kun bankaj nombroj, ni kalkulos la komisionon elspezitan por ĉiu el la kontoj. Tiel: https://github.com/pskucherov/tcsstat/tree/step4 https://github.com/pskucherov/tcsstat/compare/step3…step4Ni disvolvas mikroservon uzante la Tinkoff Invest API por aŭtomatigi laboradon kun kurtaĝaj raportoj kaj kalkulado de komisionoj.   

Mikroservo estas preta!

https://github.com/pskucherov/tcsstat Kiel hejmtasko, vi povas kontroli ĉu la servo funkcias kun malrapida konekto, kiam ligoj estas rompitaj, kiam la interreto estas malkonektita, kiam eraroj aŭ eksvalidiĝintaj limoj de la makleristo. 

Konkludoj kaj planoj por la estonteco

  • Lernis pri bazaj operacioj kaj laborado kun la Invest API
  • Tempo pasigita ~ 10 horoj
  • Malfacilnivelo ~ juniora+ / malalta meza 

Se vi daŭre rafinis la mikroservon, vi povus fini kun io tia

https://opexbot.info

  Jen mia evoluo, por tiuj, kiuj tro maldiligentas kompreni, kuri kaj kalkuli memstare. Mi planas aldoni analizojn tie laŭ peto de uzantoj. Se vi ŝatis la artikolon, tiam abonu mian telegraman kanalon . Ni disvolvas mikroservon uzante la Tinkoff Invest API por aŭtomatigi laboradon kun kurtaĝaj raportoj kaj kalkulado de komisionoj.

Pavel
Rate author
Add a comment

  1. Isakiiev

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

    Reply