Created
March 24, 2023 09:35
-
-
Save kirugan/ddbc76d29e2bb1babe1ad13a77c7d663 to your computer and use it in GitHub Desktop.
Small script to collect input/output operations in Tinkoff investments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"crypto/tls" | |
"flag" | |
"fmt" | |
"github.com/davecgh/go-spew/spew" | |
sdk "github.com/tinkoff/invest-api-go-sdk" | |
"google.golang.org/grpc" | |
"google.golang.org/grpc/credentials" | |
"google.golang.org/grpc/metadata" | |
"google.golang.org/protobuf/types/known/timestamppb" | |
"math/rand" | |
"time" | |
) | |
const token = `` | |
var stats = struct { | |
Output map[string]int | |
Input map[string]int | |
}{ | |
Output: map[string]int{}, | |
Input: map[string]int{}, | |
} | |
func main() { | |
SDKInit(token, false) | |
//Получаем список счетов | |
accounts, err := GetAccounts() | |
if err != nil { | |
panic(err) | |
} | |
types := map[sdk.OperationType]int{} | |
for _, acc := range accounts { | |
date := acc.GetOpenedDate() | |
t := ts(date) | |
ops, err := GetOperations(acc.GetId(), t, time.Now(), "") | |
if err != nil { | |
panic(err) | |
} | |
fmt.Printf("Operations %d\n", len(ops)) | |
for _, op := range ops { | |
p := op.Payment | |
switch op.Type { | |
case sdk.OperationType_OPERATION_TYPE_OUTPUT: | |
if op.State != sdk.OperationState_OPERATION_STATE_EXECUTED { | |
panic(op) | |
} | |
if p.Units > 0 { | |
panic("units positive for output") | |
} | |
stats.Output[p.Currency] += abs(int(p.Units)) | |
// fmt.Printf("Вывод %v %v %v\n", p.Units, p.Currency, ts(op.Date)) | |
case sdk.OperationType_OPERATION_TYPE_INPUT: | |
if op.State != sdk.OperationState_OPERATION_STATE_EXECUTED { | |
panic(op) | |
} | |
if p.Units < 0 { | |
panic("input is negative") | |
} | |
//spew.Dump(op) | |
stats.Input[p.Currency] += abs(int(p.Units)) | |
default: | |
types[op.Type]++ | |
} | |
} | |
} | |
spew.Dump(stats) | |
} | |
func ts(t *timestamppb.Timestamp) time.Time { | |
return time.Unix(t.Seconds, int64(t.Nanos)) | |
} | |
func abs(i int) int { | |
if i < 0 { | |
return -i | |
} else { | |
return i | |
} | |
} | |
var Instruments sdk.InstrumentsServiceClient | |
var MarketData sdk.MarketDataServiceClient | |
var Operations sdk.OperationsServiceClient | |
var Users sdk.UsersServiceClient | |
var Orders sdk.OrdersServiceClient | |
var ctx context.Context | |
var conn *grpc.ClientConn | |
var md metadata.MD | |
const ( | |
address_prod = "invest-public-api.tinkoff.ru:443" | |
address_sandbox = "sandbox-invest-public-api.tinkoff.ru:443" | |
) | |
func SDKInit(token string, use_sandbox bool) { | |
rand.Seed(time.Now().UnixNano()) | |
flag.Parse() | |
ctx = context.Background() | |
addr := address_prod | |
if use_sandbox { | |
addr = address_sandbox | |
} | |
var err error | |
conn, err = grpc.Dial(addr, | |
grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{InsecureSkipVerify: true})), grpc.WithBlock()) | |
if err != nil { | |
panic(err) | |
} | |
md = metadata.New(map[string]string{"Authorization": "Bearer " + token}) | |
ctx = metadata.NewOutgoingContext(ctx, md) | |
Instruments = sdk.NewInstrumentsServiceClient(conn) | |
MarketData = sdk.NewMarketDataServiceClient(conn) | |
Operations = sdk.NewOperationsServiceClient(conn) | |
Users = sdk.NewUsersServiceClient(conn) | |
Orders = sdk.NewOrdersServiceClient(conn) | |
} | |
func GetAccounts() ([]*sdk.Account, error) { | |
var ar sdk.GetAccountsRequest | |
r, err := Users.GetAccounts(ctx, &ar) | |
if err != nil { | |
return nil, err | |
} | |
return r.GetAccounts(), nil | |
} | |
func GetOperations(AccountId string, from time.Time, to time.Time, figi string) ([]sdk.OperationItem, error) { | |
var or sdk.OperationsRequest | |
or.AccountId = AccountId | |
tsFrom := timestamppb.New(from) | |
tsTo := timestamppb.New(to) | |
//or.From = tsFrom | |
//or.To = tsTo | |
//or.Figi = figi | |
// | |
//r, err := Operations.GetOperations(ctx, &or) | |
//if err != nil { | |
// return nil, err | |
//} | |
//return r.GetOperations(), nil | |
var r sdk.GetOperationsByCursorRequest | |
r.From = tsFrom | |
r.To = tsTo | |
r.AccountId = AccountId | |
r.Limit = 1000 | |
r.OperationTypes = []sdk.OperationType{ | |
sdk.OperationType_OPERATION_TYPE_INPUT, | |
sdk.OperationType_OPERATION_TYPE_OUTPUT, | |
} | |
resp, err := Operations.GetOperationsByCursor(ctx, &r) | |
if err != nil { | |
return nil, err | |
} | |
var items []sdk.OperationItem | |
for _, item := range resp.GetItems() { | |
items = append(items, *item) | |
} | |
return items, nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment