Ang mga inspirasyon sa likod ng pagbuo ng serbisyo ng istatistika para sa Tinkoff Investments ay:
- artikulo sa Habré “Ano ang hindi sinasabi ng Tinkoff Investments”
- pagsusuri ng mga kagustuhan ng mga gumagamit ng platform
- isang artikulo tungkol sa pagkalkula ng mga komisyon .
- Ano ang tatalakayin?
- Pagbuo ng serbisyo ng istatistika nang sunud-sunod:
- Koneksyon sa Tinkoff Invest API
- Pagguhit ng data mula sa Tinkoff Invest API sa isang browser
- Pagtanggap ng mga ulat at transaksyon sa brokerage
- GetBrokerReport
- Paraan para sa pagkuha ng petsa, isinasaalang-alang ang pagbabawas mula sa kasalukuyang petsa
- Paghiling ng pagbuo ng ulat
- Resulta:
- Kumuha ngDividendsForeignIssuer
- GetOperationsByCursor
- Pagkalkula at output ng impormasyon ng interes
- Paggawa gamit ang mga presyo
- Ang halaga ng mga kontrata sa futures
- OTC market
- Mga pagpapatakbo ng matematika sa mga tool
- Handa na ang microservice!
- Mga konklusyon at plano para sa hinaharap
- https://opexbot.info
Ano ang tatalakayin?
- Tanging ang inilapat na bahagi tungkol sa pag-unlad.
- Tunay na kaalaman at karanasan, na napakahalaga sa pagtatrabaho sa mga instrumentong pinansyal.
- Pangkalahatang-ideya ng mga isyu na gagawin
Kaya, gusto kong kalkulahin ang mga istatistika ng kalakalan at gawin ito sa isang maginhawang paraan.
Pagbuo ng serbisyo ng istatistika nang sunud-sunod:
- Koneksyon sa Tinkoff Invest API
- Pagguhit ng data mula sa Tinkoff Invest API sa isang browser
- Pagtanggap ng mga ulat at transaksyon sa brokerage
- Pagkalkula at output ng impormasyon ng interes
- Mga konklusyon at plano para sa hinaharap
Koneksyon sa Tinkoff Invest API
Upang kumonekta sa API, maaari kang kumuha ng anumang sdk mula sa dokumentasyon https://github.com/Tinkoff/investAPI#sdk . O npm package ` tinkoff-sdk-grpc-js `. Mahalaga na ang package ay na-update sa pinakabagong bersyon ng mga developer. I-install
npm i tinkoff-sdk-grpc-js
Sinusuri
const {createSdk } = nangangailangan(‘tinkoff-sdk-grpc-js’); // Token na maaaring makuha tulad nitong const TOKEN = ‘YOURAPI’; // Ang pangalan ng application kung saan makikita ka sa mga TCS log. const appName = ‘tcsstat’; const sdk = createSdk(TOKEN, appName); (async () => { console.log(naghihintay sa sdk.users.getAccounts()); })();
Resulta: isang listahan ng iyong mga account ang ipapakita sa console. Halimbawa, pag-aralan natin ang mga nuances:
- Sa listahan ng mga account mayroong isang “Investment bank”, kung saan hindi ka maaaring magtrabaho gamit ang API
- Pakitandaan na ang mga field ay nasa camelCase, habang sa dokumentasyon ang mga field na ito ay ipinakita sa under_score.
- Magiging ganito ito sa lahat ng dako, kaya hindi ka maaaring kumuha at kumopya ng isang field mula sa dokumentasyon.
Kapaki-pakinabang:
- Mahahanap mo ang code na ito sa sangay ng proyekto
https://github.com/pskucherov/tcsstat/tree/step1 https://github.com/pskucherov/tcsstat/compare/step1
Pagguhit ng data mula sa Tinkoff Invest API sa isang browser
Kinuha ko ang next.js at socket.io. Ito ay hindi isang malakas na rekomendasyon, pumili sa iyong paghuhusga.
npx create-next-app@latest npm i socket.io socket.io-client
Agad kaming tumuloy sa pakikipagkaibigan na hakbang sa susunod na+socket+investapi, at tingnan ang Kapaki-pakinabang na seksyon ng hakbang na ito para sa lahat ng detalye. Ilalarawan ko ang mga detalye:
- Sa gilid ng nodejs (server), mayroong isang pages/api/investapi.js file. Dito kami gumagawa ng socket.io server at kumonekta sa investapi.
- Sa gilid ng browser (kliyente), kumonekta kami sa server sa pamamagitan ng isang socket at humiling ng data ng account mula sa broker.
- Nakatanggap kami ng data mula sa broker sa server, pagkatapos ay ipadala ito sa kliyente. Kapag natanggap ang mga ito sa kliyente, ipinapakita ang mga ito sa browser.
Resulta: sa browser console makikita natin ang impormasyon tungkol sa mga account. Iyon ay, sa huling hakbang, nakita namin ang impormasyon tungkol sa mga account sa server console (nodejs), sa kasalukuyang hakbang, inilipat namin ang impormasyong ito sa kliyente (browser).
Ngayon gawin natin ito upang maaari kang pumili ng isang account mula sa browser, at kung walang token, pagkatapos ay isang error ang ipapadala sa console. Ang trabaho ay simple at walang bago, kaya nagbibigay lamang ako ng mga link sa mga commit
- https://github.com/pskucherov/tcsstat/commit/7e1ac57061e5e971588479015b06d8814d6609a9
- https://github.com/pskucherov/tcsstat/commit/b28ac973a57494f5232589b4cb6b9fb13b8af759
Kapaki-pakinabang:
- Paano makipagkaibigan sa susunod at ang socket ay inilarawan nang detalyado dito .
- Friendship code next+socket+investapi:
https://github.com/pskucherov/tcsstat/commit/a443a4ac1bb4f0aa898f638128755fe7391ee381 Para kanino ang nasa itaas ay mahirap, pagkatapos ay mananatili kami sa yugtong ito at haharapin ang code. Kung mayroon kang mga katanungan – magtanong. https://github.com/pskucherov/tcsstat/tree/step2 https://github.com/pskucherov/tcsstat/compare/step1…step2
Pagtanggap ng mga ulat at transaksyon sa brokerage
May tatlong paraan para makatanggap ng mga ulat at transaksyon sa brokerage
Sa simula pa lamang ay mahalagang malaman:
- Ang ulat ng brokerage ay nabuo sa T-3 mode, i.e. ang mga trade ay ipinapakita doon pagkatapos ng kanilang aktwal na pagpapatupad.
- Alinsunod dito, kung hihilingin mo ang ulat na ito para sa huling dalawang araw, magiging handa ito sa loob ng tatlong araw.
- Upang makakuha ng mga transaksyon para sa mga huling araw, ginagamit namin ang paraan para sa pagtanggap ng mga transaksyon, ngunit tandaan na ang kanilang id at nilalaman ay maaaring magbago pagkatapos mabuo ang ulat ng brokerage.
GetBrokerReport
Upang makakuha ng ulat ng brokerage, kailangan mong kunin ang account id, petsa ng pagsisimula at petsa ng pagtatapos ng ulat, ngunit hindi hihigit sa 31 araw. Nagpapadala kami ng kahilingan para makabuo ng ulat sa API sa pagbuo ng _broker_report_request , kumuha ng taskId bilang tugon. Pagkatapos nito, gamit ang taskId na ito, nakakakuha kami ng data mula sa get _broker_report_response.
- Kailangan mong i-save ang TaskID magpakailanman nang eksakto para sa mga petsang ito.
- Dahil kung mawala mo ito, pagkatapos ay para sa mga hiniling na petsa ang ulat ay unang darating bilang tugon sa kahilingan ng henerasyon,
- At pagkatapos ay hindi ito darating sa lahat.
Paraan para sa pagkuha ng petsa, isinasaalang-alang ang pagbabawas mula sa kasalukuyang petsa
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); } petsa ng pagbabalik; };
Paghiling ng pagbuo ng ulat
const brokerReport = naghihintay (sdk.operations.getBrokerReport)({ generateBrokerReportRequest: { accountId, from, to, }, });
Resulta:
- Bilang resulta ng unang pagpapatupad ng utos, nakuha namin ang taskId.
- Nagsisimulang mabuo ang ulat sa panig ng broker. Kapag handa na ito ay hindi alam, naghihintay kami at pana-panahong kinukuha ang taskId bilang pag-asa sa ulat.
- Bakit? Dahil kung ang ulat ay hindi handa, ito ay nagtatapon ng isang error. Kung ang ulat ay hindi handa sa panig ng broker, ito ay isang error sa iyong code. Pakiproseso: 30058|INVALID_ARGUMENT|hindi pa nakumpleto ang gawain, pakisubukang muli sa ibang pagkakataon
Ang code para sa paghihintay at pagtanggap ng ulat ay mukhang ganito.
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); maghintay ng timer(10000); pagbabalik naghihintay getBrokerResponseByTaskId(taskId, pahina); } };
Pagkatapos ay ang parehong magic ang mangyayari. Itinigil namin ang aming script, simulan itong muli, wala kaming taskId. Isinasagawa namin ang code gamit ang kahilingan sa taskId, ngunit hindi na namin makuha ang taskId, ngunit kaagad ang ulat. Magic! At magiging maayos ang lahat kung laging ganito. Ngunit sa isang buwan ay wala nang data. Kapaki-pakinabang :
- Ang kaunting teorya ay nakabalangkas dito at dito .
- Kapag pinagsama ang code, magiging ganito ang hitsura ng draft.
https://github.com/pskucherov/tcsstat/tree/step3.1 https://github.com/pskucherov/tcsstat/compare/step3.1
- Kung may nakatagpo nito, maligayang pagdating sa isyu . Pagkatapos nilang ayusin ang mahika na ito, mawawalan ito ng kapangyarihan at kahit papaano ay magiging iba. Ngunit sa kasalukuyang sandali (03/21/2023) ito ay gumagana nang ganoon.
Kumuha ngDividendsForeignIssuer
Maaaring isipin ng isang tao na ang pamamaraan ay katulad ng nauna at maaari kang gumamit ng isang paraan kung saan binago mo lamang ang pangalan ng mga operasyon. Ngunit hindi nila nahulaan! Ang pagpapangalan doon ay ibang-iba sa mga pamamaraan at sa ibinalik na impormasyon. At ang bilang ng pahina ay nagsisimula sa 0, pagkatapos ay mula sa 1. Upang hindi malito sa lahat ng ito, mas madaling magsulat ng dalawang magkaibang pamamaraan. Na kakaiba, dahil ang lohika ng trabaho ay pareho. Matagal akong dumura nang sinubukan kong gumawa ng isang paraan at mas kaunti ang code. Walang mga halimbawa dito.
GetOperationsByCursor
Favorite ko sa tatlo. Kahit na hindi ang pinaka-tumpak, ngunit ang pinaka-sapat. Gumagawa kami ng isang kahilingan mula sa simula ng paglikha ng isang account hanggang sa maximum na posibleng petsa (pagsasara ng isang account o sa kasalukuyan). Nakukuha namin ang sagot, kunin ang cursor at muling humiling hangga’t may data. At ang code ay mas maigsi kaysa sa mga halimbawa sa itaas.
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, state: sdk.OperationState.OPERATION_STATE_EXECUTED, withoutCommissions: false, withoutTrades: false, withoutOvernights: false, cursor, }; pagbabalik naghihintay sdk.operations.getOperationsByCursor(reqData); } catch (e) { wait timer(60000); return wait getOperationsByCursor(sdk, accountId, from, to, cursor = ”); } };
Narito ang draft na tatakbo: https://github.com/pskucherov/tcsstat/tree/step3.3 https://github.com/pskucherov/tcsstat/compare/step3.3 Ngayon handa na kaming magdagdag ng mga operasyon sa pagtanggap sa aming aplikasyon. Kung nagawa nang tama, kailangan mong makakuha ng mga ulat ng brokerage para sa buong pagkakaroon ng account. At para sa nawawalang data, ang parehong mga T-3, i-reload mula sa mga operasyon. Ngunit ito ay maaaring ihiwalay sa isang hiwalay na artikulo. Sa mga pangunahing nuances na makakatagpo mo ay ang pagdikit ng mga operasyon at isang ulat ng brokerage.
- Kung ngayon nakatanggap ka ng ulat ng brokerage at mga transaksyon para sa mga kinakailangang petsa, ilagay ang lahat sa database, kung gayon walang mga problema.
- Magkakaroon ka ng mga problema bukas kapag natanggap mo ang susunod na bahagi ng data mula sa ulat at mga operasyon at nagpasya na i-synchronize ang mga ito sa umiiral na database.
- Maraming mga nuances tungkol sa hindi tugma o pagbabago ng id pagkatapos ng pagproseso
- Pagkatapos para sa OTC market, ang mga id ay hindi tumutugma sa lahat.
- Pati na rin ang mga nuances ng pag-synchronize ng mga instrumento, na muli ay hindi nag-tutugma, dahil sa mga kakaibang katangian ng API. Ngunit iyon ay ibang kuwento.
Idagdag natin ang pagkuha ng impormasyon tungkol sa mga pagpapatakbo sa aming application. Ang pangunahing tanong ay kung saan ipoproseso at iimbak ang data.
- Kung gagawin mo ito para sa iyong sarili, uubusin mo ang parehong data mula sa iba’t ibang device. Pagkatapos ay kailangan mong iproseso at iimbak ang data sa server.
- Kung mayroon kang maraming iba’t ibang data na natupok ng maraming iba’t ibang mga gumagamit, kailangan mong magpasya kung ano ang mas mahalaga: ang bilis ng mga gumagamit o ang pag-save ng bakal sa iyong panig. Ang sinumang kayang bumili ng walang katapusang halaga ng hardware ay binibilang ang lahat sa kanyang server at ginagawa itong napakabilis para sa mga user, na nakakatipid sa mga mapagkukunan ng user, gaya ng baterya at trapiko, na napakahalaga sa mga telepono.
Sa turn, ang pagbibilang sa browser ay hindi ang pinakamainam na solusyon sa prinsipyo. Samakatuwid, kung ano ang hindi mahal, isinasaalang-alang namin ito sa aming server. Iniiwan namin ang natitira sa kliyente. Gusto ko talagang kunin at kalkulahin ang komisyon sa server. Ngunit narito ang nuance na tinatawag na “interactivity”. Sabihin nating mayroon kang libu-libong mga operasyon at tumatagal ng limang minuto upang matanggap ang mga ito. Ano ang mayroon ang gumagamit sa oras na ito? Spinner? Progreso? Infa tungkol sa kung magkano ang na-upload? Mainam na gumamit ng “aktibong paghihintay” kapag may nakita na ang user sa proseso. Narito ang Resulta:
- Naglo-load ng page
- Hinihiling ang lahat ng mga invoice
- Pagkatapos nito, ang lahat ng mga transaksyon na may mga komisyon para sa mga naisagawang transaksyon ay hinihiling para sa lahat ng mga account. Habang natatanggap ang data, nai-render ito sa browser.
Upang hindi ma-filter ang data sa mga kaganapan sa bawat oras, kinukuha namin ang aming sariling kaganapan para sa bawat account. Ganito:
socket.emit(‘sdk:getOperationsCommissionResult_’ + accountId, { item: data?.items, inProgress: Boolean(nextCursor), });
Narito ang draft na ilulunsad: https://github.com/pskucherov/tcsstat/tree/step3 https://github.com/pskucherov/tcsstat/compare/step2…step3 Moving on. Napakaganda na nabasa mo ang linyang ito!
Pagkalkula at output ng impormasyon ng interes
Depende kung sino ang nangangailangan ng kung anong impormasyon. Samakatuwid, agad kong sasabihin sa iyo ang pangunahing mga nuances na makakatagpo mo.
Paggawa gamit ang mga presyo
Alam ng lahat na nagtatrabaho sa pananalapi na ang mga transaksyon sa pera ay dapat lamang gawin gamit ang mga buong numero. Dahil sa hindi kawastuhan ng mga halaga pagkatapos ng decimal point at ang pinagsama-samang error na may malaking bilang ng mga operasyon. Iyon ang dahilan kung bakit ipinakita ang lahat ng mga presyo sa sumusunod na format ng MoneyValue
patlang | uri | Paglalarawan |
---|---|---|
pera | string | String ISO currency code |
mga yunit | int64 | Ang integer na bahagi ng kabuuan, ay maaaring negatibong numero |
nano | int32 | Fractional na bahagi ng halaga, ay maaaring negatibong numero |
Pinoproseso namin ang mga ito nang hiwalay, pagkatapos ay dinadala ang mga ito sa halaga ng presyo:
quotation.units + quotation.nano / 1e9
Ang halaga ng mga kontrata sa futures
Ang presyo ng futures ay ipinakita sa mga puntos, kapag mayroon kang hinaharap na pera, kailangan mong malaman ang rate. At siyempre ang presyo sa mga puntos at ang hakbang ng presyo. Kapag kinakalkula mo ang kita mula sa mga transaksyon, maaari itong mabaril, dahil. kung kalkulahin mo ang kabuuang halaga sa pamamagitan ng pagpaparami ng presyo sa dami. Dito kailangan mong mag-ingat. Sa ngayon, titingnan natin kung paano ito mangyayari. Nalalapat ito sa mga futures ng pera, sa ibang mga lugar ay ok ang lahat dito.
OTC market
Ang merkado na ito ay may maraming mga kakaiba, kaya pag-aralan natin ang mga operasyon dito nang hiwalay. Kapag sinimulan mo ang pag-synchronize ng mga operasyon, lalabas na kailangan mong dalhin ang figi / ticker sa parehong form upang maitugma nang tama ang instrumento. Kapag sinimulan mo itong i-synchronize sa ulat ng brokerage, lalabas na ang tradeID ng parehong transaksyon ay may mga titik sa simula sa mga transaksyon at wala sila sa ulat ng brokerage. Samakatuwid, hindi sila maihahambing … ahem-ahem … sa paghahambing! Tinugma ko ang oras ng kalakalan, ticker at pagtutugma na ang isang tradeId ay nakapaloob sa isa pa. Tama, hindi ko alam. Kung sino man ang nakatagpo nito at nagmamalasakit dito, pumunta sa isyu o magsimula ng bago.
Mga pagpapatakbo ng matematika sa mga tool
Imposible, nang hindi tumitingin, na magsagawa ng mga operasyong matematika sa buong listahan. Upang hindi magdagdag ng mainit sa malambot, palagi naming sinusuri ang pera at pinoproseso lamang kung sigurado kami na ang pera ay tumutugma, at ang mga puntos ay na-convert sa nais na pera. Gamit ang kaalaman tungkol sa pagtatrabaho sa mga numero ng bangko, kakalkulahin namin ang komisyon na ginastos sa bawat isa sa mga account. Tulad nito: https://github.com/pskucherov/tcsstat/tree/step4 https://github.com/pskucherov/tcsstat/compare/step3…step4
Handa na ang microservice!
https://github.com/pskucherov/tcsstat Bilang isang takdang-aralin, maaari mong suriin kung gumagana ang serbisyo sa isang mabagal na koneksyon, kapag nasira ang mga koneksyon, kapag ang Internet ay hindi nakakonekta, kapag ang mga error o nag-expire na mga limitasyon sa bahagi ng broker.
Mga konklusyon at plano para sa hinaharap
- Natutunan ang tungkol sa mga pangunahing operasyon at pagtatrabaho sa Invest API
- Oras na ginugol ~ 10 oras
- Antas ng kahirapan ~ junior+ / mababang gitna
Kung patuloy mong pinuhin ang microservice, maaaring magkaroon ka ng ganito
https://opexbot.info
Ito ang development ko, para sa mga tamad umintindi, tumakbo at umasa sa sarili nila. Plano kong magdagdag ng analytics doon sa kahilingan ng mga gumagamit. Kung nagustuhan mo ang artikulo, pagkatapos ay mag-subscribe sa aking telegram channel .
Полезная статья. Не могу представить, сколько усилий автора потребовалось, чтобы все описать. Благодарю.