Tinkoff Investments-ის სტატისტიკური სერვისის განვითარების ინსპირატორები იყვნენ:
- სტატია ჰაბრეზე “რას არ ამბობს Tinkoff Investments”
- პლატფორმის მომხმარებლების სურვილების ანალიზი
- სტატია საკომისიოების გაანგარიშების შესახებ .
- რა იქნება განხილული?
- სტატისტიკის სერვისის შემუშავება ეტაპობრივად:
- კავშირი Tinkoff Invest API-სთან
- მონაცემების დახატვა Tinkoff Invest API-დან ბრაუზერში
- საბროკერო ანგარიშების და ტრანზაქციების მიღება
- GetBrokerReport
- თარიღის მიღების მეთოდი მიმდინარე თარიღიდან გამოკლების გათვალისწინებით
- მოხსენების გენერირების მოთხოვნა
- შედეგი:
- GetDividendsForeignIssuer
- GetOperationsByCursor
- საინტერესო ინფორმაციის გაანგარიშება და გამოტანა
- ფასებთან მუშაობა
- ფიუჩერსული კონტრაქტების ღირებულება
- OTC ბაზარი
- მათემატიკური მოქმედებები ხელსაწყოებზე
- მიკროსერვისი მზადაა!
- დასკვნები და სამომავლო გეგმები
- https://opexbot.info
რა იქნება განხილული?
- მხოლოდ გამოყენებითი ნაწილი განვითარების შესახებ.
- რეალური ცოდნა და გამოცდილება, რაც ძალიან მნიშვნელოვანია ფინანსურ ინსტრუმენტებთან მუშაობისას.
- სამუშაო საკითხების მიმოხილვა
ასე რომ, მე მინდა გამოვთვალო ვაჭრობის სტატისტიკა და გავაკეთო ეს მოსახერხებელი გზით.
სტატისტიკის სერვისის შემუშავება ეტაპობრივად:
- კავშირი Tinkoff Invest API-სთან
- მონაცემების დახატვა Tinkoff Invest API-დან ბრაუზერში
- საბროკერო ანგარიშების და ტრანზაქციების მიღება
- საინტერესო ინფორმაციის გაანგარიშება და გამოტანა
- დასკვნები და სამომავლო გეგმები
კავშირი Tinkoff Invest API-სთან
API-სთან დასაკავშირებლად, შეგიძლიათ აიღოთ ნებისმიერი sdk დოკუმენტაციის https://github.com/Tinkoff/investAPI#sdk . ან npm პაკეტი ` tinkoff-sdk-grpc-js` . მნიშვნელოვანია, რომ პაკეტი განახლდეს უახლეს ვერსიაზე დეველოპერების მიერ. Დაინსტალირება
npm და tinkoff-sdk-grpc-js
შემოწმება
const {createSdk } = მოითხოვს(‘tinkoff-sdk-grpc-js’); // ჟეტონი, რომელიც შეიძლება მივიღოთ ასე const TOKEN = ‘YOURAPI’; // აპლიკაციის სახელი, რომლითაც შეგიძლიათ იპოვოთ TCS ჟურნალებში. const appName = ‘tcsstat’; const sdk = createSdk(TOKEN, appName); (ასინქრონული () => { console.log(wait sdk.users.getAccounts()); })();
შედეგი: თქვენი ანგარიშების სია გამოჩნდება კონსოლში. მაგალითად, მოდით გავაანალიზოთ ნიუანსი:
- ანგარიშების ჩამონათვალში არის “საინვესტიციო ბანკი”, რომელთანაც არ შეგიძლიათ იმუშაოთ API-ის გამოყენებით
- გთხოვთ გაითვალისწინოთ, რომ ველები მოდის camelCase-ში, ხოლო დოკუმენტაციაში ეს ველები წარმოდგენილია under_score-ში.
- ასე იქნება ყველგან, ასე რომ თქვენ არ შეგიძლიათ უბრალოდ აიღოთ და დააკოპიროთ ველი დოკუმენტაციადან.
სასარგებლო:
- ამ კოდის ნახვა შეგიძლიათ პროექტის ფილიალში
https://github.com/pskucherov/tcsstat/tree/step1 https://github.com/pskucherov/tcsstat/compare/step1
მონაცემების დახატვა Tinkoff Invest API-დან ბრაუზერში
მე ავიღე next.js და socket.io. ეს არ არის ძლიერი რეკომენდაცია, აირჩიეთ თქვენი შეხედულებისამებრ.
npx create-next-app@latest npm i socket.io socket.io-client
ჩვენ დაუყოვნებლივ გადავდივართ მეგობრობის საფეხურზე შემდეგი+სოკეტ+ინვესტაპი და იხილეთ ამ ნაბიჯის სასარგებლო განყოფილება ყველა დეტალისთვის. მე აღვწერ დეტალებს:
- nodejs (სერვერის) მხარეს არის pages/api/investapi.js ფაილი. სწორედ აქ ვქმნით socket.io სერვერს და ვუკავშირდებით investapi-ს.
- ბრაუზერის (კლიენტის) მხარეს ჩვენ ვუკავშირდებით სერვერს სოკეტის საშუალებით და ვითხოვთ ანგარიშის მონაცემებს ბროკერისგან.
- ჩვენ ვიღებთ მონაცემებს ბროკერისგან სერვერზე, შემდეგ ვუგზავნით კლიენტს. როდესაც ისინი მიიღება კლიენტზე, ისინი ნაჩვენებია ბრაუზერში.
შედეგი: ბრაუზერის კონსოლში ჩვენ ვხედავთ ინფორმაციას ანგარიშების შესახებ. ანუ ბოლო ეტაპზე ჩვენ ვნახეთ ინფორმაცია ანგარიშების შესახებ სერვერის კონსოლში (nodejs), მიმდინარე ეტაპზე ეს ინფორმაცია გადავეცი კლიენტს (ბრაუზერს).
ახლა მოდით გავაკეთოთ ისე, რომ თქვენ შეგიძლიათ აირჩიოთ ანგარიში ბრაუზერიდან და თუ არ არის ნიშანი, მაშინ შეცდომა იგზავნება კონსოლში. ნამუშევარი მარტივია და ახალი არაფერია, ამიტომ ვაძლევ მხოლოდ ბმულებს ვალდებულებებზე
- https://github.com/pskucherov/tcsstat/commit/7e1ac57061e5e971588479015b06d8814d6609a9
- https://github.com/pskucherov/tcsstat/commit/b28ac973a57494f5232589b4cb6b9fb13b8af759
სასარგებლო:
- როგორ შევიძინოთ მეგობრები შემდეგი და სოკეტი, დეტალურად არის აღწერილი აქ .
- მეგობრობის კოდი შემდეგი+სოკეტ+ინვესტაპი:
https://github.com/pskucherov/tcsstat/commit/a443a4ac1bb4f0aa898f638128755fe7391ee381 ვისთვისაც ზემოაღნიშნული რთულია, მაშინ ამ ეტაპზე ვრჩებით და კოდს ვუკავშირდებით. თუ თქვენ გაქვთ შეკითხვები – ჰკითხეთ. https://github.com/pskucherov/tcsstat/tree/step2 https://github.com/pskucherov/tcsstat/compare/step1…step2
საბროკერო ანგარიშების და ტრანზაქციების მიღება
საბროკერო ანგარიშებისა და ტრანზაქციების მიღების სამი მეთოდი არსებობს
თავიდანვე მნიშვნელოვანია იცოდეთ:
- საბროკერო ანგარიში გენერირდება T-3 რეჟიმში, ე.ი. გარიგებები იქ არის ნაჩვენები მათი ფაქტობრივი შესრულების შემდეგ.
- შესაბამისად, თუ თქვენ მოითხოვთ ამ ანგარიშს ბოლო ორი დღის განმავლობაში, ის მზად იქნება სამ დღეში.
- ბოლო დღეების ტრანზაქციების მისაღებად ჩვენ ვიყენებთ ტრანზაქციის მიღების მეთოდს, მაგრამ გახსოვდეთ, რომ მათი ID და შინაარსი შეიძლება შეიცვალოს საბროკერო ანგარიშის გენერირების შემდეგ.
GetBrokerReport
საბროკერო ანგარიშის მისაღებად, თქვენ უნდა აიღოთ ანგარიშის ID, დაწყების თარიღი და ანგარიშის დასრულების თარიღი, მაგრამ არა უმეტეს 31 დღისა. ჩვენ ვუგზავნით მოთხოვნას ანგარიშის გენერირების შესახებ API-ში გენერირებს _broker_report_request- ში, პასუხად ვიღებთ taskId-ს. ამის შემდეგ, ამ taskId-ის გამოყენებით, ჩვენ ვიღებთ მონაცემებს get _broker_report_response-დან.
- თქვენ უნდა შეინახოთ TaskID სამუდამოდ ზუსტად ამ თარიღებისთვის.
- ვინაიდან თუ დაკარგავთ მას, მაშინ მოთხოვნილი თარიღებისთვის მოხსენება პირველად მოვა გენერირების მოთხოვნის საპასუხოდ,
- და მაშინ ის საერთოდ არ მოვა.
[/სპოილერი] დავიწყოთ კოდის წერა
თარიღის მიღების მეთოდი მიმდინარე თარიღიდან გამოკლების გათვალისწინებით
const getDateSubDay = (subDay = 5, start = true) => { const date = new Date(); date.setUTCDate(date.getUTCDate() – subDay); if (დაწყება) { date.setUTCHours(0, 0, 0, 0); } else { date.setUTCHours(23, 59, 59, 999); } დაბრუნების თარიღი; };
მოხსენების გენერირების მოთხოვნა
const brokerReport = await (sdk.operations.getBrokerReport)({ genereBrokerReportRequest: { accountId, from, to, }, });
შედეგი:
- ბრძანების პირველი შესრულების შედეგად ვიღებთ taskId-ს.
- ანგარიშის გენერირება იწყება ბროკერის მხრიდან. როდესაც ის მზად არის, უცნობია, ჩვენ ველოდებით და პერიოდულად ვიღებთ taskId-ს ანგარიშის მოლოდინში.
- რატომ? იმის გამო, რომ თუ ანგარიში არ არის მზად, ის აგდებს შეცდომას. თუ ანგარიში არ არის მზად ბროკერის მხრიდან, მაშინ ეს არის შეცდომა თქვენს კოდში. გთხოვთ, დაამუშავოთ: 30058|INVALID_ARGUMENT|ამოცანა ჯერ არ დასრულებულა, გთხოვთ სცადოთ მოგვიანებით
ანგარიშის მოლოდინისა და მიღების კოდი დაახლოებით ასე გამოიყურება.
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); ლოდინის ტაიმერი (10000); დაბრუნება ელოდება getBrokerResponseByTaskId(taskId, გვერდი); } };
მერე იგივე მაგია ხდება. ჩვენ ვაჩერებთ ჩვენს სკრიპტს, ვიწყებთ თავიდან, ჩვენ არ გვაქვს taskId. ჩვენ ვასრულებთ კოდს taskId მოთხოვნით, მაგრამ აღარ ვიღებთ taskId-ს, არამედ დაუყოვნებლივ ვიღებთ ანგარიშს. მაგია! და ყველაფერი კარგად იქნებოდა, ყოველთვის ასე რომ იყოს. მაგრამ ერთ თვეში მონაცემები საერთოდ არ იქნება. სასარგებლო :
https://github.com/pskucherov/tcsstat/tree/step3.1 https://github.com/pskucherov/tcsstat/compare/step3.1
- თუ ვინმეს შეხვდება ეს, მაშინ კეთილი იყოს თქვენი მობრძანება ამ საკითხში . მას შემდეგ რაც ამ მაგიას შეაკეთებენ, ის ძალას დაკარგავს და რაღაცნაირად განსხვავებული იქნება. მაგრამ ამჟამინდელ მომენტში (03/21/2023) მუშაობს ზუსტად ასე.
GetDividendsForeignIssuer
შეიძლება ვინმემ იფიქროს, რომ მეთოდი წინას მსგავსია და შეგიძლიათ გამოიყენოთ ერთი მეთოდი, რომელშიც მხოლოდ ოპერაციების სახელს შეცვლით. მაგრამ მათ არ გამოიცნეს! იქ დასახელება ძალიან განსხვავებულია როგორც მეთოდებში, ასევე დაბრუნებულ ინფორმაციაში. და გვერდების დათვლა იწყება 0-დან, შემდეგ 1-დან. იმისათვის, რომ ამ ყველაფერში არ დაიბნეთ, უფრო ადვილია ორი განსხვავებული მეთოდის დაწერა. რაც უცნაურია, რადგან მუშაობის ლოგიკა იგივეა. დიდხანს ვიფურთხე, როცა ერთი მეთოდის გაკეთებას ვცდილობდი და კოდი ნაკლები იყო. აქ მაგალითები არ იქნება.
GetOperationsByCursor
ჩემი ფავორიტი სამიდან. მართალია არა ყველაზე ზუსტი, მაგრამ ყველაზე ადეკვატური. ჩვენ ვაკეთებთ მოთხოვნას ანგარიშის შექმნის დასაწყისიდან მაქსიმალურ შესაძლო თარიღამდე (ანგარიშის დახურვა ან მიმდინარე). ვიღებთ პასუხს, ვიღებთ კურსორს და ხელახლა ვითხოვთ, სანამ მონაცემებია. და კოდი უფრო ლაკონურია, ვიდრე ზემოთ მოცემულ მაგალითებში.
const timer = async time => { return new Promise(resolve => setTimeout(resolve, time)); } const getOperationsByCursor = ასინქრონული (sdk, accountId, from, to, cursor = ”) => { try { const reqData = { accountId, from, to, limit: 1000, state: sdk.OperationState.OPERATION_STATE_EXECUTED, გარეშე კომისიები: false: გარეშე ვაჭრობა: ცრუ, ღამისთევის გარეშე: false, კურსორი, }; დაბრუნება ელოდება sdk.operations.getOperationsByCursor(reqData); } catch (e) { await timer (60000); დაბრუნება დაელოდება getOperationsByCursor(sdk, accountId, from, to, კურსორი = ”); } };
გასაშვები პროექტი აქ არის: https://github.com/pskucherov/tcsstat/tree/step3.3 https://github.com/pskucherov/tcsstat/compare/step3.3 ახლა ჩვენ მზად ვართ დავამატოთ მიმღები ოპერაციები ჩვენი აპლიკაცია. თუ გაკეთდა სწორად, მაშინ თქვენ უნდა მიიღოთ საბროკერო ანგარიშები ანგარიშის მთელი არსებობისთვის. და დაკარგული მონაცემებისთვის, იგივე T-3, გადატვირთეთ ოპერაციებიდან. მაგრამ ეს შეიძლება დაიყოს ცალკეულ სტატიაში. ძირითადი ნიუანსებიდან, რომელსაც წააწყდებით, არის ოპერაციების წებო და საბროკერო ანგარიში.
- თუ დღეს მიიღეთ საბროკერო ანგარიში და ტრანზაქციები საჭირო თარიღებისთვის, ჩადეთ ეს ყველაფერი მონაცემთა ბაზაში, მაშინ არანაირი პრობლემა არ არის.
- პრობლემები შეგექმნებათ ხვალ, როდესაც მიიღებთ მონაცემების შემდეგ ნაწილს ანგარიშიდან და ოპერაციებიდან და გადაწყვეტთ მათ სინქრონიზაციას არსებულ მონაცემთა ბაზასთან.
- ბევრი ნიუანსი შეუსაბამობის ან დამუშავების შემდეგ ID-ის შეცვლის შესახებ
- შემდეგ OTC ბაზრისთვის, ID-ები საერთოდ არ ემთხვევა.
- ასევე სინქრონიზაციის ინსტრუმენტების ნიუანსები, რომლებიც ისევ არ ემთხვევა API-ს თავისებურებების გამო. მაგრამ ეს სხვა ამბავია.
მოდით დავამატოთ ჩვენს აპლიკაციას ოპერაციების შესახებ ინფორმაციის მიღება. მთავარი კითხვა იქნება სად დამუშავდება და შეინახება მონაცემები.
- თუ ამას საკუთარ თავზე აკეთებთ, თქვენ მოიხმართ იგივე მონაცემებს სხვადასხვა მოწყობილობებიდან. შემდეგ თქვენ უნდა დაამუშავოთ და შეინახოთ მონაცემები სერვერზე.
- თუ თქვენ გაქვთ ბევრი სხვადასხვა მონაცემი მოხმარებული სხვადასხვა მომხმარებლის მიერ, მაშინ უნდა გადაწყვიტოთ რა არის უფრო მნიშვნელოვანი: მომხმარებლების სიჩქარე თუ რკინის დაზოგვა თქვენს მხარეს. ვისაც აქვს უსასრულო რაოდენობის აპარატურა, ითვლის ყველაფერს თავის სერვერზე და ხდის მას სუპერ სწრაფს მომხმარებლებისთვის, დაზოგავს მომხმარებლის რესურსებს, როგორიცაა ბატარეა და ტრაფიკი, რაც ძალიან მნიშვნელოვანია ტელეფონებზე.
თავის მხრივ, ბრაუზერში დათვლა პრინციპში არ არის ყველაზე ოპტიმალური გადაწყვეტა. ამიტომ, რაც არ არის ძვირი, ჩვენ განვიხილავთ ჩვენს სერვერზე. დანარჩენს კლიენტს ვუტოვებთ. ძალიან მინდა ავიღო და გამოვთვალო საკომისიო სერვერზე. მაგრამ აქ მოდის ნიუანსი სახელწოდებით “ინტერაქტიულობა”. ვთქვათ, თქვენ გაქვთ ათასობით ოპერაცია და მათ მიღებას ხუთი წუთი სჭირდება. რა ექნება ამ დროს მომხმარებელს? სპინერი? პროგრესი? ინფორმაცია რამდენი იყო ატვირთული? იდეალურია „აქტიური ლოდინის“ გამოყენება, როდესაც ამ პროცესში მომხმარებელი უკვე რაღაცას ხედავდა. აი შედეგი:
- გვერდის ჩატვირთვა
- ყველა ინვოისი მოთხოვნილია
- ამის შემდეგ, შესრულებული ტრანზაქციების საკომისიოებთან ყველა ტრანზაქცია მოითხოვება ყველა ანგარიშზე. როგორც კი მონაცემები მიიღება, ის გადაიცემა ბრაუზერში.
იმისათვის, რომ არ გავფილტროთ მონაცემები მოვლენებში ყოველ ჯერზე, ჩვენ ვიღებთ საკუთარ მოვლენას თითოეული ანგარიშისთვის. Ამგვარად:
socket.emit(‘sdk:getOperationsCommissionResult_’ + accountId, { ელემენტი: data?.items, inProgress: Boolean(nextCursor), });
გასაშვები პროექტი აქ არის: https://github.com/pskucherov/tcsstat/tree/step3 https://github.com/pskucherov/tcsstat/compare/step2…step3 წინსვლა. კარგია, რომ წაიკითხეთ ეს სტრიქონი!
საინტერესო ინფორმაციის გაანგარიშება და გამოტანა
დამოკიდებულია ვის რა ინფორმაცია სჭირდება. ამიტომ, მე მაშინვე გეტყვით მთავარ ნიუანსებს, რომლებსაც წააწყდებით.
ფასებთან მუშაობა
ყველამ, ვინც ფინანსებთან მუშაობს, იცის, რომ ფულადი ტრანზაქციები უნდა განხორციელდეს მხოლოდ მთელი რიცხვებით. ათობითი წერტილის შემდეგ მნიშვნელობების უზუსტობის გამო და ოპერაციების დიდი რაოდენობით კუმულაციური შეცდომის გამო. ამიტომ ყველა ფასი წარმოდგენილია შემდეგი MoneyValue ფორმატში
ველი | ტიპი | აღწერა |
---|---|---|
ვალუტა | სიმებიანი | სიმებიანი ISO ვალუტის კოდი |
ერთეულები | int64 | ჯამის მთელი ნაწილი შეიძლება იყოს უარყოფითი რიცხვი |
ნანო | int32 | თანხის წილადი ნაწილი, შეიძლება იყოს უარყოფითი რიცხვი |
ჩვენ მათ ცალ-ცალკე ვამუშავებთ, შემდეგ მივყავართ ფასის ღირებულებამდე:
quotation.unit + quotation.nano / 1e9
ფიუჩერსული კონტრაქტების ღირებულება
ფიუჩერსების ფასი წარმოდგენილია ქულებით, როცა ვალუტის ფიუჩერსი გაქვთ, კურსი უნდა იცოდეთ. და რა თქმა უნდა ფასი ქულებში და ფასის ნაბიჯი. როდესაც თქვენ ითვლით მოგებას ტრანზაქციებიდან, ეს შეიძლება სროლა, რადგან. თუ მთლიან თანხას გამოთვლით ფასის რაოდენობაზე გამრავლებით. აქ თქვენ უნდა იყოთ ფრთხილად. ჯერ-ჯერობით ვნახოთ როგორ წავა. ეს ეხება ვალუტის ფიუჩერსებს, სხვა ადგილებში ყველაფერი წესრიგშია.
OTC ბაზარი
ამ ბაზარს ბევრი თავისებურება აქვს, ამიტომ ცალ-ცალკე შევისწავლოთ მასზე ოპერაციები.როდესაც დაიწყებთ ოპერაციების სინქრონიზაციას, აღმოჩნდება, რომ თქვენ უნდა მოიყვანოთ ფიგი/ტიკერი იმავე ფორმაში, რათა სწორად შეესაბამებოდეს ინსტრუმენტს. როდესაც დაიწყებთ ამის სინქრონიზაციას საბროკერო ანგარიშთან, აღმოჩნდება, რომ იგივე ტრანზაქციის სავაჭრო ID-ს აქვს ასოები ტრანზაქციის დასაწყისში და ისინი არ არიან საბროკერო ანგარიშში. მაშასადამე, მათი შედარება შეუძლებელია… აჰემ-აჰემ… შედარებით! მე დავამთხვიე ვაჭრობის დრო, ტიკერი და შესატყვისი, რომ ერთი tradeId შეიცავს მეორეში. მართალია, არ ვიცი. ვინც ამას წააწყდება და ვისაც ეს აინტერესებს, მიდით საკითხზე ან დაიწყეთ ახალი.
მათემატიკური მოქმედებები ხელსაწყოებზე
შეუძლებელია მათემატიკური ოპერაციების შესრულება მთელი სიით ნახვის გარეშე. იმისათვის, რომ არ დავამატოთ თბილი რბილის, ჩვენ ყოველთვის ვამოწმებთ ვალუტას და ვამუშავებთ მხოლოდ იმ შემთხვევაში, თუ დარწმუნებული ვართ, რომ ვალუტა ემთხვევა და ქულები გარდაიქმნება სასურველ ვალუტაში. ბანკის ნომრებთან მუშაობის ცოდნით შეიარაღებული, ჩვენ გამოვთვლით თითოეულ ანგარიშზე დახარჯულ საკომისიოს. მოიწონეთ ეს: https://github.com/pskucherov/tcsstat/tree/step4 https://github.com/pskucherov/tcsstat/compare/step3…step4
მიკროსერვისი მზადაა!
https://github.com/pskucherov/tcsstat როგორც საშინაო დავალება, შეგიძლიათ შეამოწმოთ, მუშაობს თუ არა სერვისი ნელი კავშირით, კავშირების გაწყვეტისას, ინტერნეტის გათიშვისას, ბროკერის მხრიდან შეცდომების ან ვადაგასული ლიმიტების დროს.
დასკვნები და სამომავლო გეგმები
- გაეცანით საბაზისო ოპერაციებსა და Invest API-სთან მუშაობას
- გატარებული დრო ~ 10 საათი
- სირთულის დონე ~ უმცროსი+ / დაბალი საშუალო
თუ გააგრძელებთ მიკროსერვისის დახვეწას, შეიძლება მსგავსი რამ დასრულდეს
https://opexbot.info
ეს არის ჩემი განვითარება, მათთვის, ვისაც ძალიან ეზარება საკუთარი თავის გაგება, გაშვება და იმედი. მომხმარებლების მოთხოვნით იქ ანალიტიკის დამატებას ვგეგმავ. თუ მოგეწონათ სტატია, გამოიწერეთ ჩემი ტელეგრამის არხი .
Полезная статья. Не могу представить, сколько усилий автора потребовалось, чтобы все описать. Благодарю.