Tinkoff Investments の統計サービスの開発の背後にあるインスピレーションは次のとおりです。
- Habréに関する記事「Tinkoff Investmentsが言っていないこと」
- プラットフォームユーザーの要望の分析
- コミッションの計算に関する記事。
何が議論されますか?
- 開発に関しては応用部分のみ。
- 金融商品を扱う上で非常に重要な真の知識と経験。
- 取り組む課題の概要
だから、私は貿易統計を計算し、それを便利な方法で行いたい.
統計サービスを段階的に開発する:
- Tinkoff Invest APIへの接続
- ブラウザーでの Tinkoff Invest API からのデータの描画
- 仲介レポートと取引の受け取り
- 興味のある情報の計算と出力
- 結論と今後の計画
Tinkoff Invest APIへの接続
API に接続するには、ドキュメントhttps://github.com/Tinkoff/investAPI#sdkから任意の SDK を取得できます。または npm パッケージ ` tinkoff-sdk-grpc-js `。開発者がパッケージを最新バージョンに更新することが重要です。 インストール
npm とtinkoff-sdk-grpc-js
チェック中
const { createSdk } = require(‘tinkoff-sdk-grpc-js’); //このように取得できるトークン const TOKEN = ‘YOURAPI’; // TCS ログで見つけることができるアプリケーションの名前。 const appName = ‘tcsstat’; const sdk = createSdk(TOKEN, appName); (async () => { console.log(await 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
すぐにフレンドシップ ステップ next+socket+investapi に進みます。すべての詳細については、このステップの 便利なセクションを参照してください。 詳細を説明します。
- nodejs (サーバー) 側には、pages/api/investapi.js ファイルがあります。これは、socket.io サーバーを作成し、investapi に接続する場所です。
- ブラウザー (クライアント) 側では、ソケットを介してサーバーに接続し、ブローカーからアカウント データを要求します。
- サーバー上のブローカーからデータを受け取り、それをクライアントに送信します。クライアントで受信すると、ブラウザに表示されます。
結果: ブラウザ コンソールに、アカウントに関する情報が表示されます。 つまり、最後のステップでは、サーバー コンソール (nodejs) でアカウントに関する情報を確認しました。現在のステップでは、この情報をクライアント (ブラウザー) に転送しました。
ブラウザからアカウントを選択できるようにして、トークンがない場合はコンソールにエラーを送信します。作業はシンプルで新しいものではないので、コミットへのリンクのみを提供します
- https://github.com/pskucherov/tcsstat/commit/7e1ac57061e5e971588479015b06d8814d6609a9
- https://github.com/pskucherov/tcsstat/commit/b28ac973a57494f5232589b4cb6b9fb13b8af759
使える:
- 次にフレンドを作る方法とソケットについては、こちらで詳しく説明しています。
- 友情コード next+socket+investapi:
https://github.com/pskucherov/tcsstat/commit/a443a4ac1bb4f0aa898f638128755fe7391ee381 上記が難しい場合は、この段階にとどまってコードを処理します。ご不明な点がございましたら、お問い合わせください。 https://github.com/pskucherov/tcsstat/tree/step2 https://github.com/pskucherov/tcsstat/compare/step1…step2
仲介レポートと取引の受け取り
仲介レポートと取引を受け取るには3つの方法があります
最初から、次のことを知っておくことが重要です。
- 仲介レポートは T-3 モードで生成されます。取引は、実際の実行後にそこに表示されます。
- したがって、過去 2 日間のこのレポートをリクエストすると、3 日後には準備が整います。
- 過去数日間のトランザクションを取得するには、トランザクションを受信する方法を使用しますが、仲介レポートが生成された後に ID とコンテンツが変更される可能性があることに注意してください。
GetBrokerReport
仲介レポートを取得するには、アカウント ID、レポートの開始日と終了日を取得する必要がありますが、31 日以内です。generate _broker_report_requestでレポートを生成するリクエストを API に送信し、応答で taskId を取得します。その後、この taskId を使用して、get _broker_report_response からデータを取得します。[スポイラー タイトル = ドキュメントによると、実際にはニュアンスがあります。手を見てください:”]
- これらの日付について、TaskID を完全に保存する必要があります。
- 紛失した場合、要求された日付については生成要求に応答して最初にレポートが来るため、
- そしたら全然来ない。
[/spoiler]コードを書き始めましょう
現在の日付からの減算を考慮した日付の取得方法
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)({ generateBrokerReportRequest: { 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); await タイマー (10000); return await getBrokerResponseByTaskId(taskId, page); } };
その後、同じ魔法が起こります。スクリプトを停止し、再度開始します。タスク ID はありません。taskId リクエストでコードを実行しますが、もはや taskId を取得しませんが、すぐにレポートを取得します。魔法!そして、それがいつもこのようであれば、すべてがうまくいくでしょう。しかし、1か月でデータがまったくなくなります。 便利:
https://github.com/pskucherov/tcsstat/tree/step3.1 https://github.com/pskucherov/tcsstat/compare/step3.1
- 誰かがこれに遭遇した場合は、問題へようこそ。彼らがこの魔法を修復した後、それはその力を失い、どこか違ったものになる. しかし、現時点 (2023 年 3 月 21 日) では、そのように動作します。
GetDividendsForeignIssuer
この方法は前の方法と似ていると考える人がいるかもしれません。操作の名前を変更するだけで、単一の方法を使用できます。しかし、彼らは推測しませんでした! そこでの命名は、メソッドと返される情報の両方で大きく異なります。そして、ページ数は 0 から始まり、次に 1 から始まります。これらすべてで混乱しないように、2 つの異なるメソッドを記述する方が簡単です。これは奇妙なことです。仕事のロジックは同じです。 1 つのメソッドを作成しようとすると、コードが少なくなり、長い間唾を吐きました。ここには例はありません。
GetOperationsByCursor
三人の中で一番好き。最も正確ではありませんが、最も適切です。アカウントの作成開始から可能な限り最大の日付(アカウントの閉鎖または現在のアカウントの閉鎖)までリクエストを行います。答えを取得し、カーソルを取得して、データがある限り再リクエストします。 また、コードは上記の例よりも簡潔です。
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, カーソル, }; return await sdk.operations.getOperationsByCursor(reqData); } catch (e) { await timer(60000); return await getOperationsByCursor(sdk, accountId, from, to, cursor = ”); } };
実行するドラフトはこちら: https://github.com/pskucherov/tcsstat/tree/step3.3 https://github.com/pskucherov/tcsstat/compare/step3.3 これで、受信操作をに追加する準備ができました私たちのアプリケーション。正しく行われた場合は、アカウントの存在全体の仲介レポートを取得する必要があります. 欠落しているデータについては、同じ T-3 が作戦から再装填されます。しかし、これは別の記事に分けることができます。 あなたが遭遇する主なニュアンスの1つは、操作と仲介レポートを接着することです.
- 今日、必要な日付の仲介レポートとトランザクションを受け取った場合、それをすべてデータベースに入れれば、問題はありません。
- 明日、レポートと操作からデータの次の部分を受け取り、それらを既存のデータベースと同期することを決定すると、問題が発生します。
- 処理後の ID の不一致または変更に関する多くのニュアンス
- 次に、OTC 市場では、ID がまったく一致しません。
- APIの特殊性のために、再び一致しない楽器の同期のニュアンスと同様に。しかし、それは別の話です。
操作に関する情報の取得をアプリケーションに追加しましょう。 主な問題は、データが処理され、保存される場所です。
- 自分で行う場合、異なるデバイスから同じデータを消費します。次に、データを処理してサーバーに保存する必要があります。
- 多くの異なるユーザーが多くの異なるデータを消費している場合は、どちらがより重要かを決定する必要があります: ユーザーの速度またはあなたの側の鉄の節約. 無限の量のハードウェアを購入できる人は誰でも、サーバー上のすべてのものを数えて、ユーザーにとって超高速にし、バッテリーやトラフィックなどのユーザー リソースを節約します。これは電話にとって非常に重要です。
同様に、ブラウザでカウントすることは、原則として最適なソリューションではありません。したがって、高価ではないものは、サーバー上で検討しています。あとはお客様にお任せします。 私は本当にサーバー上の手数料を取って計算したい. しかし、ここで「双方向性」と呼ばれるニュアンスが生まれます。何千もの操作があり、それらを受け取るのに 5 分かかるとします。 この時点で、ユーザーは何を持っていますか? スピナー?進捗?アップロードされた量についての情報? プロセス中のユーザーがすでに何かを見ている可能性がある場合は、「アクティブな待機」を使用するのが理想的です。 結果は次のとおりです。
- ページの読み込み
- すべての請求書が要求されます
- その後、実行されたトランザクションの手数料を伴うすべてのトランザクションがすべてのアカウントに対して要求されます。データが受信されると、ブラウザでレンダリングされます。
毎回イベントのデータをフィルタリングしないために、アカウントごとに独自のイベントをプルします。このような:
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 | 金額の小数部分。負の数を指定できます |
それらを個別に処理してから、価格値にします。
quote.units + quote.nano / 1e9
先物契約のコスト
先物の価格はポイントで表示されます。通貨の先物がある場合は、レートを知る必要があります。そしてもちろん、ポイントでの価格と価格ステップ。 トランザクションからの利益を計算すると、これがうまくいく可能性があります。価格に数量を掛けて合計金額を計算する場合。ここで注意が必要です。とりあえず様子見です。これは通貨先物に適用され、他の場所ではすべてこれで問題ありません。
店頭市場
この市場には多くの特殊性があるため、操作を個別に検討してみましょう. 同期操作を 開始すると、楽器を正しく一致させるために、フィジ/ティッカーを同じ形にする必要があることがわかります. これを仲介レポートと同期し始めると、同じトランザクションの tradeID がトランザクションの先頭に文字があり、それらが仲介レポートにないことがわかります。したがって、それらを比較することはできません…エヘムエヘム…比較によって!トレード時間、ティッカー、およびトレード ID が別のトレード ID に含まれているマッチングを一致させました。わかりません。これに遭遇し、それを気にする人は誰でも、問題に来るか、新しい問題を始めてください.
ツールの数学的操作
リスト全体で数学演算を実行することは、見なければ不可能です。ウォームにソフトを追加しないために、常に通貨をチェックし、通貨が一致することが確実な場合にのみ処理し、ポイントは目的の通貨に変換されます。 銀行番号の操作に関する知識を武器に、各口座に費やされた手数料を計算します。このように: 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
これは、自分で理解し、実行し、頼りにするのが面倒な人のための私の開発です。ユーザーのリクエストに応じて、そこに分析を追加する予定です。 記事が気に入ったら、私の電報チャンネルを購読してください。
Полезная статья. Не могу представить, сколько усилий автора потребовалось, чтобы все описать. Благодарю.