Những người truyền cảm hứng đằng sau sự phát triển của dịch vụ thống kê cho Tinkoff Investments là:
- bài báo trên Habré “Điều mà Tinkoff Investments không nói”
- phân tích mong muốn của người dùng nền tảng
- một bài báo về cách tính tiền hoa hồng .
- Những gì sẽ được thảo luận?
- Từng bước phát triển dịch vụ thống kê:
- Kết nối với API Tinkoff Invest
- Vẽ dữ liệu từ API Tinkoff Invest trong trình duyệt
- Nhận báo cáo môi giới và giao dịch
- NhậnBáo cáo Môi giới
- Phương pháp lấy ngày, có tính đến phép trừ từ ngày hiện tại
- Yêu cầu tạo báo cáo
- Kết quả:
- Nhận cổ tứcNhà phát hành nước ngoài
- GetOperationsByCursor
- Tính toán và xuất thông tin quan tâm
- Làm việc với giá cả
- Chi phí hợp đồng tương lai
- thị trường OTC
- Các phép toán trên công cụ
- Dịch vụ vi mô đã sẵn sàng!
- Kết luận và kế hoạch cho tương lai
- https://opexbot.info
Những gì sẽ được thảo luận?
- Chỉ có phần áp dụng về phát triển.
- Kiến thức và kinh nghiệm thực tế, những điều rất quan trọng khi làm việc với các công cụ tài chính.
- Tổng quan về các vấn đề cần giải quyết
Vì vậy, tôi muốn tính toán số liệu thống kê thương mại và thực hiện nó một cách thuận tiện.
Từng bước phát triển dịch vụ thống kê:
- Kết nối với API Tinkoff Invest
- Vẽ dữ liệu từ API Tinkoff Invest trong trình duyệt
- Nhận báo cáo môi giới và giao dịch
- Tính toán và xuất thông tin quan tâm
- Kết luận và kế hoạch cho tương lai
Kết nối với API Tinkoff Invest
Để kết nối với API, bạn có thể lấy bất kỳ sdk nào từ tài liệu https://github.com/Tinkoff/investAPI#sdk . Hoặc gói npm ` tinkoff-sdk-grpc-js` . Điều quan trọng là gói được các nhà phát triển cập nhật lên phiên bản mới nhất. Cài đặt
npm tôi tinkoff-sdk-grpc-js
kiểm tra
const { createSdk } = yêu cầu (‘tinkoff-sdk-grpc-js’); // Mã thông báo có thể nhận được như thế này const TOKEN = ‘YOURAPI’; // Tên của ứng dụng mà bạn có thể được tìm thấy trong nhật ký TCS. const appName = ‘tcsstat’; const sdk = createSdk(TOKEN, appName); (async() => { console.log(đang chờ sdk.users.getAccounts()); })();
Kết quả: một danh sách các tài khoản của bạn sẽ được hiển thị trong bảng điều khiển. Ví dụ: hãy phân tích các sắc thái:
- Trong danh sách tài khoản có “Ngân hàng đầu tư” mà bạn không thể làm việc với API
- Xin lưu ý rằng các trường có trong camelCase, trong khi trong tài liệu, các trường này được trình bày dưới dạng under_score.
- Nó sẽ giống như thế này ở khắp mọi nơi, vì vậy bạn không thể lấy và sao chép một trường từ tài liệu.
Hữu ích:
- Bạn có thể tìm thấy mã này trong nhánh dự án
https://github.com/pskucherov/tcsstat/tree/step1 https://github.com/pskucherov/tcsstat/compare/step1
Vẽ dữ liệu từ API Tinkoff Invest trong trình duyệt
Tôi lấy next.js và socket.io. Đây không phải là một khuyến nghị mạnh mẽ, hãy chọn theo quyết định của bạn.
npx tạo-next-app@ npm mới nhất i socket.io socket.io-client
Chúng tôi ngay lập tức chuyển sang bước kết bạn tiếp theo+socket+investapi và xem phần Hữu ích của bước này để biết tất cả các chi tiết. Tôi sẽ mô tả chi tiết:
- Phía nodejs (server) có file pages/api/investapi.js. Đây là nơi chúng tôi tạo máy chủ socket.io và kết nối vớiinvestapi.
- Về phía trình duyệt (máy khách), chúng tôi kết nối với máy chủ thông qua một ổ cắm và yêu cầu dữ liệu tài khoản từ nhà môi giới.
- Chúng tôi nhận dữ liệu từ nhà môi giới trên máy chủ, sau đó gửi nó cho khách hàng. Khi chúng được nhận trên máy khách, chúng sẽ được hiển thị trong trình duyệt.
Kết quả: trong bảng điều khiển trình duyệt, chúng ta có thể xem thông tin về tài khoản. Tức là ở bước trước chúng ta đã xem thông tin về các tài khoản trong server console (nodejs), ở bước hiện tại chúng ta đã chuyển thông tin này cho client (browser).
Bây giờ, hãy làm cho nó để bạn có thể chọn một tài khoản từ trình duyệt và nếu không có mã thông báo, thì một lỗi sẽ được gửi đến bảng điều khiển. Công việc đơn giản và không có gì mới nên mình chỉ đưa link tới các commit
- https://github.com/pskucherov/tcsstat/commit/7e1ac57061e5e971588479015b06d8814d6609a9
- https://github.com/pskucherov/tcsstat/commit/b28ac973a57494f5232589b4cb6b9fb13b8af759
Hữu ích:
- Cách kết bạn next và socket được mô tả chi tiết tại đây .
- Mã tình bạn next+socket+investapi:
https://github.com/pskucherov/tcsstat/commit/a443a4ac1bb4f0aa898f638128755fe7391ee381 Đối với ai khó khăn ở trên, thì chúng tôi vẫn ở giai đoạn này và xử lý mã. Nếu bạn có câu hỏi, cứ tự nhiên. https://github.com/pskucherov/tcsstat/tree/step2 https://github.com/pskucherov/tcsstat/compare/step1…step2
Nhận báo cáo môi giới và giao dịch
Có ba phương pháp để nhận báo cáo môi giới và giao dịch
Ngay từ đầu, điều quan trọng là phải biết:
- Báo cáo môi giới được tạo ở chế độ T-3, tức là giao dịch được hiển thị ở đó sau khi thực hiện thực tế của họ.
- Theo đó, nếu bạn yêu cầu báo cáo này trong hai ngày qua, nó sẽ sẵn sàng sau ba ngày.
- Để nhận giao dịch cho những ngày qua, chúng tôi sử dụng phương thức nhận giao dịch, nhưng hãy nhớ rằng id và nội dung của chúng có thể thay đổi sau khi báo cáo môi giới được tạo.
NhậnBáo cáo Môi giới
Để lấy báo cáo môi giới, bạn cần lấy id tài khoản, ngày bắt đầu và ngày kết thúc báo cáo, nhưng không quá 31 ngày. Chúng tôi gửi yêu cầu tạo báo cáo tới API trong tạo _broker_report_request , nhận được taskId trong phản hồi. Sau đó, sử dụng taskId này, chúng tôi lấy dữ liệu từ get _broker_report_response.
- Bạn cần lưu TaskID vĩnh viễn chính xác cho những ngày này.
- Vì nếu bạn làm mất nó, thì đối với những ngày được yêu cầu, trước tiên báo cáo sẽ đến để đáp ứng yêu cầu tạo,
- Và sau đó nó sẽ không đến chút nào.
Phương pháp lấy ngày, có tính đến phép trừ từ ngày hiện tại
const getDateSubDay = (subDay = 5, start = true) => { const date = new Date(); date.setUTCDate(date.getUTCDate() – subDay); nếu (bắt đầu) { date.setUTCHours(0, 0, 0, 0); } khác { date.setUTCHours(23, 59, 59, 999); } ngày trở lại; };
Yêu cầu tạo báo cáo
const brokerReport = đang chờ (sdk.operations.getBrokerReport)({ generateBrokerReportRequest: { accountId, from, to, }, });
Kết quả:
- Kết quả của lần thực thi lệnh đầu tiên, chúng tôi nhận được taskId.
- Báo cáo bắt đầu được tạo ở phía nhà môi giới. Chưa biết khi nào nó sẵn sàng, chúng tôi chờ đợi và định kỳ lấy taskId để chờ báo cáo.
- Tại sao? Bởi vì nếu báo cáo chưa sẵn sàng, nó sẽ báo lỗi. Nếu báo cáo chưa sẵn sàng từ phía nhà môi giới, thì đây là lỗi trong mã của bạn. Vui lòng xử lý: 30058|INVALID_ARGUMENT|tác vụ chưa hoàn thành, vui lòng thử lại sau
Mã chờ và nhận báo cáo trông như thế này.
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, }, }); } bắt (e) { console.log(‘chờ’, e); chờ hẹn giờ (10000); trả về đang chờ getBrokerResponseByTaskId(taskId, trang); } };
Sau đó, điều kỳ diệu tương tự xảy ra. Chúng tôi dừng tập lệnh của mình, bắt đầu lại tập lệnh, chúng tôi không có taskId. Chúng tôi thực thi mã với yêu cầu taskId, nhưng chúng tôi không còn nhận được taskId nữa mà ngay lập tức báo cáo. Ảo thuật! Và mọi thứ sẽ ổn nếu nó luôn như thế này. Nhưng trong một tháng sẽ không có dữ liệu nào cả. hữu ích :
https://github.com/pskucherov/tcsstat/tree/step3.1 https://github.com/pskucherov/tcsstat/compare/step3.1
- Nếu ai đó gặp vấn đề này, thì chào mừng bạn đến với vấn đề này . Sau khi họ sửa chữa phép thuật này, nó sẽ mất đi sức mạnh và sẽ khác đi theo một cách nào đó. Nhưng tại thời điểm hiện tại (21/03/2023) nó vẫn hoạt động như vậy.
Nhận cổ tứcNhà phát hành nước ngoài
Ai đó có thể nghĩ rằng phương pháp này tương tự như phương pháp trước và bạn có thể sử dụng một phương pháp duy nhất mà bạn chỉ thay đổi tên của các thao tác. Nhưng họ đã không đoán! Việc đặt tên ở đó rất khác nhau cả về phương thức và thông tin trả về. Và số trang bắt đầu từ 0, sau đó từ 1. Để không bị nhầm lẫn trong tất cả những điều này, việc viết hai phương thức khác nhau sẽ dễ dàng hơn. Điều đó thật kỳ lạ, bởi vì logic của công việc là như nhau. Tôi đã phàn nàn rất lâu khi cố gắng tạo một phương thức và có ít mã hơn. Sẽ không có ví dụ nào ở đây.
GetOperationsByCursor
Yêu thích của tôi trong ba. Mặc dù không phải là chính xác nhất, nhưng đầy đủ nhất. Chúng tôi đưa ra yêu cầu từ khi bắt đầu tạo tài khoản đến ngày tối đa có thể (đóng tài khoản hoặc tài khoản hiện tại). Chúng tôi nhận được câu trả lời, lấy con trỏ và yêu cầu lại miễn là có dữ liệu. Và mã ngắn gọn hơn trong các ví dụ trên.
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, không có Giao dịch: sai, không có Đêm: sai, con trỏ, }; trả về đang chờ sdk.operations.getOperationsByCursor(reqData); } bắt (e) { bộ đếm thời gian chờ (60000); quay lại chờ getOperationsByCursor(sdk, accountId, from, to, cursor = ”); } };
Bản nháp để chạy có tại đây: https://github.com/pskucherov/tcsstat/tree/step3.3 https://github.com/pskucherov/tcsstat/compare/step3.3 Bây giờ chúng tôi đã sẵn sàng để thêm các hoạt động nhận vào ứng dụng của chúng tôi. Nếu được thực hiện chính xác, thì bạn cần nhận báo cáo môi giới cho toàn bộ sự tồn tại của tài khoản. Và đối với dữ liệu bị thiếu, những chiếc T-3 đó, hãy tải lại từ các hoạt động. Nhưng điều này có thể được tách thành một bài viết riêng biệt. Trong số các sắc thái chính mà bạn sẽ gặp phải là kết dính hoạt động và báo cáo môi giới.
- Nếu hôm nay bạn nhận được báo cáo môi giới và giao dịch cho những ngày cần thiết, hãy đưa tất cả vào cơ sở dữ liệu, thì không có vấn đề gì.
- Bạn sẽ gặp sự cố vào ngày mai khi nhận được phần dữ liệu tiếp theo từ báo cáo và hoạt động và quyết định đồng bộ hóa chúng với cơ sở dữ liệu hiện có.
- Rất nhiều sắc thái về việc không khớp hoặc thay đổi id sau khi xử lý
- Sau đó, đối với thị trường OTC, id hoàn toàn không khớp.
- Cũng như các sắc thái của các công cụ đồng bộ hóa, một lần nữa không trùng khớp do đặc thù của API. Nhưng đó là một câu truyện khác.
Hãy thêm nhận thông tin về các hoạt động vào ứng dụng của chúng ta. Câu hỏi chính sẽ là dữ liệu sẽ được xử lý và lưu trữ ở đâu.
- Nếu bạn làm điều đó cho chính mình, bạn sẽ sử dụng cùng một dữ liệu từ các thiết bị khác nhau. Sau đó, bạn cần xử lý và lưu trữ dữ liệu trên máy chủ.
- Nếu bạn có nhiều dữ liệu khác nhau được sử dụng bởi nhiều người dùng khác nhau, thì bạn cần quyết định điều gì quan trọng hơn: tốc độ của người dùng hay tiết kiệm sắt từ phía bạn. Bất kỳ ai có khả năng chi trả vô số phần cứng đều đếm mọi thứ trên máy chủ của mình và làm cho nó siêu nhanh cho người dùng, tiết kiệm tài nguyên của người dùng, chẳng hạn như pin và lưu lượng truy cập, điều rất quan trọng trên điện thoại.
Đổi lại, đếm trong trình duyệt không phải là giải pháp tối ưu nhất về nguyên tắc. Do đó, những gì không đắt tiền, chúng tôi xem xét nó trên máy chủ của chúng tôi. Chúng tôi để phần còn lại cho khách hàng. Tôi thực sự muốn nhận và tính hoa hồng trên máy chủ. Nhưng ở đây có sắc thái gọi là “tương tác”. Giả sử bạn có hàng nghìn thao tác và phải mất năm phút để nhận được chúng. Người dùng sẽ có gì vào lúc này? Con quay? Tiến triển? Infa về bao nhiêu đã được tải lên? Lý tưởng nhất là sử dụng “chờ tích cực” khi người dùng trong quá trình này có thể đã nhìn thấy thứ gì đó. Đây là kết quả:
- tải trang
- Tất cả các hóa đơn được yêu cầu
- Sau đó, tất cả các giao dịch có hoa hồng cho các giao dịch được thực hiện được yêu cầu cho tất cả các tài khoản. Khi dữ liệu được nhận, nó sẽ được hiển thị trong trình duyệt.
Để không lọc dữ liệu trong các sự kiện mỗi lần, chúng tôi lấy sự kiện của riêng mình cho từng tài khoản. Như thế này:
socket.emit(‘sdk:getOperationsCommissionResult_’ + accountId, { item: data?.items, inProgress: Boolean(nextCursor), });
Bản nháp để khởi chạy có tại đây: https://github.com/pskucherov/tcsstat/tree/step3 https://github.com/pskucherov/tcsstat/compare/step2…step3 Tiếp tục. Thật tuyệt khi bạn đã đọc đến dòng này!
Tính toán và xuất thông tin quan tâm
Phụ thuộc vào những người cần thông tin gì. Do đó, tôi ngay lập tức cho bạn biết những sắc thái chính mà bạn sẽ gặp phải.
Làm việc với giá cả
Mọi người làm việc trong lĩnh vực tài chính đều biết rằng các giao dịch tiền chỉ nên được thực hiện với các số nguyên. Do sự không chính xác của các giá trị sau dấu thập phân và lỗi tích lũy với một số lượng lớn các hoạt động. Đó là lý do tại sao tất cả giá được trình bày theo định dạng MoneyValue sau đây
cánh đồng | kiểu | Sự miêu tả |
---|---|---|
tiền tệ | sợi dây | Chuỗi mã tiền tệ ISO |
các đơn vị | int64 | Phần nguyên của tổng, có thể là số âm |
nano | int32 | Phần phân số của số tiền, có thể là số âm |
Chúng tôi xử lý chúng một cách riêng biệt, sau đó đưa chúng về giá trị:
báo giá.đơn vị + báo giá.nano / 1e9
Chi phí hợp đồng tương lai
Giá của hợp đồng tương lai được trình bày theo điểm, khi bạn có một hợp đồng tương lai tiền tệ, bạn cần biết tỷ giá. Và tất nhiên giá theo điểm và bước giá. Khi bạn tính toán lợi nhuận từ các giao dịch, điều này có thể xảy ra, bởi vì. nếu bạn tính tổng số tiền bằng cách nhân giá với số lượng. Ở đây bạn cần phải cẩn thận. Bây giờ, chúng ta sẽ xem nó diễn ra như thế nào. Điều này áp dụng cho tương lai tiền tệ, ở những nơi khác, mọi thứ đều ổn với điều này.
thị trường OTC
Thị trường này có rất nhiều đặc thù, vì vậy chúng ta hãy nghiên cứu riêng về các hoạt động trên nó, khi bạn bắt đầu đồng bộ hóa các hoạt động, hóa ra bạn cần đưa figi / ticker về cùng một biểu mẫu để khớp chính xác công cụ. Khi bạn bắt đầu đồng bộ hóa điều này với báo cáo môi giới, nó sẽ chỉ ra rằng ID giao dịch của cùng một giao dịch có các chữ cái ở đầu các giao dịch và chúng không có trong báo cáo môi giới. Do đó, chúng không thể được so sánh … ahem-ahem … bằng cách so sánh! Tôi đã khớp thời gian giao dịch, mã đánh dấu và khớp một ID giao dịch được chứa trong một ID giao dịch khác. Đúng, tôi không biết. Bất cứ ai gặp phải điều này và ai quan tâm đến nó, hãy đến với vấn đề này hoặc bắt đầu một vấn đề mới.
Các phép toán trên công cụ
Không thể thực hiện các phép toán với toàn bộ danh sách mà không cần nhìn. Để không thêm ấm vào mềm, chúng tôi luôn kiểm tra đơn vị tiền tệ và chỉ xử lý nếu chúng tôi chắc chắn rằng đơn vị tiền tệ khớp và điểm được chuyển đổi thành đơn vị tiền tệ mong muốn. Được trang bị kiến thức về cách làm việc với số ngân hàng, chúng tôi sẽ tính toán hoa hồng chi cho từng tài khoản. Như thế này: https://github.com/pskucherov/tcsstat/tree/step4 https://github.com/pskucherov/tcsstat/compare/step3…step4
Dịch vụ vi mô đã sẵn sàng!
https://github.com/pskucherov/tcsstat Như một bài tập về nhà, bạn có thể kiểm tra xem dịch vụ có hoạt động với kết nối chậm hay không, khi kết nối bị hỏng, khi Internet bị ngắt kết nối, khi lỗi hoặc giới hạn hết hạn từ phía nhà môi giới.
Kết luận và kế hoạch cho tương lai
- Tìm hiểu về các hoạt động cơ bản và làm việc với Invest API
- Thời gian sử dụng ~ 10 giờ
- Độ khó ~ sơ cấp + / trung bình thấp
Nếu bạn tiếp tục tinh chỉnh microservice, bạn có thể nhận được kết quả như thế này
https://opexbot.info
Đây là mình phát triển, dành cho những bạn nào lười hiểu, tự chạy đi tính lại. Tôi dự định thêm các phân tích ở đó theo yêu cầu của người dùng. Nếu bạn thích bài viết, thì hãy đăng ký kênh telegram của tôi .
Полезная статья. Не могу представить, сколько усилий автора потребовалось, чтобы все описать. Благодарю.