mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 01:01:56 +00:00
Compare commits
327 Commits
cb0b6e88b4
...
4a106ac2e2
Author | SHA1 | Date | |
---|---|---|---|
|
4a106ac2e2 | ||
|
37106c35b7 | ||
|
8265ada5a0 | ||
|
744ca57c71 | ||
|
17d3097e06 | ||
|
a0c41f89f2 | ||
|
35a6639530 | ||
|
26b1fd2ae7 | ||
|
80430fec46 | ||
|
1f8b2b3710 | ||
|
25a2203000 | ||
|
aca2c32442 | ||
|
df915d6ee8 | ||
|
0d6b7b29d5 | ||
|
2784ef4687 | ||
|
ea8f3a5485 | ||
|
52f32e0ad0 | ||
|
50cdf617f2 | ||
|
de0d11b511 | ||
|
789bb1e53e | ||
|
a9b71adce9 | ||
|
f83491af26 | ||
|
82d07a0098 | ||
|
619cce53f6 | ||
|
643ecde2e9 | ||
|
d7ddc9c462 | ||
|
bd19b63c7b | ||
|
83ed9b0811 | ||
|
34ef50d889 | ||
|
52925c5643 | ||
|
b4f2748892 | ||
|
ceda1e06b9 | ||
|
bc1715f8ad | ||
|
f361b19564 | ||
|
f44486447e | ||
|
a2eca66af5 | ||
|
129e2c438e | ||
|
90749f4873 | ||
|
77dfe213e5 | ||
|
960ea89d8c | ||
|
f24a96c8c3 | ||
|
6ad16b7488 | ||
|
e14f09a914 | ||
|
3cc96ff6ad | ||
|
6ea996bec4 | ||
|
ef935f8ca0 | ||
|
a282654c02 | ||
|
336dd7a108 | ||
|
f2a443a499 | ||
|
63a58e1b12 | ||
|
1b40118bba | ||
|
c75a685cc0 | ||
|
50262f2a84 | ||
|
9fc3a1b44a | ||
|
656112de45 | ||
|
ba73eeaad1 | ||
|
2527c0c7b7 | ||
|
a2f8fe5f72 | ||
|
ed51eff242 | ||
|
f6865f664c | ||
|
24de49860f | ||
|
83dc981c92 | ||
|
ec68e3c5f6 | ||
|
699164484b | ||
|
f27afac77b | ||
|
d404b20bd1 | ||
|
1b8d7bd805 | ||
|
7d034d1ba8 | ||
|
7135895006 | ||
|
ba913ce4de | ||
|
f12ba1adb9 | ||
|
294e529a98 | ||
|
f30aca1b5a | ||
|
f9b9832fff | ||
|
2bf1072977 | ||
|
01f8b78008 | ||
|
4d1c357c3d | ||
|
a4833524cf | ||
|
ed073264f1 | ||
|
ad6056834e | ||
|
8b1306a6a6 | ||
|
d85da78e17 | ||
|
9d581adc04 | ||
|
cff7103ece | ||
|
d501e8ff4d | ||
|
b87213827e | ||
|
ec80cbfd9f | ||
|
04bed165d0 | ||
|
7c4b3e81df | ||
|
cc820d3df0 | ||
|
371db8e7d1 | ||
|
b8abc065de | ||
|
9ebab4f4f7 | ||
|
d9fb9ff3e0 | ||
|
88d7783843 | ||
|
86e464b1bc | ||
|
8e91a023ca | ||
|
8de0c67503 | ||
|
e187614179 | ||
|
bda66040e7 | ||
|
d36bbe5fb5 | ||
|
77b7b29739 | ||
|
1d6282a10b | ||
|
108fb6138a | ||
|
1e2f086643 | ||
|
6011fd5157 | ||
|
652c9b62e8 | ||
|
9939b5ce68 | ||
|
a740ef10c2 | ||
|
f81ce5ce95 | ||
|
4ae8ad77b3 | ||
|
3819feacf3 | ||
|
4af12a7e5d | ||
|
3d4ccd1344 | ||
|
b3c8739983 | ||
|
5edf5a763f | ||
|
7e65aca62e | ||
|
199b86df86 | ||
|
6fb6467d59 | ||
|
2479f2e9fc | ||
|
e77f0cbacb | ||
|
be386d085a | ||
|
ea93bf959a | ||
|
e3079c134c | ||
|
7367ea73b8 | ||
|
f96e0d6552 | ||
|
68e56d76e6 | ||
|
ec51eb7cdd | ||
|
3ec509b379 | ||
|
84edcb0e02 | ||
|
866751cc3d | ||
|
80949bf0e1 | ||
|
86cc821626 | ||
|
90bcd25bef | ||
|
f59ff90c5e | ||
|
3013e37a38 | ||
|
349a3040f3 | ||
|
7fdb3f671f | ||
|
321eb23514 | ||
|
77e185ffa7 | ||
|
e7fd90ed59 | ||
|
9a7517a72a | ||
|
9a1d9ae27b | ||
|
c76a80da6a | ||
|
afac81a3e8 | ||
|
b0cc009d67 | ||
|
0df56ad6e7 | ||
|
1c1959b8a8 | ||
|
9f01dc28c8 | ||
|
e8bd370aa2 | ||
|
5ca1c4fb62 | ||
|
f7dc07327e | ||
|
6ef8aa62e5 | ||
|
5f65e87e89 | ||
|
14fff8dbad | ||
|
92ad80f2f8 | ||
|
0a2d442ceb | ||
|
f7f8ecfd15 | ||
|
40a0585187 | ||
|
9f510da78b | ||
|
c2679b4ae1 | ||
|
106a01e508 | ||
|
02ff04cfb5 | ||
|
80ad5c32b5 | ||
|
e3c4314aed | ||
|
c7f62cf1e5 | ||
|
4bbb9c5e38 | ||
|
b2f1f7d735 | ||
|
1b06fcc961 | ||
|
b820fccce1 | ||
|
bb06a6a046 | ||
|
72575e3cd8 | ||
|
a900c72032 | ||
|
5635e31487 | ||
|
e2d68f2a86 | ||
|
6718087cb1 | ||
|
9136877207 | ||
|
c063df6467 | ||
|
80fc10a1fd | ||
|
fead99aaa6 | ||
|
40d3a40277 | ||
|
055cfbb3ff | ||
|
d18adfcbc7 | ||
|
48eeae0a10 | ||
|
d855d9bbc0 | ||
|
1a1f700122 | ||
|
3a2e4dfd26 | ||
|
6f0cf8f3e0 | ||
|
731fa9af7e | ||
|
a06b63c897 | ||
|
ebaf3a330f | ||
|
a0cbf82d97 | ||
|
9a2b792ed1 | ||
|
2392fddc3c | ||
|
c92c395f67 | ||
|
48029f95cc | ||
|
8911f88ed6 | ||
|
a1c77e42f1 | ||
|
c03f5f47c2 | ||
|
40260a1204 | ||
|
baffefac07 | ||
|
6d3a18ad55 | ||
|
d1617b6a0b | ||
|
b9c41b7ad7 | ||
|
0530809834 | ||
|
d8fad8250c | ||
|
c8aea81505 | ||
|
cec078f4bf | ||
|
648e10fd7c | ||
|
b7d18e687e | ||
|
51c1b995c2 | ||
|
f845918d80 | ||
|
47c7714d33 | ||
|
408a41342b | ||
|
f7ad141b04 | ||
|
90712aff29 | ||
|
0a83c26fd5 | ||
|
1294cd95be | ||
|
9dd85623b9 | ||
|
621a2b86cf | ||
|
daa1def6d9 | ||
|
e9bf4babe2 | ||
|
52abb9193d | ||
|
3d7453f18c | ||
|
098de2245c | ||
|
b88aff6d73 | ||
|
7488a1069f | ||
|
4154cc9d53 | ||
|
714275fedb | ||
|
b27fc896f9 | ||
|
cf42d9d0b0 | ||
|
a91685920e | ||
|
5596589bff | ||
|
ee04e12210 | ||
|
b02be2cf70 | ||
|
4925d8bfd9 | ||
|
9911a4f711 | ||
|
1b0d4599e2 | ||
|
473a6bc108 | ||
|
1ad2bc5f34 | ||
|
df8d52adda | ||
|
00e860df26 | ||
|
f277b191d2 | ||
|
8773c220f5 | ||
|
f228ca7962 | ||
|
eb6e5cda39 | ||
|
813684fc77 | ||
|
25b0b5ded5 | ||
|
ffb2c14f1d | ||
|
fad7ef219e | ||
|
9e28898df0 | ||
|
b4cc893cac | ||
|
a24a118182 | ||
|
e03ba63e44 | ||
|
5d65b817ef | ||
|
b4bb7b6716 | ||
|
57a68f8063 | ||
|
c35805916a | ||
|
00091e1ce1 | ||
|
97336912e5 | ||
|
089e69a221 | ||
|
600d81049e | ||
|
22fa8d5acb | ||
|
1583d1413b | ||
|
e76496523e | ||
|
4c75f4dc29 | ||
|
661b870f71 | ||
|
eb317da21a | ||
|
4bf558f9eb | ||
|
6bc8dffe16 | ||
|
ab20b6db89 | ||
|
378ef91e5d | ||
|
373c4ebd58 | ||
|
a5bf3518df | ||
|
3ebed3b836 | ||
|
1889e83a08 | ||
|
0dd2919bf8 | ||
|
82811de9dc | ||
|
7516bc0eee | ||
|
aff94d3081 | ||
|
869385b403 | ||
|
c5ed6fc52f | ||
|
acd908064c | ||
|
1c28fd3b44 | ||
|
015c5fc9a9 | ||
|
2c2e5afa45 | ||
|
9fb273e6a1 | ||
|
be27d32bd8 | ||
|
0eb3856906 | ||
|
e7a20db048 | ||
|
22c154f9cd | ||
|
d41de325f8 | ||
|
c217aadc1b | ||
|
d982524824 | ||
|
e293ec5c70 | ||
|
bc12e88501 | ||
|
0a6d24195b | ||
|
a6aef35393 | ||
|
1fe0ddbbea | ||
|
e63158f5fa | ||
|
3735499753 | ||
|
ad5674d9cb | ||
|
396ee68170 | ||
|
9bf635de5f | ||
|
bbb1b8a9fa | ||
|
ee09922865 | ||
|
1dc1afc993 | ||
|
3007fa7ed7 | ||
|
a1b8e07bb5 | ||
|
df125c0efb | ||
|
6be38558e4 | ||
|
6cdf991877 | ||
|
82501ff57c | ||
|
00b9c3156f | ||
|
6afde4808f | ||
|
26d0fedcec | ||
|
b2722d9e44 | ||
|
9cbf8a0ecf | ||
|
0f03bc785b | ||
|
6b6bf2f722 | ||
|
46bd4a0ef8 | ||
|
c83524a04a | ||
|
4dc28ec16a | ||
|
e953a04638 | ||
|
589a8b6eb2 | ||
|
0d7236ca8a | ||
|
49d567c8f2 |
27
.github/dependabot.yml
vendored
Normal file
27
.github/dependabot.yml
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
commit-message:
|
||||
prefix: "dep"
|
||||
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
commit-message:
|
||||
prefix: "dep"
|
||||
# Create pull requests only for security updates
|
||||
open-pull-requests-limit: 0
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directories:
|
||||
- "/apps/backtest-report"
|
||||
- "/apps/frontend"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
commit-message:
|
||||
prefix: "dep"
|
||||
open-pull-requests-limit: 0
|
12
.github/workflows/docker.yml
vendored
12
.github/workflows/docker.yml
vendored
|
@ -20,7 +20,7 @@ jobs:
|
|||
steps:
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v3
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
# list of Docker images to use as base name for tags
|
||||
images: |
|
||||
|
@ -36,23 +36,23 @@ jobs:
|
|||
type=semver,pattern={{major}}
|
||||
type=sha
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Login to Quay Container Registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: quay.io
|
||||
username: ${{ secrets.QUAY_USERNAME }}
|
||||
password: ${{ secrets.QUAY_TOKEN }}
|
||||
- name: Build and push
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v2
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
push: true
|
||||
# tags: yoanlin/bbgo:latest
|
||||
|
|
14
.github/workflows/go.yml
vendored
14
.github/workflows/go.yml
vendored
|
@ -2,8 +2,10 @@ name: Go
|
|||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
branches:
|
||||
- "main"
|
||||
pull_request:
|
||||
types: [synchronize, opened, reopened]
|
||||
branches:
|
||||
- "main"
|
||||
- "v*"
|
||||
|
@ -27,12 +29,12 @@ jobs:
|
|||
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
# lfs: 'true'
|
||||
ssh-key: ${{ secrets.git_ssh_key }}
|
||||
|
||||
- uses: actions/cache@v2
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
|
@ -53,7 +55,7 @@ jobs:
|
|||
# auto-start: "false"
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
|
@ -88,13 +90,13 @@ jobs:
|
|||
sed -i -e '/_requestgen.go/d' coverage_dnum.txt
|
||||
|
||||
- name: Revive Check
|
||||
uses: morphy2k/revive-action@v2.5.4 # https://github.com/mgechev/revive/issues/956
|
||||
uses: morphy2k/revive-action@v2.5.10 # https://github.com/mgechev/revive/issues/956
|
||||
with:
|
||||
reporter: github-pr-review
|
||||
fail_on_error: true
|
||||
|
||||
- name: Upload Coverage Report
|
||||
uses: codecov/codecov-action@v3
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
files: ./coverage.txt,./coverage_dnum.txt
|
||||
|
||||
|
|
2
.github/workflows/golang-lint.yml
vendored
2
.github/workflows/golang-lint.yml
vendored
|
@ -20,6 +20,6 @@ jobs:
|
|||
go-version: '1.21'
|
||||
cache: false
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v4
|
||||
uses: golangci/golangci-lint-action@v6
|
||||
with:
|
||||
version: 'v1.54'
|
||||
|
|
4
.github/workflows/node.yml
vendored
4
.github/workflows/node.yml
vendored
|
@ -21,9 +21,9 @@ jobs:
|
|||
node-version: [ 16.x ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: npm install -g yarn
|
||||
|
|
48
.github/workflows/python.yml
vendored
48
.github/workflows/python.yml
vendored
|
@ -1,48 +0,0 @@
|
|||
name: Python
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- python
|
||||
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- python
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [ 3.8 ]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Install poetry
|
||||
run: pip install poetry==1.1.13
|
||||
|
||||
- name: Install package
|
||||
run: |
|
||||
cd python
|
||||
poetry install
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
cd python
|
||||
poetry run pytest -v -s tests
|
||||
|
||||
- name: Lint
|
||||
run: |
|
||||
cd python
|
||||
poetry run flake8 .
|
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
|
@ -16,13 +16,13 @@ jobs:
|
|||
id: get_version
|
||||
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v4
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.21"
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "16"
|
||||
- name: Build
|
||||
|
|
25
.travis.yml
25
.travis.yml
|
@ -1,25 +0,0 @@
|
|||
---
|
||||
language: go
|
||||
go:
|
||||
- 1.14
|
||||
- 1.15
|
||||
|
||||
services:
|
||||
- redis-server
|
||||
- mysql
|
||||
|
||||
before_install:
|
||||
- mysql -e 'CREATE DATABASE bbgo;'
|
||||
- mysql -e 'CREATE DATABASE bbgo_dev;'
|
||||
|
||||
install:
|
||||
- go get github.com/c9s/rockhopper/cmd/rockhopper
|
||||
|
||||
before_script:
|
||||
- go mod download
|
||||
- make migrations
|
||||
|
||||
script:
|
||||
- bash scripts/test-sqlite3-migrations.sh
|
||||
- bash scripts/test-mysql-migrations.sh
|
||||
- go test -v ./pkg/...
|
|
@ -15,9 +15,9 @@ type: application
|
|||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.3.5
|
||||
version: 0.4.3
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
appVersion: 1.21.0
|
||||
appVersion: 1.60.0
|
||||
|
|
55
charts/bbgo/templates/cronjob_sync.yaml
Normal file
55
charts/bbgo/templates/cronjob_sync.yaml
Normal file
|
@ -0,0 +1,55 @@
|
|||
{{- if .Values.sync.enabled }}
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: {{ include "bbgo.fullname" . }}-sync
|
||||
{{- with .Values.deploymentAnnotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "bbgo.labels" . | nindent 4 }}
|
||||
spec:
|
||||
schedule: {{ .Values.sync.schedule | quote }}
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: bbgo
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 14 }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
args:
|
||||
{{- if .Values.metrics.enabled }}
|
||||
- "--metrics"
|
||||
- "--metrics-port"
|
||||
- {{ .Values.metrics.port | quote }}
|
||||
{{- end }}
|
||||
- "sync"
|
||||
- "--config"
|
||||
- "/config/bbgo.yaml"
|
||||
{{- if .Values.sync.since }}
|
||||
- "--since"
|
||||
- {{ .Values.sync.since | quote }}
|
||||
{{- end }}
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 14 }}
|
||||
volumeMounts:
|
||||
- name: config-volume
|
||||
mountPath: /config
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ .Values.dotenv.secret | default .Release.Name }}
|
||||
restartPolicy: OnFailure
|
||||
volumes:
|
||||
- name: config-volume
|
||||
configMap:
|
||||
{{- if .Values.existingConfigMap }}
|
||||
name: {{ .Values.existingConfigMap }}
|
||||
{{- else }}
|
||||
name: {{ include "bbgo.fullname" . }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
|
@ -98,6 +98,18 @@ spec:
|
|||
mountPath: /config
|
||||
|
||||
# the "env" entries will override the environment variables from envFrom.
|
||||
env:
|
||||
- name: USE_MARKETS_CACHE_IN_MEMORY
|
||||
value: "true"
|
||||
{{- if .Values.environment }}
|
||||
- name: BBGO_ENV
|
||||
value: {{ .Values.environment | quote }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Values.rbTreeOrderbook.enabled }}
|
||||
- name: ENABLE_RBT_ORDERBOOK
|
||||
value: "true"
|
||||
{{- end }}
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ .Values.dotenv.secret | default .Release.Name }}
|
||||
|
|
|
@ -75,11 +75,11 @@ webserver:
|
|||
enabled: false
|
||||
|
||||
metrics:
|
||||
enabled: false
|
||||
enabled: true
|
||||
port: 9090
|
||||
|
||||
logFormatter:
|
||||
enabled: false
|
||||
enabled: true
|
||||
format: json
|
||||
|
||||
grpc:
|
||||
|
@ -89,6 +89,18 @@ grpc:
|
|||
debug:
|
||||
enabled: false
|
||||
|
||||
environment: dev
|
||||
|
||||
# this set ENABLE_RBT_ORDERBOOK env
|
||||
rbTreeOrderbook:
|
||||
enabled: false
|
||||
|
||||
sync:
|
||||
enabled: false
|
||||
schedule: "0 * * * *"
|
||||
## since: sync from time
|
||||
since: false
|
||||
|
||||
resources:
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
|
|
|
@ -5,7 +5,7 @@ exchangeStrategies:
|
|||
autobuy:
|
||||
symbol: MAXTWD
|
||||
schedule: "@every 1s"
|
||||
threshold: 200
|
||||
minBaseBalance: 200
|
||||
# price type: LAST, BUY, SELL, MID, TAKER, MAKER
|
||||
priceType: BUY
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ logging:
|
|||
trade: true
|
||||
order: true
|
||||
fields:
|
||||
env: staging
|
||||
env: local
|
||||
|
||||
sessions:
|
||||
max:
|
||||
|
@ -59,6 +59,17 @@ crossExchangeStrategies:
|
|||
# 0.1 pip is 0.01, here we use 10, so we will get 18000.00, 18001.00 and
|
||||
# 18002.00
|
||||
pips: 10
|
||||
persistence:
|
||||
type: redis
|
||||
|
||||
## profitFixer is used for fixing the profit stats and the position
|
||||
# profitFixer:
|
||||
# tradesSince: "2024-08-01T15:00:00.000+08:00"
|
||||
circuitBreaker:
|
||||
enabled: true
|
||||
maximumConsecutiveTotalLoss: 36.0
|
||||
maximumConsecutiveLossTimes: 10
|
||||
maximumLossPerRound: 15.0
|
||||
maximumTotalLoss: 80.0
|
||||
ignoreConsecutiveDustLoss: true
|
||||
consecutiveDustLossThreshold: 0.003
|
||||
haltDuration: "30m"
|
||||
maximumHaltTimes: 2
|
||||
maximumHaltTimesExceededPanic: true
|
||||
|
|
|
@ -58,4 +58,4 @@ bbgo [flags]
|
|||
* [bbgo userdatastream](bbgo_userdatastream.md) - Listen to session events (orderUpdate, tradeUpdate, balanceUpdate, balanceSnapshot)
|
||||
* [bbgo version](bbgo_version.md) - show version name
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -41,4 +41,4 @@ bbgo account [--session SESSION] [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -50,4 +50,4 @@ bbgo backtest [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -40,4 +40,4 @@ bbgo balances [--session SESSION] [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -39,4 +39,4 @@ bbgo build [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -49,4 +49,4 @@ bbgo cancel-order [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -41,4 +41,4 @@ bbgo deposits [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -9,16 +9,18 @@ bbgo execute-order --session SESSION --symbol SYMBOL --side SIDE --target-quanti
|
|||
### Options
|
||||
|
||||
```
|
||||
--deadline duration deadline of the order execution
|
||||
-h, --help help for execute-order
|
||||
--price-ticks int the number of price tick for the jump spread, default to 0
|
||||
--session string the exchange session name for sync
|
||||
--side string the trading side: buy or sell
|
||||
--slice-quantity string slice quantity
|
||||
--stop-price string stop price (default "0")
|
||||
--symbol string the trading pair, like btcusdt
|
||||
--target-quantity string target quantity
|
||||
--update-interval duration order update time (default 10s)
|
||||
--deadline duration deadline duration of the order execution, e.g. 1h
|
||||
--delay-interval duration order delay time after filled (default 3s)
|
||||
-h, --help help for execute-order
|
||||
--order-update-rate-limit string order update rate limit, syntax: 1+1/1m (default "1s")
|
||||
--price-ticks int the number of price tick for the jump spread, default to 0
|
||||
--session string the exchange session name for sync
|
||||
--side string the trading side: buy or sell
|
||||
--slice-quantity string slice quantity
|
||||
--stop-price string stop price (default "0")
|
||||
--symbol string the trading pair, like btcusdt
|
||||
--target-quantity string target quantity
|
||||
--update-interval duration order update time (default 10s)
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
@ -48,4 +50,4 @@ bbgo execute-order --session SESSION --symbol SYMBOL --side SIDE --target-quanti
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -42,4 +42,4 @@ bbgo get-order --session SESSION --order-id ORDER_ID [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -45,4 +45,4 @@ bbgo hoptimize [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -42,4 +42,4 @@ bbgo kline [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -41,4 +41,4 @@ bbgo list-orders open|closed --session SESSION --symbol SYMBOL [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -38,4 +38,4 @@ margin related history
|
|||
* [bbgo margin loans](bbgo_margin_loans.md) - query loans history
|
||||
* [bbgo margin repays](bbgo_margin_repays.md) - query repay history
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -41,4 +41,4 @@ bbgo margin interests --session=SESSION_NAME --asset=ASSET [flags]
|
|||
|
||||
* [bbgo margin](bbgo_margin.md) - margin related history
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -41,4 +41,4 @@ bbgo margin loans --session=SESSION_NAME --asset=ASSET [flags]
|
|||
|
||||
* [bbgo margin](bbgo_margin.md) - margin related history
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -41,4 +41,4 @@ bbgo margin repays --session=SESSION_NAME --asset=ASSET [flags]
|
|||
|
||||
* [bbgo margin](bbgo_margin.md) - margin related history
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -40,4 +40,4 @@ bbgo market [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -44,4 +44,4 @@ bbgo optimize [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -42,4 +42,4 @@ bbgo orderbook --session=[exchange_name] --symbol=[pair_name] [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -40,4 +40,4 @@ bbgo orderupdate [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -49,4 +49,4 @@ bbgo pnl [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -51,4 +51,4 @@ bbgo run [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -46,4 +46,4 @@ bbgo submit-order --session SESSION --symbol SYMBOL --side SIDE --quantity QUANT
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -42,4 +42,4 @@ bbgo sync [--session=[exchange_name]] [--symbol=[pair_name]] [[--since=yyyy/mm/d
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -42,4 +42,4 @@ bbgo trades --session=[exchange_name] --symbol=[pair_name] [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -40,4 +40,4 @@ bbgo tradeupdate --session=[exchange_name] [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -42,4 +42,4 @@ bbgo transfer-history [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -40,4 +40,4 @@ bbgo userdatastream [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -39,4 +39,4 @@ bbgo version [flags]
|
|||
|
||||
* [bbgo](bbgo.md) - bbgo is a crypto trading bot
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-May-2024
|
||||
###### Auto generated by spf13/cobra on 16-Sep-2024
|
||||
|
|
|
@ -17,7 +17,7 @@ TELEGRAM_BOT_TOKEN=347374838:ABFTjfiweajfiawoejfiaojfeijoaef
|
|||
```
|
||||
|
||||
For the telegram chat authentication (your bot needs to verify it's you), if you only need a fixed authentication token,
|
||||
you can set `TELEGRAM_AUTH_TOKEN` in the `.env.local` file, e.g.,
|
||||
you can set `TELEGRAM_BOT_AUTH_TOKEN` in the `.env.local` file, e.g.,
|
||||
|
||||
```sh
|
||||
TELEGRAM_BOT_AUTH_TOKEN=itsme55667788
|
||||
|
|
62
doc/release/v1.60.0.md
Normal file
62
doc/release/v1.60.0.md
Normal file
|
@ -0,0 +1,62 @@
|
|||
[Full Changelog](https://github.com/c9s/bbgo/compare/v1.59.2...main)
|
||||
|
||||
- [#1683](https://github.com/c9s/bbgo/pull/1683): dep: bump codecov/codecov-action from 3 to 4
|
||||
- [#1680](https://github.com/c9s/bbgo/pull/1680): dep: bump docker/setup-buildx-action from 1 to 3
|
||||
- [#1684](https://github.com/c9s/bbgo/pull/1684): dep: bump docker/metadata-action from 3 to 5
|
||||
- [#1681](https://github.com/c9s/bbgo/pull/1681): dep: bump actions/checkout from 2 to 4
|
||||
- [#1689](https://github.com/c9s/bbgo/pull/1689): FIX: fix float64 series use mean or stdev function result is zero
|
||||
- [#1697](https://github.com/c9s/bbgo/pull/1697): FEATURE: redesign and refactor twap order executor
|
||||
- [#1698](https://github.com/c9s/bbgo/pull/1698): FEATURE: update get trades api
|
||||
- [#1692](https://github.com/c9s/bbgo/pull/1692): DELETE: delete python
|
||||
- [#1693](https://github.com/c9s/bbgo/pull/1693): FIX: fix binance exchange query futures order
|
||||
- [#1696](https://github.com/c9s/bbgo/pull/1696): FIX: [core] setting.InitializeConverter could return a nil converter object
|
||||
- [#1695](https://github.com/c9s/bbgo/pull/1695): FIX: [max] fix GetDepositHistoryRequest
|
||||
- [#1694](https://github.com/c9s/bbgo/pull/1694): FIX: [max] fix max withdrawal api parameters
|
||||
- [#1691](https://github.com/c9s/bbgo/pull/1691): FEATURE: [bitget] upgrade public websocket to v2
|
||||
- [#1690](https://github.com/c9s/bbgo/pull/1690): FEATURE: improve trade/order converter
|
||||
- [#1688](https://github.com/c9s/bbgo/pull/1688): FEATURE: [xdepthmaker] separate hedge symbol
|
||||
- [#1685](https://github.com/c9s/bbgo/pull/1685): IMPROVE: [xalign] improve notification
|
||||
- [#1679](https://github.com/c9s/bbgo/pull/1679): FIX: [xalign] fix max withdraw history api query
|
||||
- [#1671](https://github.com/c9s/bbgo/pull/1671): dep: bump morphy2k/revive-action from 2.5.4 to 2.5.9
|
||||
- [#1672](https://github.com/c9s/bbgo/pull/1672): dep: bump docker/login-action from 1 to 3
|
||||
- [#1674](https://github.com/c9s/bbgo/pull/1674): dep: bump docker/setup-qemu-action from 1 to 3
|
||||
- [#1676](https://github.com/c9s/bbgo/pull/1676): dep: bump docker/build-push-action from 2 to 6
|
||||
- [#1677](https://github.com/c9s/bbgo/pull/1677): dep: bump golangci/golangci-lint-action from 4 to 6
|
||||
- [#1678](https://github.com/c9s/bbgo/pull/1678): FEATURE: [xalign] add withdraw detection
|
||||
- [#1673](https://github.com/c9s/bbgo/pull/1673): dep: bump actions/setup-go from 4 to 5
|
||||
- [#1675](https://github.com/c9s/bbgo/pull/1675): dep: bump actions/cache from 2 to 4
|
||||
- [#1670](https://github.com/c9s/bbgo/pull/1670): CI: Create .github/dependabot.yml
|
||||
- [#1669](https://github.com/c9s/bbgo/pull/1669): FEATURE: [max] update max api url
|
||||
- [#1668](https://github.com/c9s/bbgo/pull/1668): REFACTOR: support custom order by column
|
||||
- [#1663](https://github.com/c9s/bbgo/pull/1663): FIX: [rebalance] round down quantity
|
||||
- [#1667](https://github.com/c9s/bbgo/pull/1667): FIX: [common] fix profit fixer batch query
|
||||
- [#1666](https://github.com/c9s/bbgo/pull/1666): FEATURE: [liqmaker] add profit fixer support
|
||||
- [#1665](https://github.com/c9s/bbgo/pull/1665): IMPROVE: improve price volume slice parsing
|
||||
- [#1664](https://github.com/c9s/bbgo/pull/1664): FEATURE: update max api to latest version
|
||||
- [#1383](https://github.com/c9s/bbgo/pull/1383): FEATURE: merge recover logic and run periodically
|
||||
- [#1656](https://github.com/c9s/bbgo/pull/1656): REFACTOR: [autobuy] replace threshold with minBaseBalance
|
||||
- [#1644](https://github.com/c9s/bbgo/pull/1644): REFACTOR: Extract and move FeeBudget from xgap
|
||||
- [#1662](https://github.com/c9s/bbgo/pull/1662): FIX: [atrpin] fix position quantity
|
||||
- [#1661](https://github.com/c9s/bbgo/pull/1661): IMPROVE: [batch] improve trade batch query
|
||||
- [#1648](https://github.com/c9s/bbgo/pull/1648): FEATURE: [atrpin] take profit by expected base balance
|
||||
- [#1660](https://github.com/c9s/bbgo/pull/1660): FIX: fix trade insertion for inserted_at field
|
||||
- [#1659](https://github.com/c9s/bbgo/pull/1659): FEATURE: [core] add syncBufferPeriod config and set default to -30 mins
|
||||
- [#1657](https://github.com/c9s/bbgo/pull/1657): MINOR: compile and update migration package for trades.inserted_at
|
||||
- [#1646](https://github.com/c9s/bbgo/pull/1646): MINOR: add inserted_at column to trades
|
||||
- [#1655](https://github.com/c9s/bbgo/pull/1655): FEATURE: [xgap] add dailyTargetVolume option
|
||||
- [#1645](https://github.com/c9s/bbgo/pull/1645): FEATURE: [dca2] make the take-profit order of round from order to orders
|
||||
- [#1654](https://github.com/c9s/bbgo/pull/1654): FIX: [types] improve AdjustQuantityByMinNotional
|
||||
- [#1653](https://github.com/c9s/bbgo/pull/1653): FIX: [xgap] make sourceBook optional
|
||||
- [#1652](https://github.com/c9s/bbgo/pull/1652): FIX: [xgap] fix empty source book pricing issue
|
||||
- [#1649](https://github.com/c9s/bbgo/pull/1649): FEATURE: add BasicCircuitBreaker
|
||||
- [#1650](https://github.com/c9s/bbgo/pull/1650): FIX: [okex] fix order book subscription channels
|
||||
- [#1651](https://github.com/c9s/bbgo/pull/1651): FEATURE: [okx] add conn info event
|
||||
- [#1647](https://github.com/c9s/bbgo/pull/1647): FIX: [retry] add initialAttempts to the order trades query backoff
|
||||
- [#1637](https://github.com/c9s/bbgo/pull/1637): CHORE: [atrpin] add symbol and window log fields
|
||||
- [#1643](https://github.com/c9s/bbgo/pull/1643): FIX: [binance] implement query trade for binance margin trading
|
||||
- [#1640](https://github.com/c9s/bbgo/pull/1640): FEATURE: [dca2] change state recovery logic
|
||||
- [#1642](https://github.com/c9s/bbgo/pull/1642): Refactor: add average depth price method
|
||||
- [#1641](https://github.com/c9s/bbgo/pull/1641): FEATURE: [dca2] new flag UniversalCancelAllOrdersWhenClose to decide …
|
||||
- [#1638](https://github.com/c9s/bbgo/pull/1638): FEATURE: [dca2] store price quantity pairs of the open-position order…
|
||||
- [#1639](https://github.com/c9s/bbgo/pull/1639): REFACTOR: move maker tools
|
||||
- [#1625](https://github.com/c9s/bbgo/pull/1625): CHORE: fix function names in comment
|
35
doc/release/v1.60.1.md
Normal file
35
doc/release/v1.60.1.md
Normal file
|
@ -0,0 +1,35 @@
|
|||
## Fixes
|
||||
|
||||
- fixed xmaker bugs
|
||||
- updated helm chart for sync cronjob
|
||||
- fixed max deposits api
|
||||
|
||||
[Full Changelog](https://github.com/c9s/bbgo/compare/v1.60.0...main)
|
||||
|
||||
- [#1727](https://github.com/c9s/bbgo/pull/1727): FIX: update timeInForce for binance margin order
|
||||
- [#1729](https://github.com/c9s/bbgo/pull/1729): FIX: [max] fix v3 deposit state conversion
|
||||
- [#1723](https://github.com/c9s/bbgo/pull/1723): FIX: [xmaker] avoid calculate margin from 0.0 signal
|
||||
- [#1721](https://github.com/c9s/bbgo/pull/1721): FIX: [xmaker] fix aggregatePrice method
|
||||
- [#1725](https://github.com/c9s/bbgo/pull/1725): IMPROVE: [xmaker] improve hedge margin account leverage calculation
|
||||
- [#1722](https://github.com/c9s/bbgo/pull/1722): FEATURE: [xmaker] add signals
|
||||
- [#1720](https://github.com/c9s/bbgo/pull/1720): FEATURE: [xmaker] margin credit improvement
|
||||
- [#1718](https://github.com/c9s/bbgo/pull/1718): FEATURE: [xmaker] add more config metrics
|
||||
- [#1719](https://github.com/c9s/bbgo/pull/1719): IMPROVE: [xmaker] fix bollinger band price calculation
|
||||
- [#1709](https://github.com/c9s/bbgo/pull/1709): IMPROVE: [xmaker] improve profit stats ticker and integrate rate limiter
|
||||
- [#1708](https://github.com/c9s/bbgo/pull/1708): FEATURE: [xmaker] integrate circuit breaker
|
||||
- [#1712](https://github.com/c9s/bbgo/pull/1712): FEATURE: [xmaker] add profit fixer
|
||||
- [#1710](https://github.com/c9s/bbgo/pull/1710): IMPROVE: [xmaker] improve stability
|
||||
- [#1717](https://github.com/c9s/bbgo/pull/1717): REFACTOR: [xmaker] refactor hedge worker and quote worker
|
||||
- [#1716](https://github.com/c9s/bbgo/pull/1716): FIX: [xmaker] profit object can be nil
|
||||
- [#1707](https://github.com/c9s/bbgo/pull/1707): FIX: [xmaker] position metrics missing label
|
||||
- [#1715](https://github.com/c9s/bbgo/pull/1715): UPGRADE: [go] upgrade packages that are too old
|
||||
- [#1713](https://github.com/c9s/bbgo/pull/1713): FEATURE: [chart] add env vars section
|
||||
- [#1711](https://github.com/c9s/bbgo/pull/1711): FEATURE: [binance] add new margin order side effect AUTO_BORROW_REPAY
|
||||
- [#1705](https://github.com/c9s/bbgo/pull/1705): FIX: [k8s] fix sync.enabled option
|
||||
- [#1704](https://github.com/c9s/bbgo/pull/1704): FEATURE: [k8s] add cronjob for sync
|
||||
- [#1700](https://github.com/c9s/bbgo/pull/1700): Fix: [autobuy] fix error when bollinger settings is not set
|
||||
- [#1703](https://github.com/c9s/bbgo/pull/1703): FEATURE: [core] add position metrics
|
||||
- [#1702](https://github.com/c9s/bbgo/pull/1702): IMPROVE: improve balance related metrics
|
||||
- [#1699](https://github.com/c9s/bbgo/pull/1699): REFACTOR: [twap] upgrade twap command and add optional order update rate limiter
|
||||
- [#1701](https://github.com/c9s/bbgo/pull/1701): RELEASE: v1.60.0
|
||||
- [#1714](https://github.com/c9s/bbgo/pull/1714): dep: bump actions/setup-node from 2 to 4
|
18
doc/release/v1.60.2.md
Normal file
18
doc/release/v1.60.2.md
Normal file
|
@ -0,0 +1,18 @@
|
|||
[Full Changelog](https://github.com/c9s/bbgo/compare/v1.60.1...main)
|
||||
|
||||
- [#1739](https://github.com/c9s/bbgo/pull/1739): FEATURE: [dca2] set exchange fee rate for round position
|
||||
- [#1738](https://github.com/c9s/bbgo/pull/1738): FEATURE: [okx] update symbols to latest
|
||||
- [#1737](https://github.com/c9s/bbgo/pull/1737): FEATURE: [xmaker] implement tryArbitrage
|
||||
- [#1730](https://github.com/c9s/bbgo/pull/1730): FEATURE: [xmaker] add market trade signal
|
||||
- [#1734](https://github.com/c9s/bbgo/pull/1734): REFACTOR: [xmaker] refactor for supporting ioc arb [part1]
|
||||
- [#1736](https://github.com/c9s/bbgo/pull/1736): MINOR: [session] remove environment nil validation log
|
||||
- [#1742](https://github.com/c9s/bbgo/pull/1742): FIX: types/stream: change errorf to warnf
|
||||
- [#1741](https://github.com/c9s/bbgo/pull/1741): FIX: upgrade github.com/c9s/requestgen to 1.4.3
|
||||
- [#1740](https://github.com/c9s/bbgo/pull/1740): FIX: upgrade requestgen and re-generate max cancel order request files
|
||||
- [#1726](https://github.com/c9s/bbgo/pull/1726): dep: bump morphy2k/revive-action from 2.5.9 to 2.5.10
|
||||
- [#1735](https://github.com/c9s/bbgo/pull/1735): FIX: configure environment
|
||||
- [#1724](https://github.com/c9s/bbgo/pull/1724): FIX: fix slice init length
|
||||
- [#1733](https://github.com/c9s/bbgo/pull/1733): FIX: [bbgo] fix the defaults / initialize steps
|
||||
- [#1732](https://github.com/c9s/bbgo/pull/1732): FIX: fix env name
|
||||
- [#1728](https://github.com/c9s/bbgo/pull/1728): FIX: [core] fix memory leak
|
||||
- [#1731](https://github.com/c9s/bbgo/pull/1731): FIX: fix json tag
|
4
doc/release/v1.60.3.md
Normal file
4
doc/release/v1.60.3.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
[Full Changelog](https://github.com/c9s/bbgo/compare/v1.60.2...main)
|
||||
|
||||
- FIX: fix xmaker default price
|
||||
- [#1744](https://github.com/c9s/bbgo/pull/1744): call b.EmitNew() when new order is added into activeorderbook
|
|
@ -48,7 +48,7 @@ var rootCmd = &cobra.Command{
|
|||
stream.SetPublicOnly()
|
||||
stream.Subscribe(types.BookChannel, symbol, types.SubscribeOptions{})
|
||||
|
||||
streamBook := types.NewStreamBook(symbol)
|
||||
streamBook := types.NewStreamBook(symbol, exchange.Name())
|
||||
streamBook.BindStream(stream)
|
||||
|
||||
go func() {
|
||||
|
|
96
go.mod
96
go.mod
|
@ -2,16 +2,16 @@
|
|||
|
||||
module github.com/c9s/bbgo
|
||||
|
||||
go 1.21
|
||||
go 1.21.0
|
||||
|
||||
toolchain go1.21.6
|
||||
|
||||
require (
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||
github.com/Masterminds/squirrel v1.5.3
|
||||
github.com/adshao/go-binance/v2 v2.5.0
|
||||
github.com/adshao/go-binance/v2 v2.6.0
|
||||
github.com/c-bata/goptuna v0.8.1
|
||||
github.com/c9s/requestgen v1.3.6
|
||||
github.com/c9s/requestgen v1.4.3
|
||||
github.com/c9s/rockhopper/v2 v2.0.4
|
||||
github.com/cenkalti/backoff/v4 v4.2.0
|
||||
github.com/cheggaaa/pb/v3 v3.0.8
|
||||
|
@ -20,13 +20,13 @@ require (
|
|||
github.com/fatih/camelcase v1.0.0
|
||||
github.com/fatih/color v1.14.1
|
||||
github.com/gertd/go-pluralize v0.2.1
|
||||
github.com/gin-contrib/cors v1.3.1
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/go-redis/redis/v8 v8.8.0
|
||||
github.com/gin-contrib/cors v1.7.2
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/go-redis/redis/v8 v8.11.5
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/gofrs/flock v0.8.1
|
||||
github.com/google/uuid v1.4.0
|
||||
github.com/gorilla/websocket v1.5.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/heroku/rollrus v0.2.0
|
||||
github.com/jedib0t/go-pretty/v6 v6.5.8
|
||||
github.com/jmoiron/sqlx v1.3.4
|
||||
|
@ -55,72 +55,77 @@ require (
|
|||
github.com/zserge/lorca v0.1.9
|
||||
go.uber.org/mock v0.4.0
|
||||
go.uber.org/multierr v1.11.0
|
||||
golang.org/x/oauth2 v0.15.0
|
||||
golang.org/x/sync v0.7.0
|
||||
golang.org/x/time v0.5.0
|
||||
golang.org/x/oauth2 v0.22.0
|
||||
golang.org/x/sync v0.8.0
|
||||
golang.org/x/time v0.6.0
|
||||
gonum.org/v1/gonum v0.8.2
|
||||
google.golang.org/api v0.153.0
|
||||
google.golang.org/grpc v1.59.0
|
||||
google.golang.org/protobuf v1.31.0
|
||||
google.golang.org/api v0.194.0
|
||||
google.golang.org/grpc v1.65.0
|
||||
google.golang.org/protobuf v1.34.2
|
||||
gopkg.in/tucnak/telebot.v2 v2.5.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute v1.23.3 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/auth v0.9.1 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.5.0 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/VividCortex/ewma v1.1.1 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bitly/go-simplejson v0.5.1 // indirect
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||
github.com/bytedance/sonic v1.9.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/bytedance/sonic v1.12.1 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/cockroachdb/apd v1.1.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/denisenkom/go-mssqldb v0.12.3 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.22.0 // indirect
|
||||
github.com/go-test/deep v1.0.6 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/s2a-go v0.1.8 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
|
||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/lestrrat-go/strftime v1.0.0 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.23 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.32.1 // indirect
|
||||
|
@ -137,23 +142,24 @@ require (
|
|||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/tebeka/strftime v0.1.3 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/ziutek/mymysql v1.5.4 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/otel v0.19.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v0.19.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v0.19.0 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
|
||||
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||
golang.org/x/arch v0.9.0 // indirect
|
||||
golang.org/x/crypto v0.26.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect
|
||||
golang.org/x/image v0.5.0 // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/net v0.24.0 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
golang.org/x/term v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.20.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect
|
||||
golang.org/x/mod v0.20.0 // indirect
|
||||
golang.org/x/net v0.28.0 // indirect
|
||||
golang.org/x/sys v0.24.0 // indirect
|
||||
golang.org/x/term v0.23.0 // indirect
|
||||
golang.org/x/text v0.17.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
)
|
||||
|
|
245
go.sum
245
go.sum
|
@ -13,16 +13,18 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV
|
|||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go/auth v0.9.1 h1:+pMtLEV2k0AXKvs/tGZojuj6QaioxfUjOpMsG5Gtx+w=
|
||||
cloud.google.com/go/auth v0.9.1/go.mod h1:Sw8ocT5mhhXxFklyhT12Eiy0ed6tTrPMCJjSI8KhYLk=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk=
|
||||
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
|
||||
cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
|
@ -44,16 +46,16 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2
|
|||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
||||
github.com/Masterminds/squirrel v1.5.3 h1:YPpoceAcxuzIljlr5iWpNKaql7hLeG1KLSrhvdHpkZc=
|
||||
github.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
|
||||
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
|
||||
github.com/adshao/go-binance/v2 v2.5.0 h1:mk8ylSjIzDYVBF9Wf2KXu6GWD/Ws4LLzD9q2R2mqZB0=
|
||||
github.com/adshao/go-binance/v2 v2.5.0/go.mod h1:41Up2dG4NfMXpCldrDPETEtiOq+pHoGsFZ73xGgaumo=
|
||||
github.com/adshao/go-binance/v2 v2.6.0 h1:sXPkfix+SgBojJmkt+sNJbJBQZOJK5GFP/WtAu+B5r0=
|
||||
github.com/adshao/go-binance/v2 v2.6.0/go.mod h1:41Up2dG4NfMXpCldrDPETEtiOq+pHoGsFZ73xGgaumo=
|
||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
|
@ -77,13 +79,15 @@ github.com/bitly/go-simplejson v0.5.1/go.mod h1:YOPVLzCfwK14b4Sff3oP1AmGhI9T9Vsg
|
|||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
github.com/bytedance/sonic v1.12.1 h1:jWl5Qz1fy7X1ioY74WqO0KjAMtAGQs4sYnjiEBiyX24=
|
||||
github.com/bytedance/sonic v1.12.1/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=
|
||||
github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/c-bata/goptuna v0.8.1 h1:25+n1MLv0yvCsD56xv4nqIus3oLHL9GuPAZDLIqmX1U=
|
||||
github.com/c-bata/goptuna v0.8.1/go.mod h1:knmS8+Iyq5PPy1YUeIEq0pMFR4Y6x7z/CySc9HlZTCY=
|
||||
github.com/c9s/requestgen v1.3.6 h1:ul7dZ2uwGYjNBjreooRfSY10WTXvQmQSjZsHebz6QfE=
|
||||
github.com/c9s/requestgen v1.3.6/go.mod h1:QwkZudcv84kJ8g9+E0RDTj+13btFXbTvv2aI+zbuLbc=
|
||||
github.com/c9s/requestgen v1.4.3 h1:0QZ27RVBLb9QuBKfiSBTOB5zSUuasrJm2p6/GZZHZZw=
|
||||
github.com/c9s/requestgen v1.4.3/go.mod h1:3gk1M2ihvNU2wWl7WLUc09myp7XpHMP33Dx96+Vr8A0=
|
||||
github.com/c9s/rockhopper/v2 v2.0.4 h1:1cQEzU7rzCSz09B2RYdyPWwBW9gZ/DoFqD1b2xLLmAk=
|
||||
github.com/c9s/rockhopper/v2 v2.0.4/go.mod h1:x0XuYI2Su3kS/74UYu/3Cqc9m5Dtzqh7j7JZarczfss=
|
||||
github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
|
||||
|
@ -91,13 +95,10 @@ github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY
|
|||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cheggaaa/pb/v3 v3.0.8 h1:bC8oemdChbke2FHIIGy9mn4DPJ2caZYQnfbRqwmdCoA=
|
||||
github.com/cheggaaa/pb/v3 v3.0.8/go.mod h1:UICbiLec/XO6Hw6k+BHEtHeQFzzBH4i2/qk/ow1EJTA=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/chewxy/hm v1.0.0/go.mod h1:qg9YI4q6Fkj/whwHR1D+bOGeF7SniIP40VweVepLjg0=
|
||||
github.com/chewxy/math32 v1.0.0/go.mod h1:Miac6hA1ohdDUTagnvJy/q+aNnEk16qWUdb8ZVhvCN0=
|
||||
github.com/chewxy/math32 v1.0.6/go.mod h1:dOB2rcuFrCn6UHrze36WSLVPKtzPMRAQvBvUwkSsLqs=
|
||||
|
@ -106,6 +107,10 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
|
|||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/cfssl v0.0.0-20190808011637-b1ec8c586c2a/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
|
||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
|
@ -153,25 +158,25 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
|
|||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
|
||||
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
|
||||
github.com/gertd/go-pluralize v0.2.1 h1:M3uASbVjMnTsPb0PNqg+E/24Vwigyo/tvyMTtAlLgiA=
|
||||
github.com/gertd/go-pluralize v0.2.1/go.mod h1:rbYaKDbsXxmRfr8uygAEKhOWsjyrrqrkHVpZvoOp8zk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gin-contrib/cors v1.3.1 h1:doAsuITavI4IOcd0Y19U4B+O0dNWihRyX//nn4sEmgA=
|
||||
github.com/gin-contrib/cors v1.3.1/go.mod h1:jjEJ4268OPZUcU7k9Pm653S7lXUGcqMADzFA61xsmDk=
|
||||
github.com/gin-contrib/cors v1.7.2 h1:oLDHxdg8W/XDoN/8zamqk/Drgt4oVZDvaV0YmvVICQw=
|
||||
github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
|
@ -182,18 +187,21 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb
|
|||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
||||
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||
github.com/go-redis/redis/v8 v8.8.0 h1:fDZP58UN/1RD3DjtTXP/fFZ04TFohSYhjZDkcDe2dnw=
|
||||
github.com/go-redis/redis/v8 v8.8.0/go.mod h1:F7resOH5Kdug49Otu24RjHWwgK7u9AmtqWMnCV1iP5Y=
|
||||
github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
|
||||
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
|
@ -201,8 +209,8 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
|
|||
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
github.com/go-test/deep v1.0.6 h1:UHSEyLZUwX9Qoi99vVwvewiMC8mM2bf7XEM2nqvzEn8=
|
||||
github.com/go-test/deep v1.0.6/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
|
@ -245,9 +253,8 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq
|
|||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
|
@ -277,24 +284,24 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf
|
|||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
|
||||
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
||||
github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
|
||||
github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
|
||||
github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
|
||||
github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s=
|
||||
github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorgonia/bindgen v0.0.0-20180812032444-09626750019e/go.mod h1:YzKk63P9jQHkwAo2rXHBv02yPxDzoQT2cBV0x5bGV/8=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
|
@ -321,7 +328,6 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
|
|||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/heroku/rollrus v0.2.0 h1:b3AgcXJKFJNUwbQOC2S69/+mxuTpe4laznem9VJdPEo=
|
||||
github.com/heroku/rollrus v0.2.0/go.mod h1:B3MwEcr9nmf4xj0Sr5l9eSht7wLKMa1C+9ajgAU79ek=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
|
@ -384,7 +390,6 @@ github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0
|
|||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
|
@ -398,9 +403,11 @@ github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E
|
|||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
|
@ -421,9 +428,8 @@ github.com/leekchan/accounting v0.0.0-20191218023648-17a4ce5f94d4 h1:KZzDAtJ7ZLm
|
|||
github.com/leekchan/accounting v0.0.0-20191218023648-17a4ce5f94d4/go.mod h1:3timm6YPhY3YDaGxl0q3eaflX0eoSx3FXn7ckHe4tO0=
|
||||
github.com/leesper/go_rng v0.0.0-20171009123644-5344a9259b21/go.mod h1:N0SVk0uhy+E1PZ3C9ctsPRlvOPAFPkCNlcPBDkt0N3U=
|
||||
github.com/leesper/go_rng v0.0.0-20190531154944-a612b043e353/go.mod h1:N0SVk0uhy+E1PZ3C9ctsPRlvOPAFPkCNlcPBDkt0N3U=
|
||||
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
|
||||
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
|
||||
github.com/lestrrat-go/file-rotatelogs v2.2.0+incompatible h1:eXEwY0f2h6mcobdAxm4VRSWds4tqmlLdUqxu8ybiEEA=
|
||||
|
@ -466,8 +472,8 @@ github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lL
|
|||
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
|
||||
github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0=
|
||||
github.com/mattn/go-sqlite3 v1.14.23/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
|
||||
|
@ -497,22 +503,17 @@ github.com/muesli/kmeans v0.3.0 h1:cI2cpeS8m3pm+gTOdzl+7SlzZYSe+x0XoqXUyUvb1ro=
|
|||
github.com/muesli/kmeans v0.3.0/go.mod h1:eNyybq0tX9/iBEP6EMU4Y7dpmGK0uEhODdZpnG1a/iQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4=
|
||||
github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.10.5 h1:7n6FEkpFmfCoo2t+YYqXH0evK+a9ICQz0xcAy9dYcaQ=
|
||||
github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
||||
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo=
|
||||
github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
|
@ -637,8 +638,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
|
@ -649,10 +648,8 @@ github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIU
|
|||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/valyala/fastjson v1.5.1 h1:SXaQZVSwLjZOVhDEhjiCcDtnX0Feu7Z7A1+C5atpoHM=
|
||||
github.com/valyala/fastjson v1.5.1/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.0 h1:tY2slqVQ6bN+yHSnDYwZebLQFkphK4WNrVwnt7CJZ2I=
|
||||
|
@ -666,7 +663,6 @@ github.com/xtgo/set v1.0.0/go.mod h1:d3NHzGzSa0NmB2NhFyECA+QdRp29oEn2xbT+TpeFoM8
|
|||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
|
||||
|
@ -681,14 +677,14 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/otel v0.19.0 h1:Lenfy7QHRXPZVsw/12CWpxX6d/JkrX8wrx2vO8G80Ng=
|
||||
go.opentelemetry.io/otel v0.19.0/go.mod h1:j9bF567N9EfomkSidSfmMwIwIBuP37AMAIzVW85OxSg=
|
||||
go.opentelemetry.io/otel/metric v0.19.0 h1:dtZ1Ju44gkJkYvo+3qGqVXmf88tc+a42edOywypengg=
|
||||
go.opentelemetry.io/otel/metric v0.19.0/go.mod h1:8f9fglJPRnXuskQmKpnad31lcLJ2VmNNqIsx/uIwBSc=
|
||||
go.opentelemetry.io/otel/oteltest v0.19.0 h1:YVfA0ByROYqTwOxqHVZYZExzEpfZor+MU1rU+ip2v9Q=
|
||||
go.opentelemetry.io/otel/oteltest v0.19.0/go.mod h1:tI4yxwh8U21v7JD6R3BcA/2+RBoTKFexE/PJ/nSO7IA=
|
||||
go.opentelemetry.io/otel/trace v0.19.0 h1:1ucYlenXIDA1OlHVLDZKX0ObXV5RLaq06DtUKz5e5zc=
|
||||
go.opentelemetry.io/otel/trace v0.19.0/go.mod h1:4IXiNextNOpPnRlI4ryK69mn5iC84bjBWZQA5DXz/qg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
|
||||
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
|
||||
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
|
||||
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
|
||||
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
|
||||
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
|
||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
|
@ -702,9 +698,8 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E
|
|||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
||||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.9.0 h1:ub9TgUInamJ8mrZIGlBG6/4TqWeMszd4N8lNorbrr6k=
|
||||
golang.org/x/arch v0.9.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
|
@ -721,8 +716,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
|||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
|
@ -764,8 +759,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
|
|||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -796,30 +791,27 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
|
|||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
|
||||
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
|
||||
golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA=
|
||||
golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -828,15 +820,13 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -855,10 +845,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -881,24 +868,23 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
|
||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
|
||||
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -907,13 +893,13 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
@ -964,10 +950,9 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY
|
|||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
|
||||
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -1001,16 +986,14 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
|
|||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4=
|
||||
google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY=
|
||||
google.golang.org/api v0.194.0 h1:dztZKG9HgtIpbI35FhfuSNR/zmaMVdxNlntHj1sIS4s=
|
||||
google.golang.org/api v0.194.0/go.mod h1:AgvUFdojGANh3vI+P7EVnxj3AISHllxGCJSFmggmnd0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
|
@ -1042,12 +1025,10 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D
|
|||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ=
|
||||
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
|
@ -1062,8 +1043,8 @@ google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
|
|||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
|
||||
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
|
||||
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
|
||||
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200910201057-6591123024b3/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
|
@ -1076,19 +1057,16 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
|
|||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
|
@ -1142,6 +1120,7 @@ modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
|
|||
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
|
||||
modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
|
||||
modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
|
|
14
migrations/mysql/20240531163411_trades_created.sql
Normal file
14
migrations/mysql/20240531163411_trades_created.sql
Normal file
|
@ -0,0 +1,14 @@
|
|||
-- +up
|
||||
-- +begin
|
||||
ALTER TABLE `trades` ADD COLUMN `inserted_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL AFTER `traded_at`;
|
||||
-- +end
|
||||
|
||||
-- +begin
|
||||
UPDATE `trades` SET `inserted_at` = `traded_at`;
|
||||
-- +end
|
||||
|
||||
-- +down
|
||||
|
||||
-- +begin
|
||||
ALTER TABLE `trades` DROP COLUMN `inserted_at`;
|
||||
-- +end
|
10
migrations/mysql/20240918132534_add_position_index.sql
Normal file
10
migrations/mysql/20240918132534_add_position_index.sql
Normal file
|
@ -0,0 +1,10 @@
|
|||
-- +up
|
||||
-- +begin
|
||||
CREATE INDEX positions_traded_at ON positions (traded_at, profit);
|
||||
-- +end
|
||||
|
||||
-- +down
|
||||
|
||||
-- +begin
|
||||
DROP INDEX positions_traded_at ON positions;
|
||||
-- +end
|
23
migrations/sqlite3/20240531163411_trades_created.sql
Normal file
23
migrations/sqlite3/20240531163411_trades_created.sql
Normal file
|
@ -0,0 +1,23 @@
|
|||
-- +up
|
||||
-- +begin
|
||||
ALTER TABLE trades ADD COLUMN inserted_at TEXT;
|
||||
|
||||
UPDATE trades SET inserted_at = traded_at;
|
||||
|
||||
CREATE TRIGGER set_inserted_at
|
||||
AFTER INSERT ON trades
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE trades
|
||||
SET inserted_at = datetime('now')
|
||||
WHERE rowid = NEW.rowid;
|
||||
END;
|
||||
|
||||
-- +end
|
||||
|
||||
-- +down
|
||||
|
||||
-- +begin
|
||||
DROP TRIGGER set_inserted_at;
|
||||
ALTER TABLE trades DROP COLUMN inserted_at;
|
||||
-- +end
|
10
migrations/sqlite3/20240918132534_add_position_index.sql
Normal file
10
migrations/sqlite3/20240918132534_add_position_index.sql
Normal file
|
@ -0,0 +1,10 @@
|
|||
-- +up
|
||||
-- +begin
|
||||
CREATE INDEX positions_traded_at ON positions (traded_at, profit);
|
||||
-- +end
|
||||
|
||||
-- +down
|
||||
|
||||
-- +begin
|
||||
DROP INDEX positions_traded_at;
|
||||
-- +end
|
|
@ -359,6 +359,7 @@ func (b *ActiveOrderBook) Add(orders ...types.Order) {
|
|||
}
|
||||
|
||||
b.add(order)
|
||||
b.EmitNew(order)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,6 +467,12 @@ func (b *ActiveOrderBook) Lookup(f func(o types.Order) bool) *types.Order {
|
|||
|
||||
func (b *ActiveOrderBook) filterExistingOrders(orders []types.Order) (existingOrders types.OrderSlice) {
|
||||
for _, o := range orders {
|
||||
// skip market order
|
||||
// this prevents if someone added a market order to the active order book
|
||||
if o.Type == types.OrderTypeMarket {
|
||||
continue
|
||||
}
|
||||
|
||||
if b.Exists(o) {
|
||||
existingOrders.Add(o)
|
||||
}
|
||||
|
|
|
@ -346,6 +346,8 @@ type EnvironmentConfig struct {
|
|||
DisableMarketDataStore bool `json:"disableMarketDataStore"`
|
||||
|
||||
MaxSessionTradeBufferSize int `json:"maxSessionTradeBufferSize"`
|
||||
|
||||
SyncBufferPeriod *types.Duration `json:"syncBufferPeriod"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
|
|
|
@ -37,6 +37,8 @@ func init() {
|
|||
rand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
|
||||
var defaultSyncBufferPeriod = 30 * time.Minute
|
||||
|
||||
// IsBackTesting is a global variable that indicates the current environment is back-test or not.
|
||||
var IsBackTesting = false
|
||||
|
||||
|
@ -645,7 +647,17 @@ func (environ *Environment) syncSession(
|
|||
|
||||
log.Infof("syncing symbols %v from session %s", symbols, session.Name)
|
||||
|
||||
return environ.SyncService.SyncSessionSymbols(ctx, session.Exchange, syncStartTime, symbols...)
|
||||
syncBufferPeriod := -defaultSyncBufferPeriod
|
||||
if environ.environmentConfig != nil && environ.environmentConfig.SyncBufferPeriod != nil {
|
||||
syncBufferPeriod = -environ.environmentConfig.SyncBufferPeriod.Duration()
|
||||
}
|
||||
|
||||
if syncBufferPeriod > 0 {
|
||||
log.Warnf("syncBufferPeriod should be a negative number, given: %d", syncBufferPeriod)
|
||||
}
|
||||
|
||||
syncEndTime := time.Now().Add(syncBufferPeriod)
|
||||
return environ.SyncService.SyncSessionSymbols(ctx, session.Exchange, syncStartTime, syncEndTime, symbols...)
|
||||
}
|
||||
|
||||
func (environ *Environment) ConfigureNotificationSystem(ctx context.Context, userConfig *Config) error {
|
||||
|
|
|
@ -5,6 +5,8 @@ import "github.com/c9s/bbgo/pkg/types"
|
|||
const MaxNumOfKLines = 5_000
|
||||
const MaxNumOfKLinesTruncate = 100
|
||||
|
||||
const CapacityOfKLineWindowLimit = 5_000
|
||||
|
||||
// MarketDataStore receives and maintain the public market data of a single symbol
|
||||
//go:generate callbackgen -type MarketDataStore
|
||||
type MarketDataStore struct {
|
||||
|
@ -57,10 +59,20 @@ func (store *MarketDataStore) AddKLine(k types.KLine) {
|
|||
}
|
||||
window.Add(k)
|
||||
|
||||
if len(*window) > MaxNumOfKLines {
|
||||
*window = (*window)[MaxNumOfKLinesTruncate-1:]
|
||||
}
|
||||
truncateKLineWindowIfNeeded(window)
|
||||
|
||||
store.EmitKLineClosed(k)
|
||||
store.EmitKLineWindowUpdate(k.Interval, *window)
|
||||
}
|
||||
|
||||
func truncateKLineWindowIfNeeded(window *types.KLineWindow) {
|
||||
lenOfWindow := len(*window)
|
||||
capOfWindow := cap(*window)
|
||||
|
||||
if lenOfWindow == capOfWindow && capOfWindow > CapacityOfKLineWindowLimit {
|
||||
size := CapacityOfKLineWindowLimit / 2
|
||||
start := lenOfWindow - size
|
||||
copy(*window, (*window)[start:])
|
||||
*window = (*window)[:size]
|
||||
}
|
||||
}
|
||||
|
|
45
pkg/bbgo/marketdatastore_test.go
Normal file
45
pkg/bbgo/marketdatastore_test.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
package bbgo
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMarketDataStore_AddKLineAndTruncateWindow(t *testing.T) {
|
||||
store := NewMarketDataStore("BTCUSD")
|
||||
|
||||
interval := types.Interval1s
|
||||
|
||||
var maxCap int = 0
|
||||
capFixed := false
|
||||
|
||||
var gid uint64 = 0
|
||||
// insert 1.5 * CapacityOfKLineWindowLimit KLine into window
|
||||
for ; gid < CapacityOfKLineWindowLimit+(CapacityOfKLineWindowLimit/2); gid++ {
|
||||
store.AddKLine(types.KLine{
|
||||
Interval: interval,
|
||||
GID: gid,
|
||||
})
|
||||
|
||||
// if the capacity is > CapacityOfKLineWindowLimit, the capacity should be fixed. We use this if expression to verify it then.
|
||||
if !capFixed && cap(*store.KLineWindows[interval]) > CapacityOfKLineWindowLimit {
|
||||
maxCap = cap(*store.KLineWindows[interval])
|
||||
capFixed = true
|
||||
}
|
||||
}
|
||||
|
||||
window := store.KLineWindows[interval]
|
||||
|
||||
// make sure the capacity is fixed
|
||||
assert.Equal(t, maxCap, cap(*window))
|
||||
|
||||
// after truncate, it will remain (CapacityOfKLineWindowLimit / 2) KLine in the window
|
||||
// so the first GIC will be the maxCap - (CapacityOfKLineWindowLimit / 2)
|
||||
truncatedGID := uint64(maxCap - (CapacityOfKLineWindowLimit / 2))
|
||||
for _, kline := range *window {
|
||||
assert.Equal(t, truncatedGID, kline.GID)
|
||||
truncatedGID++
|
||||
}
|
||||
}
|
|
@ -9,35 +9,94 @@ var (
|
|||
Help: "bbgo exchange session connection status",
|
||||
},
|
||||
[]string{
|
||||
"exchange", // exchange name
|
||||
"channel", // channel: user or market
|
||||
"margin", // margin type: none, margin or isolated
|
||||
"symbol", // margin symbol of the connection.
|
||||
"session",
|
||||
"exchange", // exchange name
|
||||
"channel", // channel: user or market
|
||||
"margin_type", // margin type: none, margin or isolated
|
||||
"symbol", // margin symbol of the connection.
|
||||
},
|
||||
)
|
||||
|
||||
metricsLockedBalances = prometheus.NewGaugeVec(
|
||||
metricsBalanceLockedMetrics = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "bbgo_balances_locked",
|
||||
Help: "bbgo exchange locked balances",
|
||||
},
|
||||
[]string{
|
||||
"exchange", // exchange name
|
||||
"margin", // margin of connection. 1 or 0
|
||||
"symbol", // margin symbol of the connection.
|
||||
"session",
|
||||
"exchange", // exchange name
|
||||
"margin_type", // margin of connection. 1 or 0
|
||||
"symbol", // margin symbol of the connection.
|
||||
"currency",
|
||||
},
|
||||
)
|
||||
|
||||
metricsAvailableBalances = prometheus.NewGaugeVec(
|
||||
metricsBalanceAvailableMetrics = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "bbgo_balances_available",
|
||||
Help: "bbgo exchange available balances",
|
||||
},
|
||||
[]string{
|
||||
"exchange", // exchange name
|
||||
"margin", // margin of connection. none, margin or isolated
|
||||
"symbol", // margin symbol of the connection.
|
||||
"session",
|
||||
"exchange", // exchange name
|
||||
"margin_type", // margin of connection. none, margin or isolated
|
||||
"symbol", // margin symbol of the connection.
|
||||
"currency",
|
||||
},
|
||||
)
|
||||
|
||||
metricsBalanceDebtMetrics = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "bbgo_balances_debt",
|
||||
Help: "bbgo exchange balance debt",
|
||||
},
|
||||
[]string{
|
||||
"session",
|
||||
"exchange", // exchange name
|
||||
"margin_type", // margin of connection. none, margin or isolated
|
||||
"symbol", // margin symbol of the connection.
|
||||
"currency",
|
||||
},
|
||||
)
|
||||
|
||||
metricsBalanceBorrowedMetrics = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "bbgo_balances_borrowed",
|
||||
Help: "bbgo exchange balance borrowed",
|
||||
},
|
||||
[]string{
|
||||
"session",
|
||||
"exchange", // exchange name
|
||||
"margin_type", // margin of connection. none, margin or isolated
|
||||
"symbol", // margin symbol of the connection.
|
||||
"currency",
|
||||
},
|
||||
)
|
||||
|
||||
metricsBalanceInterestMetrics = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "bbgo_balances_interest",
|
||||
Help: "bbgo exchange balance interest",
|
||||
},
|
||||
[]string{
|
||||
"session",
|
||||
"exchange", // exchange name
|
||||
"margin_type", // margin of connection. none, margin or isolated
|
||||
"symbol", // margin symbol of the connection.
|
||||
"currency",
|
||||
},
|
||||
)
|
||||
|
||||
metricsBalanceNetMetrics = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "bbgo_balances_net",
|
||||
Help: "bbgo exchange session total net balances",
|
||||
},
|
||||
[]string{
|
||||
"session",
|
||||
"exchange", // exchange name
|
||||
"margin_type", // margin of connection. none, margin or isolated
|
||||
"symbol", // margin symbol of the connection.
|
||||
"currency",
|
||||
},
|
||||
)
|
||||
|
@ -48,9 +107,10 @@ var (
|
|||
Help: "bbgo exchange session total balances",
|
||||
},
|
||||
[]string{
|
||||
"exchange", // exchange name
|
||||
"margin", // margin of connection. none, margin or isolated
|
||||
"symbol", // margin symbol of the connection.
|
||||
"session",
|
||||
"exchange", // exchange name
|
||||
"margin_type", // margin of connection. none, margin or isolated
|
||||
"symbol", // margin symbol of the connection.
|
||||
"currency",
|
||||
},
|
||||
)
|
||||
|
@ -61,11 +121,12 @@ var (
|
|||
Help: "bbgo exchange session trades",
|
||||
},
|
||||
[]string{
|
||||
"exchange", // exchange name
|
||||
"margin", // margin of connection. none, margin or isolated
|
||||
"symbol", // margin symbol of the connection.
|
||||
"side", // side: buy or sell
|
||||
"liquidity", // maker or taker
|
||||
"session",
|
||||
"exchange", // exchange name
|
||||
"margin_type", // margin of connection. none, margin or isolated
|
||||
"symbol", // margin symbol of the connection.
|
||||
"side", // side: buy or sell
|
||||
"liquidity", // maker or taker
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -75,26 +136,28 @@ var (
|
|||
Help: "bbgo trading volume",
|
||||
},
|
||||
[]string{
|
||||
"exchange", // exchange name
|
||||
"margin", // margin of connection. none, margin or isolated
|
||||
"symbol", // margin symbol of the connection.
|
||||
"side", // side: buy or sell
|
||||
"liquidity", // maker or taker
|
||||
"session",
|
||||
"exchange", // exchange name
|
||||
"margin_type", // margin of connection. none, margin or isolated
|
||||
"symbol", // margin symbol of the connection.
|
||||
"side", // side: buy or sell
|
||||
"liquidity", // maker or taker
|
||||
},
|
||||
)
|
||||
|
||||
metricsLastUpdateTimeBalance = prometheus.NewGaugeVec(
|
||||
metricsLastUpdateTimeMetrics = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "bbgo_last_update_time",
|
||||
Help: "bbgo last update time of different channel",
|
||||
},
|
||||
[]string{
|
||||
"exchange", // exchange name
|
||||
"margin", // margin of connection. none, margin or isolated
|
||||
"channel", // channel: user, market
|
||||
"data_type", // type: balance, ticker, kline, orderbook, trade, order
|
||||
"symbol", // for market data, trade and order
|
||||
"currency", // for balance
|
||||
"session",
|
||||
"exchange", // exchange name
|
||||
"margin_type", // margin of connection. none, margin or isolated
|
||||
"channel", // channel: user, market
|
||||
"data_type", // type: balance, ticker, kline, orderbook, trade, order
|
||||
"symbol", // for market data, trade and order
|
||||
"currency", // for balance
|
||||
},
|
||||
)
|
||||
)
|
||||
|
@ -103,10 +166,14 @@ func init() {
|
|||
prometheus.MustRegister(
|
||||
metricsConnectionStatus,
|
||||
metricsTotalBalances,
|
||||
metricsLockedBalances,
|
||||
metricsAvailableBalances,
|
||||
metricsBalanceNetMetrics,
|
||||
metricsBalanceLockedMetrics,
|
||||
metricsBalanceAvailableMetrics,
|
||||
metricsBalanceDebtMetrics,
|
||||
metricsBalanceBorrowedMetrics,
|
||||
metricsBalanceInterestMetrics,
|
||||
metricsTradesTotal,
|
||||
metricsTradingVolume,
|
||||
metricsLastUpdateTimeBalance,
|
||||
metricsLastUpdateTimeMetrics,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -27,7 +27,9 @@ var quantityReduceDelta = fixedpoint.NewFromFloat(0.005)
|
|||
// This is for the maximum retries
|
||||
const submitOrderRetryLimit = 5
|
||||
|
||||
// BaseOrderExecutor provides the common accessors for order executor
|
||||
type BaseOrderExecutor struct {
|
||||
exchange types.Exchange
|
||||
session *ExchangeSession
|
||||
activeMakerOrders *ActiveOrderBook
|
||||
orderStore *core.OrderStore
|
||||
|
@ -43,8 +45,8 @@ func (e *BaseOrderExecutor) ActiveMakerOrders() *ActiveOrderBook {
|
|||
|
||||
// GracefulCancel cancels all active maker orders if orders are not given, otherwise cancel all the given orders
|
||||
func (e *BaseOrderExecutor) GracefulCancel(ctx context.Context, orders ...types.Order) error {
|
||||
if err := e.activeMakerOrders.GracefulCancel(ctx, e.session.Exchange, orders...); err != nil {
|
||||
return errors.Wrap(err, "graceful cancel error")
|
||||
if err := e.activeMakerOrders.GracefulCancel(ctx, e.exchange, orders...); err != nil {
|
||||
return errors.Wrap(err, "graceful cancel order error")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -84,6 +86,7 @@ func NewGeneralOrderExecutor(
|
|||
executor := &GeneralOrderExecutor{
|
||||
BaseOrderExecutor: BaseOrderExecutor{
|
||||
session: session,
|
||||
exchange: session.Exchange,
|
||||
activeMakerOrders: NewActiveOrderBook(symbol),
|
||||
orderStore: orderStore,
|
||||
},
|
||||
|
@ -111,7 +114,7 @@ func (e *GeneralOrderExecutor) SetMaxRetries(maxRetries uint) {
|
|||
}
|
||||
|
||||
func (e *GeneralOrderExecutor) startMarginAssetUpdater(ctx context.Context) {
|
||||
marginService, ok := e.session.Exchange.(types.MarginBorrowRepayService)
|
||||
marginService, ok := e.exchange.(types.MarginBorrowRepayService)
|
||||
if !ok {
|
||||
log.Warnf("session %s (%T) exchange does not support MarginBorrowRepayService", e.session.Name, e.session.Exchange)
|
||||
return
|
||||
|
|
|
@ -22,6 +22,7 @@ func NewSimpleOrderExecutor(session *ExchangeSession) *SimpleOrderExecutor {
|
|||
return &SimpleOrderExecutor{
|
||||
BaseOrderExecutor: BaseOrderExecutor{
|
||||
session: session,
|
||||
exchange: session.Exchange,
|
||||
activeMakerOrders: NewActiveOrderBook(""),
|
||||
orderStore: core.NewOrderStore(""),
|
||||
},
|
||||
|
|
|
@ -12,12 +12,16 @@ type Quota struct {
|
|||
Locked fixedpoint.Value
|
||||
}
|
||||
|
||||
// Add adds the fund to the available quota
|
||||
func (q *Quota) Add(fund fixedpoint.Value) {
|
||||
q.mu.Lock()
|
||||
q.Available = q.Available.Add(fund)
|
||||
q.mu.Unlock()
|
||||
}
|
||||
|
||||
// Lock locks the fund from the available quota
|
||||
// returns true if the fund is locked successfully
|
||||
// returns false if the fund is not enough
|
||||
func (q *Quota) Lock(fund fixedpoint.Value) bool {
|
||||
if fund.Compare(q.Available) > 0 {
|
||||
return false
|
||||
|
@ -31,12 +35,15 @@ func (q *Quota) Lock(fund fixedpoint.Value) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// Commit commits the locked fund
|
||||
func (q *Quota) Commit() {
|
||||
q.mu.Lock()
|
||||
q.Locked = fixedpoint.Zero
|
||||
q.mu.Unlock()
|
||||
}
|
||||
|
||||
// Rollback rolls back the locked fund
|
||||
// this will move the locked fund to the available quota
|
||||
func (q *Quota) Rollback() {
|
||||
q.mu.Lock()
|
||||
q.Available = q.Available.Add(q.Locked)
|
||||
|
@ -44,12 +51,21 @@ func (q *Quota) Rollback() {
|
|||
q.mu.Unlock()
|
||||
}
|
||||
|
||||
func (q *Quota) String() string {
|
||||
q.mu.Lock()
|
||||
defer q.mu.Unlock()
|
||||
|
||||
return q.Locked.String() + "/" + q.Available.String()
|
||||
}
|
||||
|
||||
// QuotaTransaction is a transactional quota manager
|
||||
type QuotaTransaction struct {
|
||||
mu sync.Mutex
|
||||
BaseAsset Quota
|
||||
QuoteAsset Quota
|
||||
}
|
||||
|
||||
// Commit commits the transaction
|
||||
func (m *QuotaTransaction) Commit() bool {
|
||||
m.mu.Lock()
|
||||
m.BaseAsset.Commit()
|
||||
|
@ -58,6 +74,7 @@ func (m *QuotaTransaction) Commit() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// Rollback rolls back the transaction
|
||||
func (m *QuotaTransaction) Rollback() bool {
|
||||
m.mu.Lock()
|
||||
m.BaseAsset.Rollback()
|
||||
|
|
|
@ -54,11 +54,11 @@ type ExchangeSession struct {
|
|||
PublicOnly bool `json:"publicOnly,omitempty" yaml:"publicOnly"`
|
||||
|
||||
// PrivateChannels is used for filtering the private user data channel, .e.g, orders, trades, balances.. etc
|
||||
// This option is exchange specific
|
||||
// This option is exchange-specific, currently only MAX exchange reads this option
|
||||
PrivateChannels []string `json:"privateChannels,omitempty" yaml:"privateChannels,omitempty"`
|
||||
|
||||
// PrivateChannelSymbols is used for filtering the private user data channel, .e.g, order symbol subscription.
|
||||
// This option is exchange specific
|
||||
// This option is exchange-specific, currently only Bitget exchange reads this option
|
||||
PrivateChannelSymbols []string `json:"privateChannelSymbols,omitempty" yaml:"privateChannelSymbols,omitempty"`
|
||||
|
||||
Margin bool `json:"margin,omitempty" yaml:"margin"`
|
||||
|
@ -405,6 +405,8 @@ func (session *ExchangeSession) initSymbol(ctx context.Context, environ *Environ
|
|||
return fmt.Errorf("market %s is not defined", symbol)
|
||||
}
|
||||
|
||||
session.logger.Infof("environment config: %+v", environ.environmentConfig)
|
||||
|
||||
disableMarketDataStore := environ.environmentConfig != nil && environ.environmentConfig.DisableMarketDataStore
|
||||
disableSessionTradeBuffer := environ.environmentConfig != nil && environ.environmentConfig.DisableSessionTradeBuffer
|
||||
maxSessionTradeBufferSize := 0
|
||||
|
@ -464,7 +466,7 @@ func (session *ExchangeSession) initSymbol(ctx context.Context, environ *Environ
|
|||
for _, sub := range session.Subscriptions {
|
||||
switch sub.Channel {
|
||||
case types.BookChannel:
|
||||
book := types.NewStreamBook(sub.Symbol)
|
||||
book := types.NewStreamBook(sub.Symbol, session.ExchangeName)
|
||||
book.BindStream(session.MarketDataStream)
|
||||
session.orderBooks[sub.Symbol] = book
|
||||
|
||||
|
@ -886,91 +888,106 @@ func (session *ExchangeSession) InitExchange(name string, ex types.Exchange) err
|
|||
return nil
|
||||
}
|
||||
|
||||
func (session *ExchangeSession) MarginType() string {
|
||||
margin := "none"
|
||||
func (session *ExchangeSession) MarginType() types.MarginType {
|
||||
if session.Margin {
|
||||
margin = "margin"
|
||||
if session.IsolatedMargin {
|
||||
margin = "isolated"
|
||||
return types.MarginTypeIsolatedMargin
|
||||
} else {
|
||||
return types.MarginTypeCrossMargin
|
||||
}
|
||||
}
|
||||
return margin
|
||||
|
||||
return types.MarginTypeSpot
|
||||
}
|
||||
|
||||
func (session *ExchangeSession) metricsBalancesUpdater(balances types.BalanceMap) {
|
||||
for currency, balance := range balances {
|
||||
labels := prometheus.Labels{
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin": session.MarginType(),
|
||||
"symbol": session.IsolatedMarginSymbol,
|
||||
"currency": currency,
|
||||
"session": session.Name,
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin_type": string(session.MarginType()),
|
||||
"symbol": session.IsolatedMarginSymbol,
|
||||
"currency": currency,
|
||||
}
|
||||
|
||||
metricsTotalBalances.With(labels).Set(balance.Total().Float64())
|
||||
metricsLockedBalances.With(labels).Set(balance.Locked.Float64())
|
||||
metricsAvailableBalances.With(labels).Set(balance.Available.Float64())
|
||||
metricsLastUpdateTimeBalance.With(prometheus.Labels{
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin": session.MarginType(),
|
||||
"channel": "user",
|
||||
"data_type": "balance",
|
||||
"symbol": "",
|
||||
"currency": currency,
|
||||
metricsBalanceNetMetrics.With(labels).Set(balance.Net().Float64())
|
||||
metricsBalanceAvailableMetrics.With(labels).Set(balance.Available.Float64())
|
||||
metricsBalanceLockedMetrics.With(labels).Set(balance.Locked.Float64())
|
||||
|
||||
// margin metrics
|
||||
metricsBalanceDebtMetrics.With(labels).Set(balance.Debt().Float64())
|
||||
metricsBalanceBorrowedMetrics.With(labels).Set(balance.Borrowed.Float64())
|
||||
metricsBalanceInterestMetrics.With(labels).Set(balance.Interest.Float64())
|
||||
|
||||
metricsLastUpdateTimeMetrics.With(prometheus.Labels{
|
||||
"session": session.Name,
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin_type": string(session.MarginType()),
|
||||
"channel": "user",
|
||||
"data_type": "balance",
|
||||
"symbol": "",
|
||||
"currency": currency,
|
||||
}).SetToCurrentTime()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (session *ExchangeSession) metricsOrderUpdater(order types.Order) {
|
||||
metricsLastUpdateTimeBalance.With(prometheus.Labels{
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin": session.MarginType(),
|
||||
"channel": "user",
|
||||
"data_type": "order",
|
||||
"symbol": order.Symbol,
|
||||
"currency": "",
|
||||
metricsLastUpdateTimeMetrics.With(prometheus.Labels{
|
||||
"session": session.Name,
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin_type": string(session.MarginType()),
|
||||
"channel": "user",
|
||||
"data_type": "order",
|
||||
"symbol": order.Symbol,
|
||||
"currency": "",
|
||||
}).SetToCurrentTime()
|
||||
}
|
||||
|
||||
func (session *ExchangeSession) metricsTradeUpdater(trade types.Trade) {
|
||||
labels := prometheus.Labels{
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin": session.MarginType(),
|
||||
"side": trade.Side.String(),
|
||||
"symbol": trade.Symbol,
|
||||
"liquidity": trade.Liquidity(),
|
||||
"session": session.Name,
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin_type": string(session.MarginType()),
|
||||
"side": trade.Side.String(),
|
||||
"symbol": trade.Symbol,
|
||||
"liquidity": trade.Liquidity(),
|
||||
}
|
||||
metricsTradingVolume.With(labels).Add(trade.Quantity.Mul(trade.Price).Float64())
|
||||
metricsTradesTotal.With(labels).Inc()
|
||||
metricsLastUpdateTimeBalance.With(prometheus.Labels{
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin": session.MarginType(),
|
||||
"channel": "user",
|
||||
"data_type": "trade",
|
||||
"symbol": trade.Symbol,
|
||||
"currency": "",
|
||||
metricsLastUpdateTimeMetrics.With(prometheus.Labels{
|
||||
"session": session.Name,
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin_type": string(session.MarginType()),
|
||||
"channel": "user",
|
||||
"data_type": "trade",
|
||||
"symbol": trade.Symbol,
|
||||
"currency": "",
|
||||
}).SetToCurrentTime()
|
||||
}
|
||||
|
||||
func (session *ExchangeSession) bindMarketDataStreamMetrics(stream types.Stream) {
|
||||
stream.OnBookUpdate(func(book types.SliceOrderBook) {
|
||||
metricsLastUpdateTimeBalance.With(prometheus.Labels{
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin": session.MarginType(),
|
||||
"channel": "market",
|
||||
"data_type": "book",
|
||||
"symbol": book.Symbol,
|
||||
"currency": "",
|
||||
metricsLastUpdateTimeMetrics.With(prometheus.Labels{
|
||||
"session": session.Name,
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin_type": string(session.MarginType()),
|
||||
"channel": "market",
|
||||
"data_type": "book",
|
||||
"symbol": book.Symbol,
|
||||
"currency": "",
|
||||
}).SetToCurrentTime()
|
||||
})
|
||||
stream.OnKLineClosed(func(kline types.KLine) {
|
||||
metricsLastUpdateTimeBalance.With(prometheus.Labels{
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin": session.MarginType(),
|
||||
"channel": "market",
|
||||
"data_type": "kline",
|
||||
"symbol": kline.Symbol,
|
||||
"currency": "",
|
||||
metricsLastUpdateTimeMetrics.With(prometheus.Labels{
|
||||
"session": session.Name,
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin_type": string(session.MarginType()),
|
||||
"channel": "market",
|
||||
"data_type": "kline",
|
||||
"symbol": kline.Symbol,
|
||||
"currency": "",
|
||||
}).SetToCurrentTime()
|
||||
})
|
||||
}
|
||||
|
@ -982,18 +999,20 @@ func (session *ExchangeSession) bindUserDataStreamMetrics(stream types.Stream) {
|
|||
stream.OnOrderUpdate(session.metricsOrderUpdater)
|
||||
stream.OnDisconnect(func() {
|
||||
metricsConnectionStatus.With(prometheus.Labels{
|
||||
"channel": "user",
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin": session.MarginType(),
|
||||
"symbol": session.IsolatedMarginSymbol,
|
||||
"channel": "user",
|
||||
"session": session.Name,
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin_type": string(session.MarginType()),
|
||||
"symbol": session.IsolatedMarginSymbol,
|
||||
}).Set(0.0)
|
||||
})
|
||||
stream.OnConnect(func() {
|
||||
metricsConnectionStatus.With(prometheus.Labels{
|
||||
"channel": "user",
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin": session.MarginType(),
|
||||
"symbol": session.IsolatedMarginSymbol,
|
||||
"channel": "user",
|
||||
"session": session.Name,
|
||||
"exchange": session.ExchangeName.String(),
|
||||
"margin_type": string(session.MarginType()),
|
||||
"symbol": session.IsolatedMarginSymbol,
|
||||
}).Set(1.0)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -16,8 +16,18 @@ import (
|
|||
)
|
||||
|
||||
// Strategy method calls:
|
||||
// -> Initialize() (optional method)
|
||||
// -> Defaults() (optional method)
|
||||
//
|
||||
// setup default static values from constants
|
||||
//
|
||||
// -> Initialize() (optional method)
|
||||
//
|
||||
// initialize dynamic runtime objects
|
||||
//
|
||||
// -> Subscribe()
|
||||
//
|
||||
// register the subscriptions
|
||||
//
|
||||
// -> Validate() (optional method)
|
||||
// -> Run() (optional method)
|
||||
// -> Shutdown(shutdownCtx context.Context, wg *sync.WaitGroup)
|
||||
|
@ -112,6 +122,12 @@ func (trader *Trader) DisableLogging() {
|
|||
}
|
||||
|
||||
func (trader *Trader) Configure(userConfig *Config) error {
|
||||
// config environment
|
||||
if userConfig.Environment != nil && trader.environment != nil {
|
||||
trader.environment.environmentConfig = userConfig.Environment
|
||||
}
|
||||
|
||||
// config risk control
|
||||
if userConfig.RiskControls != nil {
|
||||
trader.SetRiskControls(userConfig.RiskControls)
|
||||
}
|
||||
|
@ -171,12 +187,6 @@ func (trader *Trader) SetRiskControls(riskControls *RiskControls) {
|
|||
func (trader *Trader) RunSingleExchangeStrategy(
|
||||
ctx context.Context, strategy SingleExchangeStrategy, session *ExchangeSession, orderExecutor OrderExecutor,
|
||||
) error {
|
||||
if v, ok := strategy.(StrategyValidator); ok {
|
||||
if err := v.Validate(); err != nil {
|
||||
return fmt.Errorf("failed to validate the config: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if shutdown, ok := strategy.(StrategyShutdown); ok {
|
||||
trader.gracefulShutdown.OnShutdown(shutdown.Shutdown)
|
||||
}
|
||||
|
@ -238,12 +248,6 @@ func (trader *Trader) injectFieldsAndSubscribe(ctx context.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if defaulter, ok := strategy.(StrategyDefaulter); ok {
|
||||
if err := defaulter.Defaults(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
if subscriber, ok := strategy.(ExchangeSessionSubscriber); ok {
|
||||
subscriber.Subscribe(session)
|
||||
} else {
|
||||
|
@ -304,12 +308,6 @@ func (trader *Trader) injectFieldsAndSubscribe(ctx context.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
if initializer, ok := strategy.(StrategyInitializer); ok {
|
||||
if err := initializer.Initialize(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if subscriber, ok := strategy.(CrossExchangeSessionSubscriber); ok {
|
||||
subscriber.CrossSubscribe(trader.environment.sessions)
|
||||
} else {
|
||||
|
@ -356,8 +354,23 @@ func (trader *Trader) Run(ctx context.Context) error {
|
|||
return trader.environment.Connect(ctx)
|
||||
}
|
||||
|
||||
// Initialize initializes the strategies, this method is called before the Run method.
|
||||
// It sets the default values and validates the strategy configurations.
|
||||
// And calls the Initialize method if the strategy implements the Initialize method.
|
||||
func (trader *Trader) Initialize(ctx context.Context) error {
|
||||
return trader.IterateStrategies(func(strategy StrategyID) error {
|
||||
if defaulter, ok := strategy.(StrategyDefaulter); ok {
|
||||
if err := defaulter.Defaults(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if v, ok := strategy.(StrategyValidator); ok {
|
||||
if err := v.Validate(); err != nil {
|
||||
return fmt.Errorf("found invalid strategy config: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if initializer, ok := strategy.(StrategyInitializer); ok {
|
||||
return initializer.Initialize()
|
||||
}
|
||||
|
|
221
pkg/cmd/execute_order.go
Normal file
221
pkg/cmd/execute_order.go
Normal file
|
@ -0,0 +1,221 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/bbgo"
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
_ "github.com/c9s/bbgo/pkg/twap"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
"github.com/c9s/bbgo/pkg/util"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/twap/v2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
executeOrderCmd.Flags().String("session", "", "the exchange session name for sync")
|
||||
executeOrderCmd.Flags().String("symbol", "", "the trading pair, like btcusdt")
|
||||
executeOrderCmd.Flags().String("side", "", "the trading side: buy or sell")
|
||||
executeOrderCmd.Flags().String("target-quantity", "", "target quantity")
|
||||
executeOrderCmd.Flags().String("slice-quantity", "", "slice quantity")
|
||||
executeOrderCmd.Flags().String("stop-price", "0", "stop price")
|
||||
executeOrderCmd.Flags().String("order-update-rate-limit", "1s", "order update rate limit, syntax: 1+1/1m")
|
||||
executeOrderCmd.Flags().Duration("update-interval", time.Second*10, "order update time")
|
||||
executeOrderCmd.Flags().Duration("delay-interval", time.Second*3, "order delay time after filled")
|
||||
executeOrderCmd.Flags().Duration("deadline", 0, "deadline duration of the order execution, e.g. 1h")
|
||||
executeOrderCmd.Flags().Int("price-ticks", 0, "the number of price tick for the jump spread, default to 0")
|
||||
RootCmd.AddCommand(executeOrderCmd)
|
||||
}
|
||||
|
||||
var executeOrderCmd = &cobra.Command{
|
||||
Use: "execute-order --session SESSION --symbol SYMBOL --side SIDE --target-quantity TOTAL_QUANTITY --slice-quantity SLICE_QUANTITY",
|
||||
Short: "execute buy/sell on the balance/position you have on specific symbol",
|
||||
SilenceUsage: true,
|
||||
PreRunE: cobraInitRequired([]string{
|
||||
"symbol",
|
||||
"side",
|
||||
"target-quantity",
|
||||
"slice-quantity",
|
||||
}),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
ctx := context.Background()
|
||||
|
||||
sessionName, err := cmd.Flags().GetString("session")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
symbol, err := cmd.Flags().GetString("symbol")
|
||||
if err != nil {
|
||||
return fmt.Errorf("can not get the symbol from flags: %w", err)
|
||||
}
|
||||
|
||||
if symbol == "" {
|
||||
return fmt.Errorf("symbol not found")
|
||||
}
|
||||
|
||||
sideS, err := cmd.Flags().GetString("side")
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't get side: %w", err)
|
||||
}
|
||||
|
||||
side, err := types.StrToSideType(sideS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
targetQuantityS, err := cmd.Flags().GetString("target-quantity")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(targetQuantityS) == 0 {
|
||||
return errors.New("--target-quantity can not be empty")
|
||||
}
|
||||
|
||||
targetQuantity, err := fixedpoint.NewFromString(targetQuantityS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sliceQuantityS, err := cmd.Flags().GetString("slice-quantity")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(sliceQuantityS) == 0 {
|
||||
return errors.New("--slice-quantity can not be empty")
|
||||
}
|
||||
|
||||
sliceQuantity, err := fixedpoint.NewFromString(sliceQuantityS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
numOfPriceTicks, err := cmd.Flags().GetInt("price-ticks")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stopPriceS, err := cmd.Flags().GetString("stop-price")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stopPrice, err := fixedpoint.NewFromString(stopPriceS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
orderUpdateRateLimitStr, err := cmd.Flags().GetString("order-update-rate-limit")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
updateInterval, err := cmd.Flags().GetDuration("update-interval")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
delayInterval, err := cmd.Flags().GetDuration("delay-interval")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deadlineDuration, err := cmd.Flags().GetDuration("deadline")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var deadlineTime time.Time
|
||||
if deadlineDuration > 0 {
|
||||
deadlineTime = time.Now().Add(deadlineDuration)
|
||||
}
|
||||
|
||||
environ := bbgo.NewEnvironment()
|
||||
if err := environ.ConfigureExchangeSessions(userConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := environ.Init(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
session, ok := environ.Session(sessionName)
|
||||
if !ok {
|
||||
return fmt.Errorf("session %s not found", sessionName)
|
||||
}
|
||||
|
||||
executionCtx, cancelExecution := context.WithCancel(ctx)
|
||||
defer cancelExecution()
|
||||
|
||||
market, ok := session.Market(symbol)
|
||||
if !ok {
|
||||
return fmt.Errorf("market %s not found", symbol)
|
||||
}
|
||||
|
||||
executor := twap.NewFixedQuantityExecutor(session.Exchange, symbol, market, side, targetQuantity, sliceQuantity)
|
||||
|
||||
if updateInterval > 0 {
|
||||
executor.SetUpdateInterval(updateInterval)
|
||||
}
|
||||
|
||||
if len(orderUpdateRateLimitStr) > 0 {
|
||||
rateLimit, err := util.ParseRateLimitSyntax(orderUpdateRateLimitStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
executor.SetOrderUpdateRateLimit(rateLimit)
|
||||
}
|
||||
|
||||
if delayInterval > 0 {
|
||||
executor.SetDelayInterval(delayInterval)
|
||||
}
|
||||
|
||||
if stopPrice.Sign() > 0 {
|
||||
executor.SetStopPrice(stopPrice)
|
||||
}
|
||||
|
||||
// NumOfTicks: numOfPriceTicks,
|
||||
if !deadlineTime.IsZero() {
|
||||
executor.SetDeadlineTime(deadlineTime)
|
||||
}
|
||||
|
||||
if numOfPriceTicks > 0 {
|
||||
executor.SetNumOfTicks(numOfPriceTicks)
|
||||
}
|
||||
|
||||
if err := executor.Start(executionCtx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var sigC = make(chan os.Signal, 1)
|
||||
signal.Notify(sigC, syscall.SIGINT, syscall.SIGTERM)
|
||||
defer signal.Stop(sigC)
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
|
||||
case sig := <-sigC:
|
||||
logrus.Warnf("signal %v", sig)
|
||||
logrus.Infof("shutting down order executor...")
|
||||
shutdownCtx, cancelShutdown := context.WithDeadline(ctx, time.Now().Add(10*time.Second))
|
||||
executor.Shutdown(shutdownCtx)
|
||||
cancelShutdown()
|
||||
|
||||
case <-executor.Done():
|
||||
logrus.Infof("the order execution is completed")
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
|
@ -54,7 +54,7 @@ var orderbookCmd = &cobra.Command{
|
|||
return fmt.Errorf("session %s not found", sessionName)
|
||||
}
|
||||
|
||||
orderBook := types.NewMutexOrderBook(symbol)
|
||||
orderBook := types.NewMutexOrderBook(symbol, session.Exchange.Name())
|
||||
|
||||
s := session.Exchange.NewStream()
|
||||
s.SetPublicOnly()
|
||||
|
|
|
@ -3,19 +3,14 @@ package cmd
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/bbgo"
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
|
@ -145,155 +140,6 @@ var listOrdersCmd = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
var executeOrderCmd = &cobra.Command{
|
||||
Use: "execute-order --session SESSION --symbol SYMBOL --side SIDE --target-quantity TOTAL_QUANTITY --slice-quantity SLICE_QUANTITY",
|
||||
Short: "execute buy/sell on the balance/position you have on specific symbol",
|
||||
SilenceUsage: true,
|
||||
PreRunE: cobraInitRequired([]string{
|
||||
"symbol",
|
||||
"side",
|
||||
"target-quantity",
|
||||
"slice-quantity",
|
||||
}),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
ctx := context.Background()
|
||||
|
||||
sessionName, err := cmd.Flags().GetString("session")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
symbol, err := cmd.Flags().GetString("symbol")
|
||||
if err != nil {
|
||||
return fmt.Errorf("can not get the symbol from flags: %w", err)
|
||||
}
|
||||
|
||||
if symbol == "" {
|
||||
return fmt.Errorf("symbol not found")
|
||||
}
|
||||
|
||||
sideS, err := cmd.Flags().GetString("side")
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't get side: %w", err)
|
||||
}
|
||||
|
||||
side, err := types.StrToSideType(sideS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
targetQuantityS, err := cmd.Flags().GetString("target-quantity")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(targetQuantityS) == 0 {
|
||||
return errors.New("--target-quantity can not be empty")
|
||||
}
|
||||
|
||||
targetQuantity, err := fixedpoint.NewFromString(targetQuantityS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sliceQuantityS, err := cmd.Flags().GetString("slice-quantity")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(sliceQuantityS) == 0 {
|
||||
return errors.New("--slice-quantity can not be empty")
|
||||
}
|
||||
|
||||
sliceQuantity, err := fixedpoint.NewFromString(sliceQuantityS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
numOfPriceTicks, err := cmd.Flags().GetInt("price-ticks")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stopPriceS, err := cmd.Flags().GetString("stop-price")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stopPrice, err := fixedpoint.NewFromString(stopPriceS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
updateInterval, err := cmd.Flags().GetDuration("update-interval")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deadlineDuration, err := cmd.Flags().GetDuration("deadline")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var deadlineTime time.Time
|
||||
if deadlineDuration > 0 {
|
||||
deadlineTime = time.Now().Add(deadlineDuration)
|
||||
}
|
||||
|
||||
environ := bbgo.NewEnvironment()
|
||||
if err := environ.ConfigureExchangeSessions(userConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := environ.Init(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
session, ok := environ.Session(sessionName)
|
||||
if !ok {
|
||||
return fmt.Errorf("session %s not found", sessionName)
|
||||
}
|
||||
|
||||
executionCtx, cancelExecution := context.WithCancel(ctx)
|
||||
defer cancelExecution()
|
||||
|
||||
execution := &bbgo.TwapExecution{
|
||||
Session: session,
|
||||
Symbol: symbol,
|
||||
Side: side,
|
||||
TargetQuantity: targetQuantity,
|
||||
SliceQuantity: sliceQuantity,
|
||||
StopPrice: stopPrice,
|
||||
NumOfTicks: numOfPriceTicks,
|
||||
UpdateInterval: updateInterval,
|
||||
DeadlineTime: deadlineTime,
|
||||
}
|
||||
|
||||
if err := execution.Run(executionCtx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var sigC = make(chan os.Signal, 1)
|
||||
signal.Notify(sigC, syscall.SIGINT, syscall.SIGTERM)
|
||||
defer signal.Stop(sigC)
|
||||
|
||||
select {
|
||||
case sig := <-sigC:
|
||||
log.Warnf("signal %v", sig)
|
||||
log.Infof("shutting down order executor...")
|
||||
shutdownCtx, cancelShutdown := context.WithDeadline(ctx, time.Now().Add(10*time.Second))
|
||||
execution.Shutdown(shutdownCtx)
|
||||
cancelShutdown()
|
||||
|
||||
case <-execution.Done():
|
||||
log.Infof("the order execution is completed")
|
||||
|
||||
case <-ctx.Done():
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// go run ./cmd/bbgo submit-order --session=ftx --symbol=BTCUSDT --side=buy --price=18000 --quantity=0.001
|
||||
var submitOrderCmd = &cobra.Command{
|
||||
Use: "submit-order --session SESSION --symbol SYMBOL --side SIDE --quantity QUANTITY [--price PRICE]",
|
||||
|
@ -413,18 +259,7 @@ func init() {
|
|||
submitOrderCmd.Flags().Bool("market", false, "submit order as a market order")
|
||||
submitOrderCmd.Flags().String("margin-side-effect", "", "margin order side effect")
|
||||
|
||||
executeOrderCmd.Flags().String("session", "", "the exchange session name for sync")
|
||||
executeOrderCmd.Flags().String("symbol", "", "the trading pair, like btcusdt")
|
||||
executeOrderCmd.Flags().String("side", "", "the trading side: buy or sell")
|
||||
executeOrderCmd.Flags().String("target-quantity", "", "target quantity")
|
||||
executeOrderCmd.Flags().String("slice-quantity", "", "slice quantity")
|
||||
executeOrderCmd.Flags().String("stop-price", "0", "stop price")
|
||||
executeOrderCmd.Flags().Duration("update-interval", time.Second*10, "order update time")
|
||||
executeOrderCmd.Flags().Duration("deadline", 0, "deadline of the order execution")
|
||||
executeOrderCmd.Flags().Int("price-ticks", 0, "the number of price tick for the jump spread, default to 0")
|
||||
|
||||
RootCmd.AddCommand(listOrdersCmd)
|
||||
RootCmd.AddCommand(getOrderCmd)
|
||||
RootCmd.AddCommand(submitOrderCmd)
|
||||
RootCmd.AddCommand(executeOrderCmd)
|
||||
}
|
||||
|
|
85
pkg/core/converter.go
Normal file
85
pkg/core/converter.go
Normal file
|
@ -0,0 +1,85 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
type Converter interface {
|
||||
OrderConverter
|
||||
TradeConverter
|
||||
Initialize() error
|
||||
}
|
||||
|
||||
// OrderConverter converts the order to another order
|
||||
type OrderConverter interface {
|
||||
ConvertOrder(order types.Order) (types.Order, error)
|
||||
}
|
||||
|
||||
// TradeConverter converts the trade to another trade
|
||||
type TradeConverter interface {
|
||||
ConvertTrade(trade types.Trade) (types.Trade, error)
|
||||
}
|
||||
|
||||
type OrderConvertFunc func(order types.Order) (types.Order, error)
|
||||
type TradeConvertFunc func(trade types.Trade) (types.Trade, error)
|
||||
|
||||
type DynamicConverter struct {
|
||||
orderConverter OrderConvertFunc
|
||||
tradeConverter TradeConvertFunc
|
||||
}
|
||||
|
||||
func NewDynamicConverter(orderConverter OrderConvertFunc, tradeConverter TradeConvertFunc) *DynamicConverter {
|
||||
return &DynamicConverter{orderConverter: orderConverter, tradeConverter: tradeConverter}
|
||||
}
|
||||
|
||||
func (c *DynamicConverter) Initialize() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *DynamicConverter) ConvertOrder(order types.Order) (types.Order, error) {
|
||||
return c.orderConverter(order)
|
||||
}
|
||||
|
||||
func (c *DynamicConverter) ConvertTrade(trade types.Trade) (types.Trade, error) {
|
||||
return c.tradeConverter(trade)
|
||||
}
|
||||
|
||||
// SymbolConverter converts the symbol to another symbol
|
||||
type SymbolConverter struct {
|
||||
FromSymbol string `json:"from"`
|
||||
ToSymbol string `json:"to"`
|
||||
}
|
||||
|
||||
func NewSymbolConverter(fromSymbol, toSymbol string) *SymbolConverter {
|
||||
return &SymbolConverter{FromSymbol: fromSymbol, ToSymbol: toSymbol}
|
||||
}
|
||||
|
||||
func (c *SymbolConverter) Initialize() error {
|
||||
if c.ToSymbol == "" {
|
||||
return errors.New("toSymbol can not be empty")
|
||||
}
|
||||
|
||||
if c.FromSymbol == "" {
|
||||
return errors.New("fromSymbol can not be empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *SymbolConverter) ConvertOrder(order types.Order) (types.Order, error) {
|
||||
if order.Symbol == c.FromSymbol {
|
||||
order.Symbol = c.ToSymbol
|
||||
}
|
||||
|
||||
return order, nil
|
||||
}
|
||||
|
||||
func (c *SymbolConverter) ConvertTrade(trade types.Trade) (types.Trade, error) {
|
||||
if trade.Symbol == c.FromSymbol {
|
||||
trade.Symbol = c.ToSymbol
|
||||
}
|
||||
|
||||
return trade, nil
|
||||
}
|
31
pkg/core/converter_test.go
Normal file
31
pkg/core/converter_test.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
func TestSymbolConverter(t *testing.T) {
|
||||
converter := NewSymbolConverter("MAXEXCHANGEUSDT", "MAXUSDT")
|
||||
trade, err := converter.ConvertTrade(types.Trade{
|
||||
Symbol: "MAXEXCHANGEUSDT",
|
||||
})
|
||||
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, "MAXUSDT", trade.Symbol)
|
||||
}
|
||||
|
||||
order, err := converter.ConvertOrder(types.Order{
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Symbol: "MAXEXCHANGEUSDT",
|
||||
},
|
||||
})
|
||||
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, "MAXUSDT", order.Symbol)
|
||||
}
|
||||
|
||||
}
|
|
@ -12,6 +12,94 @@ import (
|
|||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
type ConverterSetting struct {
|
||||
SymbolConverter *SymbolConverter `json:"symbolConverter" yaml:"symbolConverter"`
|
||||
}
|
||||
|
||||
func (s *ConverterSetting) getConverter() Converter {
|
||||
if s.SymbolConverter != nil {
|
||||
return s.SymbolConverter
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ConverterSetting) InitializeConverter() (Converter, error) {
|
||||
converter := s.getConverter()
|
||||
if converter == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
logrus.Infof("initializing converter %T ...", converter)
|
||||
err := converter.Initialize()
|
||||
return converter, err
|
||||
}
|
||||
|
||||
// ConverterManager manages the converters for trade conversion
|
||||
// It can be used to convert the trade symbol into the target symbol, or convert the price, volume into different units.
|
||||
type ConverterManager struct {
|
||||
ConverterSettings []ConverterSetting `json:"converters,omitempty" yaml:"converters,omitempty"`
|
||||
|
||||
converters []Converter
|
||||
}
|
||||
|
||||
func (c *ConverterManager) Initialize() error {
|
||||
for _, setting := range c.ConverterSettings {
|
||||
converter, err := setting.InitializeConverter()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if converter != nil {
|
||||
c.AddConverter(converter)
|
||||
}
|
||||
}
|
||||
|
||||
numConverters := len(c.converters)
|
||||
logrus.Infof("%d converters loaded", numConverters)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ConverterManager) AddConverter(converter Converter) {
|
||||
c.converters = append(c.converters, converter)
|
||||
}
|
||||
|
||||
func (c *ConverterManager) ConvertOrder(order types.Order) types.Order {
|
||||
if len(c.converters) == 0 {
|
||||
return order
|
||||
}
|
||||
|
||||
for _, converter := range c.converters {
|
||||
convOrder, err := converter.ConvertOrder(order)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Errorf("converter %+v error, order: %s", converter, order.String())
|
||||
continue
|
||||
}
|
||||
|
||||
order = convOrder
|
||||
}
|
||||
|
||||
return order
|
||||
}
|
||||
|
||||
func (c *ConverterManager) ConvertTrade(trade types.Trade) types.Trade {
|
||||
if len(c.converters) == 0 {
|
||||
return trade
|
||||
}
|
||||
|
||||
for _, converter := range c.converters {
|
||||
convTrade, err := converter.ConvertTrade(trade)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Errorf("converter %+v error, trade: %s", converter, trade.String())
|
||||
continue
|
||||
}
|
||||
|
||||
trade = convTrade
|
||||
}
|
||||
|
||||
return trade
|
||||
}
|
||||
|
||||
//go:generate callbackgen -type TradeCollector
|
||||
type TradeCollector struct {
|
||||
Symbol string
|
||||
|
@ -31,6 +119,8 @@ type TradeCollector struct {
|
|||
|
||||
positionUpdateCallbacks []func(position *types.Position)
|
||||
profitCallbacks []func(trade types.Trade, profit *types.Profit)
|
||||
|
||||
ConverterManager
|
||||
}
|
||||
|
||||
func NewTradeCollector(symbol string, position *types.Position, orderStore *OrderStore) *TradeCollector {
|
||||
|
@ -80,7 +170,7 @@ func (c *TradeCollector) BindStreamForBackground(stream types.Stream) {
|
|||
|
||||
func (c *TradeCollector) BindStream(stream types.Stream) {
|
||||
stream.OnTradeUpdate(func(trade types.Trade) {
|
||||
c.processTrade(trade)
|
||||
c.ProcessTrade(trade)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -116,6 +206,8 @@ func (c *TradeCollector) Recover(
|
|||
}
|
||||
|
||||
func (c *TradeCollector) RecoverTrade(td types.Trade) bool {
|
||||
td = c.ConvertTrade(td)
|
||||
|
||||
logrus.Debugf("checking trade: %s", td.String())
|
||||
if c.processTrade(td) {
|
||||
logrus.Infof("recovered trade: %s", td.String())
|
||||
|
@ -230,7 +322,7 @@ func (c *TradeCollector) processTrade(trade types.Trade) bool {
|
|||
// return true when the given trade is added
|
||||
// return false when the given trade is not added
|
||||
func (c *TradeCollector) ProcessTrade(trade types.Trade) bool {
|
||||
return c.processTrade(trade)
|
||||
return c.processTrade(c.ConvertTrade(trade))
|
||||
}
|
||||
|
||||
// Run is a goroutine executed in the background
|
||||
|
@ -249,7 +341,8 @@ func (c *TradeCollector) Run(ctx context.Context) {
|
|||
c.Process()
|
||||
|
||||
case trade := <-c.tradeC:
|
||||
c.processTrade(trade)
|
||||
c.processTrade(c.ConvertTrade(trade))
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,28 @@ import (
|
|||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
func TestTradeCollector_NilConvertManager(t *testing.T) {
|
||||
symbol := "BTCUSDT"
|
||||
position := types.NewPosition(symbol, "BTC", "USDT")
|
||||
orderStore := NewOrderStore(symbol)
|
||||
collector := NewTradeCollector(symbol, position, orderStore)
|
||||
|
||||
trade := types.Trade{
|
||||
ID: 1,
|
||||
OrderID: 399,
|
||||
Exchange: types.ExchangeBinance,
|
||||
Price: fixedpoint.NewFromInt(40000),
|
||||
Quantity: fixedpoint.One,
|
||||
QuoteQuantity: fixedpoint.NewFromInt(40000),
|
||||
Symbol: "BTCUSDT",
|
||||
Side: types.SideTypeBuy,
|
||||
IsBuyer: true,
|
||||
}
|
||||
|
||||
trade = collector.ConvertTrade(trade)
|
||||
assert.Equal(t, "BTCUSDT", trade.Symbol)
|
||||
}
|
||||
|
||||
func TestTradeCollector_ShouldNotCountDuplicatedTrade(t *testing.T) {
|
||||
symbol := "BTCUSDT"
|
||||
position := types.NewPosition(symbol, "BTC", "USDT")
|
||||
|
|
|
@ -17,20 +17,23 @@ type TradeBatchQuery struct {
|
|||
types.ExchangeTradeHistoryService
|
||||
}
|
||||
|
||||
func (e TradeBatchQuery) Query(ctx context.Context, symbol string, options *types.TradeQueryOptions, opts ...Option) (c chan types.Trade, errC chan error) {
|
||||
func (e TradeBatchQuery) Query(
|
||||
ctx context.Context, symbol string, options *types.TradeQueryOptions, opts ...Option,
|
||||
) (c chan types.Trade, errC chan error) {
|
||||
if options.EndTime == nil {
|
||||
now := time.Now()
|
||||
options.EndTime = &now
|
||||
}
|
||||
|
||||
startTime := *options.StartTime
|
||||
endTime := *options.EndTime
|
||||
query := &AsyncTimeRangedBatchQuery{
|
||||
Type: types.Trade{},
|
||||
Q: func(startTime, endTime time.Time) (interface{}, error) {
|
||||
options.StartTime = &startTime
|
||||
options.EndTime = &endTime
|
||||
return e.ExchangeTradeHistoryService.QueryTrades(ctx, symbol, options)
|
||||
return e.ExchangeTradeHistoryService.QueryTrades(ctx, symbol, &types.TradeQueryOptions{
|
||||
StartTime: &startTime,
|
||||
EndTime: &endTime,
|
||||
Limit: options.Limit,
|
||||
LastTradeID: options.LastTradeID,
|
||||
})
|
||||
},
|
||||
T: func(obj interface{}) time.Time {
|
||||
return time.Time(obj.(types.Trade).Time)
|
||||
|
@ -40,9 +43,10 @@ func (e TradeBatchQuery) Query(ctx context.Context, symbol string, options *type
|
|||
if trade.ID > options.LastTradeID {
|
||||
options.LastTradeID = trade.ID
|
||||
}
|
||||
|
||||
return trade.Key().String()
|
||||
},
|
||||
JumpIfEmpty: 24 * time.Hour,
|
||||
JumpIfEmpty: 24*time.Hour - 5*time.Minute, // exchange may not have trades in the last 24 hours
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
|
@ -50,6 +54,6 @@ func (e TradeBatchQuery) Query(ctx context.Context, symbol string, options *type
|
|||
}
|
||||
|
||||
c = make(chan types.Trade, 100)
|
||||
errC = query.Query(ctx, c, startTime, endTime)
|
||||
errC = query.Query(ctx, c, *options.StartTime, *options.EndTime)
|
||||
return c, errC
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package batch
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -14,6 +15,49 @@ import (
|
|||
"github.com/c9s/bbgo/pkg/types/mocks"
|
||||
)
|
||||
|
||||
func matchTradeQueryOptions(expected *types.TradeQueryOptions) *TradeQueryOptionsMatcher {
|
||||
return &TradeQueryOptionsMatcher{
|
||||
expected: expected,
|
||||
}
|
||||
}
|
||||
|
||||
type TradeQueryOptionsMatcher struct {
|
||||
expected *types.TradeQueryOptions
|
||||
}
|
||||
|
||||
func (m TradeQueryOptionsMatcher) Matches(arg interface{}) bool {
|
||||
given, ok := arg.(*types.TradeQueryOptions)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if given.StartTime != nil && m.expected.StartTime != nil {
|
||||
if !given.StartTime.Equal(*m.expected.StartTime) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if given.EndTime != nil && m.expected.EndTime != nil {
|
||||
if !given.EndTime.Equal(*m.expected.EndTime) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if given.Limit != m.expected.Limit {
|
||||
return false
|
||||
}
|
||||
|
||||
if given.LastTradeID != m.expected.LastTradeID {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (m TradeQueryOptionsMatcher) String() string {
|
||||
return fmt.Sprintf("%+v", m.expected)
|
||||
}
|
||||
|
||||
func Test_TradeBatchQuery(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
@ -55,7 +99,7 @@ func Test_TradeBatchQuery(t *testing.T) {
|
|||
mockExchange = mocks.NewMockExchangeTradeHistoryService(ctrl)
|
||||
)
|
||||
|
||||
mockExchange.EXPECT().QueryTrades(ctx, expSymbol, expOptions).DoAndReturn(
|
||||
mockExchange.EXPECT().QueryTrades(ctx, expSymbol, matchTradeQueryOptions(expOptions)).DoAndReturn(
|
||||
func(ctx context.Context, symbol string, options *types.TradeQueryOptions) ([]types.Trade, error) {
|
||||
assert.Equal(t, startTime, *options.StartTime)
|
||||
assert.Equal(t, endTime, *options.EndTime)
|
||||
|
@ -63,7 +107,13 @@ func Test_TradeBatchQuery(t *testing.T) {
|
|||
assert.Equal(t, expOptions.Limit, options.Limit)
|
||||
return queryTrades1, nil
|
||||
}).Times(1)
|
||||
mockExchange.EXPECT().QueryTrades(ctx, expSymbol, expOptions).DoAndReturn(
|
||||
|
||||
mockExchange.EXPECT().QueryTrades(ctx, expSymbol, matchTradeQueryOptions(&types.TradeQueryOptions{
|
||||
StartTime: timePtr(queryTrades1[0].Time.Time()),
|
||||
EndTime: expOptions.EndTime,
|
||||
LastTradeID: 1,
|
||||
Limit: 50,
|
||||
})).DoAndReturn(
|
||||
func(ctx context.Context, symbol string, options *types.TradeQueryOptions) ([]types.Trade, error) {
|
||||
assert.Equal(t, queryTrades1[0].Time.Time(), *options.StartTime)
|
||||
assert.Equal(t, endTime, *options.EndTime)
|
||||
|
@ -71,7 +121,13 @@ func Test_TradeBatchQuery(t *testing.T) {
|
|||
assert.Equal(t, expOptions.Limit, options.Limit)
|
||||
return queryTrades2, nil
|
||||
}).Times(1)
|
||||
mockExchange.EXPECT().QueryTrades(ctx, expSymbol, expOptions).DoAndReturn(
|
||||
|
||||
mockExchange.EXPECT().QueryTrades(ctx, expSymbol, matchTradeQueryOptions(&types.TradeQueryOptions{
|
||||
StartTime: timePtr(queryTrades2[1].Time.Time()),
|
||||
EndTime: expOptions.EndTime,
|
||||
LastTradeID: queryTrades2[1].ID,
|
||||
Limit: 50,
|
||||
})).DoAndReturn(
|
||||
func(ctx context.Context, symbol string, options *types.TradeQueryOptions) ([]types.Trade, error) {
|
||||
assert.Equal(t, queryTrades2[1].Time.Time(), *options.StartTime)
|
||||
assert.Equal(t, endTime, *options.EndTime)
|
||||
|
@ -138,3 +194,7 @@ func Test_TradeBatchQuery(t *testing.T) {
|
|||
assert.Equal(t, rcvCount, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func timePtr(t time.Time) *time.Time {
|
||||
return &t
|
||||
}
|
||||
|
|
|
@ -8,8 +8,9 @@ import (
|
|||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
)
|
||||
|
||||
//go:generate stringer -type=TransferType
|
||||
// 1 for internal transfer, 0 for external transfer
|
||||
//
|
||||
//go:generate stringer -type=TransferType
|
||||
type TransferType int
|
||||
|
||||
const (
|
||||
|
@ -33,7 +34,7 @@ type WithdrawRecord struct {
|
|||
TxID string `json:"txId"`
|
||||
}
|
||||
|
||||
//go:generate stringer -type=WithdrawStatus
|
||||
//go:generate stringer -type=WithdrawStatus -trimprefix=WithdrawStatus
|
||||
type WithdrawStatus int
|
||||
|
||||
// WithdrawStatus: 0(0:Email Sent,1:Cancelled 2:Awaiting Approval 3:Rejected 4:Processing 5:Failure 6:Completed)
|
||||
|
|
|
@ -212,6 +212,12 @@ func (g *GetWithdrawHistoryRequest) GetSlugsMap() (map[string]string, error) {
|
|||
return slugs, nil
|
||||
}
|
||||
|
||||
// GetPath returns the request path of the API
|
||||
func (g *GetWithdrawHistoryRequest) GetPath() string {
|
||||
return "/sapi/v1/capital/withdraw/history"
|
||||
}
|
||||
|
||||
// Do generates the request object and send the request object to the API endpoint
|
||||
func (g *GetWithdrawHistoryRequest) Do(ctx context.Context) ([]WithdrawRecord, error) {
|
||||
|
||||
// empty params for GET operation
|
||||
|
@ -221,7 +227,9 @@ func (g *GetWithdrawHistoryRequest) Do(ctx context.Context) ([]WithdrawRecord, e
|
|||
return nil, err
|
||||
}
|
||||
|
||||
apiURL := "/sapi/v1/capital/withdraw/history"
|
||||
var apiURL string
|
||||
|
||||
apiURL = g.GetPath()
|
||||
|
||||
req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params)
|
||||
if err != nil {
|
||||
|
@ -234,8 +242,32 @@ func (g *GetWithdrawHistoryRequest) Do(ctx context.Context) ([]WithdrawRecord, e
|
|||
}
|
||||
|
||||
var apiResponse []WithdrawRecord
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
|
||||
type responseUnmarshaler interface {
|
||||
Unmarshal(data []byte) error
|
||||
}
|
||||
|
||||
if unmarshaler, ok := interface{}(&apiResponse).(responseUnmarshaler); ok {
|
||||
if err := unmarshaler.Unmarshal(response.Body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// The line below checks the content type, however, some API server might not send the correct content type header,
|
||||
// Hence, this is commented for backward compatibility
|
||||
// response.IsJSON()
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
type responseValidator interface {
|
||||
Validate() error
|
||||
}
|
||||
|
||||
if validator, ok := interface{}(&apiResponse).(responseValidator); ok {
|
||||
if err := validator.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return apiResponse, nil
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Code generated by "stringer -type=WithdrawStatus"; DO NOT EDIT.
|
||||
// Code generated by "stringer -type=WithdrawStatus -trimprefix=WithdrawStatus"; DO NOT EDIT.
|
||||
|
||||
package binanceapi
|
||||
|
||||
|
@ -17,9 +17,9 @@ func _() {
|
|||
_ = x[WithdrawStatusCompleted-6]
|
||||
}
|
||||
|
||||
const _WithdrawStatus_name = "WithdrawStatusEmailSentWithdrawStatusCancelledWithdrawStatusAwaitingApprovalWithdrawStatusRejectedWithdrawStatusProcessingWithdrawStatusFailureWithdrawStatusCompleted"
|
||||
const _WithdrawStatus_name = "EmailSentCancelledAwaitingApprovalRejectedProcessingFailureCompleted"
|
||||
|
||||
var _WithdrawStatus_index = [...]uint8{0, 23, 46, 76, 98, 122, 143, 166}
|
||||
var _WithdrawStatus_index = [...]uint8{0, 9, 18, 34, 42, 52, 59, 68}
|
||||
|
||||
func (i WithdrawStatus) String() string {
|
||||
if i < 0 || i >= WithdrawStatus(len(_WithdrawStatus_index)-1) {
|
||||
|
|
|
@ -9,10 +9,32 @@ import (
|
|||
"github.com/adshao/go-binance/v2/futures"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/exchange/binance/binanceapi"
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
func toGlobalWithdrawStatus(status binanceapi.WithdrawStatus) (types.WithdrawStatus, error) {
|
||||
switch status {
|
||||
case binanceapi.WithdrawStatusEmailSent:
|
||||
return types.WithdrawStatusSent, nil
|
||||
case binanceapi.WithdrawStatusCancelled:
|
||||
return types.WithdrawStatusCancelled, nil
|
||||
case binanceapi.WithdrawStatusAwaitingApproval:
|
||||
return types.WithdrawStatusAwaitingApproval, nil
|
||||
case binanceapi.WithdrawStatusRejected:
|
||||
return types.WithdrawStatusRejected, nil
|
||||
case binanceapi.WithdrawStatusProcessing:
|
||||
return types.WithdrawStatusProcessing, nil
|
||||
case binanceapi.WithdrawStatusFailure:
|
||||
return types.WithdrawStatusFailed, nil
|
||||
case binanceapi.WithdrawStatusCompleted:
|
||||
return types.WithdrawStatusCompleted, nil
|
||||
default:
|
||||
return types.WithdrawStatusUnknown, fmt.Errorf("unable to convert the withdraw status: %s", status)
|
||||
}
|
||||
}
|
||||
|
||||
func toGlobalMarket(symbol binance.Symbol) types.Market {
|
||||
market := types.Market{
|
||||
Exchange: types.ExchangeBinance,
|
||||
|
|
|
@ -2,9 +2,10 @@ package binance
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/c9s/bbgo/pkg/exchange/binance/binanceapi"
|
||||
"time"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/exchange/binance/binanceapi"
|
||||
|
||||
"github.com/adshao/go-binance/v2/futures"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
|
@ -42,11 +43,10 @@ func toGlobalFuturesPositions(futuresPositions []*binanceapi.FuturesAccountPosit
|
|||
retFuturesPositions := make(types.FuturesPositionMap)
|
||||
for _, futuresPosition := range futuresPositions {
|
||||
retFuturesPositions[futuresPosition.Symbol] = types.FuturesPosition{ // TODO: types.FuturesPosition
|
||||
Isolated: futuresPosition.Isolated,
|
||||
AverageCost: fixedpoint.MustNewFromString(futuresPosition.EntryPrice),
|
||||
ApproximateAverageCost: fixedpoint.MustNewFromString(futuresPosition.EntryPrice),
|
||||
Base: fixedpoint.MustNewFromString(futuresPosition.PositionAmt),
|
||||
Quote: fixedpoint.MustNewFromString(futuresPosition.Notional),
|
||||
Isolated: futuresPosition.Isolated,
|
||||
AverageCost: fixedpoint.MustNewFromString(futuresPosition.EntryPrice),
|
||||
Base: fixedpoint.MustNewFromString(futuresPosition.PositionAmt),
|
||||
Quote: fixedpoint.MustNewFromString(futuresPosition.Notional),
|
||||
|
||||
PositionRisk: &types.PositionRisk{
|
||||
Leverage: fixedpoint.MustNewFromString(futuresPosition.Leverage),
|
||||
|
|
|
@ -571,6 +571,11 @@ func (e *Exchange) QueryWithdrawHistory(ctx context.Context, asset string, since
|
|||
return nil, err
|
||||
}
|
||||
|
||||
status, err := toGlobalWithdrawStatus(d.Status)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
withdraws = append(withdraws, types.Withdraw{
|
||||
Exchange: types.ExchangeBinance,
|
||||
ApplyTime: types.Time(applyTime),
|
||||
|
@ -581,7 +586,8 @@ func (e *Exchange) QueryWithdrawHistory(ctx context.Context, asset string, since
|
|||
TransactionFee: d.TransactionFee,
|
||||
WithdrawOrderID: d.WithdrawOrderID,
|
||||
Network: d.Network,
|
||||
Status: d.Status.String(),
|
||||
Status: status,
|
||||
OriginalStatus: fmt.Sprintf("%s (%d)", d.Status.String(), int(d.Status)),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -790,13 +796,24 @@ func (e *Exchange) QueryOrder(ctx context.Context, q types.OrderQuery) (*types.O
|
|||
return nil, err
|
||||
}
|
||||
|
||||
var order *binance.Order
|
||||
if e.IsMargin {
|
||||
order, err = e.client.NewGetMarginOrderService().Symbol(q.Symbol).OrderID(orderID).Do(ctx)
|
||||
} else {
|
||||
order, err = e.client.NewGetOrderService().Symbol(q.Symbol).OrderID(orderID).Do(ctx)
|
||||
order, err := e.client.NewGetMarginOrderService().Symbol(q.Symbol).OrderID(orderID).Do(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toGlobalOrder(order, e.IsMargin)
|
||||
}
|
||||
|
||||
if e.IsFutures {
|
||||
order, err := e.futuresClient.NewGetOrderService().Symbol(q.Symbol).OrderID(orderID).Do(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return toGlobalFuturesOrder(order, false)
|
||||
}
|
||||
|
||||
order, err := e.client.NewGetOrderService().Symbol(q.Symbol).OrderID(orderID).Do(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -988,7 +1005,6 @@ func (e *Exchange) submitMarginOrder(ctx context.Context, order types.SubmitOrde
|
|||
}
|
||||
}
|
||||
|
||||
// could be IOC or FOK
|
||||
if len(order.TimeInForce) > 0 {
|
||||
// TODO: check the TimeInForce value
|
||||
req.TimeInForce(binance.TimeInForceType(order.TimeInForce))
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
package bitgetapi
|
||||
|
||||
//go:generate -command GetRequest requestgen -method GET -responseType .APIResponse -responseDataField Data
|
||||
//go:generate -command PostRequest requestgen -method POST -responseType .APIResponse -responseDataField Data
|
||||
|
||||
import (
|
||||
"github.com/c9s/requestgen"
|
||||
)
|
||||
|
||||
type CancelOrderBySymbolResponse string
|
||||
|
||||
//go:generate GetRequest -url "/api/spot/v1/trade/cancel-symbol-order" -type CancelOrderBySymbolRequest -responseDataType .CancelOrderBySymbolResponse
|
||||
type CancelOrderBySymbolRequest struct {
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
symbol string `param:"symbol"`
|
||||
}
|
||||
|
||||
func (c *RestClient) NewCancelOrderBySymbolRequest() *CancelOrderBySymbolRequest {
|
||||
return &CancelOrderBySymbolRequest{client: c}
|
||||
}
|
|
@ -1,152 +0,0 @@
|
|||
// Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Data -url /api/spot/v1/trade/cancel-symbol-order -type CancelOrderBySymbolRequest -responseDataType .CancelOrderBySymbolResponse"; DO NOT EDIT.
|
||||
|
||||
package bitgetapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (c *CancelOrderBySymbolRequest) Symbol(symbol string) *CancelOrderBySymbolRequest {
|
||||
c.symbol = symbol
|
||||
return c
|
||||
}
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (c *CancelOrderBySymbolRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
query := url.Values{}
|
||||
for _k, _v := range params {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParameters builds and checks the parameters and return the result in a map object
|
||||
func (c *CancelOrderBySymbolRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
// check symbol field -> json key symbol
|
||||
symbol := c.symbol
|
||||
|
||||
// assign parameter of symbol
|
||||
params["symbol"] = symbol
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (c *CancelOrderBySymbolRequest) GetParametersQuery() (url.Values, error) {
|
||||
query := url.Values{}
|
||||
|
||||
params, err := c.GetParameters()
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
if c.isVarSlice(_v) {
|
||||
c.iterateSlice(_v, func(it interface{}) {
|
||||
query.Add(_k+"[]", fmt.Sprintf("%v", it))
|
||||
})
|
||||
} else {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
||||
func (c *CancelOrderBySymbolRequest) GetParametersJSON() ([]byte, error) {
|
||||
params, err := c.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(params)
|
||||
}
|
||||
|
||||
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
||||
func (c *CancelOrderBySymbolRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (c *CancelOrderBySymbolRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
||||
for _k, _v := range slugs {
|
||||
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
||||
url = needleRE.ReplaceAllString(url, _v)
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
func (c *CancelOrderBySymbolRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
||||
sliceValue := reflect.ValueOf(slice)
|
||||
for _i := 0; _i < sliceValue.Len(); _i++ {
|
||||
it := sliceValue.Index(_i).Interface()
|
||||
_f(it)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CancelOrderBySymbolRequest) isVarSlice(_v interface{}) bool {
|
||||
rt := reflect.TypeOf(_v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *CancelOrderBySymbolRequest) GetSlugsMap() (map[string]string, error) {
|
||||
slugs := map[string]string{}
|
||||
params, err := c.GetSlugParameters()
|
||||
if err != nil {
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
slugs[_k] = fmt.Sprintf("%v", _v)
|
||||
}
|
||||
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
func (c *CancelOrderBySymbolRequest) Do(ctx context.Context) (*CancelOrderBySymbolResponse, error) {
|
||||
|
||||
// empty params for GET operation
|
||||
var params interface{}
|
||||
query, err := c.GetParametersQuery()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
apiURL := "/api/spot/v1/trade/cancel-symbol-order"
|
||||
|
||||
req, err := c.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := c.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiResponse APIResponse
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data CancelOrderBySymbolResponse
|
||||
if err := json.Unmarshal(apiResponse.Data, &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &data, nil
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package bitgetapi
|
||||
|
||||
//go:generate -command GetRequest requestgen -method GET -responseType .APIResponse -responseDataField Data
|
||||
//go:generate -command PostRequest requestgen -method POST -responseType .APIResponse -responseDataField Data
|
||||
|
||||
import (
|
||||
"github.com/c9s/requestgen"
|
||||
)
|
||||
|
||||
type CancelOrderResponse struct {
|
||||
OrderId string `json:"orderId"`
|
||||
ClientOrderId string `json:"clientOrderId"`
|
||||
}
|
||||
|
||||
//go:generate PostRequest -url "/api/spot/v1/trade/cancel-order-v2" -type CancelOrderRequest -responseDataType .CancelOrderResponse
|
||||
type CancelOrderRequest struct {
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
symbol string `param:"symbol"`
|
||||
orderId *string `param:"orderId"`
|
||||
clientOrderId *string `param:"clientOid"`
|
||||
}
|
||||
|
||||
func (c *RestClient) NewCancelOrderRequest() *CancelOrderRequest {
|
||||
return &CancelOrderRequest{client: c}
|
||||
}
|
|
@ -1,177 +0,0 @@
|
|||
// Code generated by "requestgen -method POST -responseType .APIResponse -responseDataField Data -url /api/spot/v1/trade/cancel-order-v2 -type CancelOrderRequest -responseDataType .CancelOrderResponse"; DO NOT EDIT.
|
||||
|
||||
package bitgetapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (c *CancelOrderRequest) Symbol(symbol string) *CancelOrderRequest {
|
||||
c.symbol = symbol
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CancelOrderRequest) OrderId(orderId string) *CancelOrderRequest {
|
||||
c.orderId = &orderId
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CancelOrderRequest) ClientOrderId(clientOrderId string) *CancelOrderRequest {
|
||||
c.clientOrderId = &clientOrderId
|
||||
return c
|
||||
}
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (c *CancelOrderRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
query := url.Values{}
|
||||
for _k, _v := range params {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParameters builds and checks the parameters and return the result in a map object
|
||||
func (c *CancelOrderRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
// check symbol field -> json key symbol
|
||||
symbol := c.symbol
|
||||
|
||||
// assign parameter of symbol
|
||||
params["symbol"] = symbol
|
||||
// check orderId field -> json key orderId
|
||||
if c.orderId != nil {
|
||||
orderId := *c.orderId
|
||||
|
||||
// assign parameter of orderId
|
||||
params["orderId"] = orderId
|
||||
} else {
|
||||
}
|
||||
// check clientOrderId field -> json key clientOid
|
||||
if c.clientOrderId != nil {
|
||||
clientOrderId := *c.clientOrderId
|
||||
|
||||
// assign parameter of clientOrderId
|
||||
params["clientOid"] = clientOrderId
|
||||
} else {
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (c *CancelOrderRequest) GetParametersQuery() (url.Values, error) {
|
||||
query := url.Values{}
|
||||
|
||||
params, err := c.GetParameters()
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
if c.isVarSlice(_v) {
|
||||
c.iterateSlice(_v, func(it interface{}) {
|
||||
query.Add(_k+"[]", fmt.Sprintf("%v", it))
|
||||
})
|
||||
} else {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
||||
func (c *CancelOrderRequest) GetParametersJSON() ([]byte, error) {
|
||||
params, err := c.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(params)
|
||||
}
|
||||
|
||||
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
||||
func (c *CancelOrderRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (c *CancelOrderRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
||||
for _k, _v := range slugs {
|
||||
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
||||
url = needleRE.ReplaceAllString(url, _v)
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
func (c *CancelOrderRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
||||
sliceValue := reflect.ValueOf(slice)
|
||||
for _i := 0; _i < sliceValue.Len(); _i++ {
|
||||
it := sliceValue.Index(_i).Interface()
|
||||
_f(it)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CancelOrderRequest) isVarSlice(_v interface{}) bool {
|
||||
rt := reflect.TypeOf(_v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *CancelOrderRequest) GetSlugsMap() (map[string]string, error) {
|
||||
slugs := map[string]string{}
|
||||
params, err := c.GetSlugParameters()
|
||||
if err != nil {
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
slugs[_k] = fmt.Sprintf("%v", _v)
|
||||
}
|
||||
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
func (c *CancelOrderRequest) Do(ctx context.Context) (*CancelOrderResponse, error) {
|
||||
|
||||
params, err := c.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query := url.Values{}
|
||||
|
||||
apiURL := "/api/spot/v1/trade/cancel-order-v2"
|
||||
|
||||
req, err := c.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := c.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiResponse APIResponse
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data CancelOrderResponse
|
||||
if err := json.Unmarshal(apiResponse.Data, &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &data, nil
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
package bitgetapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/testutil"
|
||||
)
|
||||
|
||||
func getTestClientOrSkip(t *testing.T) *RestClient {
|
||||
if b, _ := strconv.ParseBool(os.Getenv("CI")); b {
|
||||
t.Skip("skip test for CI")
|
||||
}
|
||||
|
||||
key, secret, ok := testutil.IntegrationTestConfigured(t, "BITGET")
|
||||
if !ok {
|
||||
t.Skip("BITGET_* env vars are not configured")
|
||||
return nil
|
||||
}
|
||||
|
||||
client := NewClient()
|
||||
client.Auth(key, secret, os.Getenv("BITGET_API_PASSPHRASE"))
|
||||
return client
|
||||
}
|
||||
|
||||
func TestClient(t *testing.T) {
|
||||
client := getTestClientOrSkip(t)
|
||||
ctx := context.Background()
|
||||
|
||||
t.Run("GetAllTickersRequest", func(t *testing.T) {
|
||||
req := client.NewGetAllTickersRequest()
|
||||
tickers, err := req.Do(ctx)
|
||||
assert.NoError(t, err)
|
||||
t.Logf("tickers: %+v", tickers)
|
||||
})
|
||||
|
||||
t.Run("GetSymbolsRequest", func(t *testing.T) {
|
||||
req := client.NewGetSymbolsRequest()
|
||||
symbols, err := req.Do(ctx)
|
||||
assert.NoError(t, err)
|
||||
t.Logf("symbols: %+v", symbols)
|
||||
})
|
||||
|
||||
t.Run("GetTickerRequest", func(t *testing.T) {
|
||||
req := client.NewGetTickerRequest()
|
||||
req.Symbol("BTCUSDT_SPBL")
|
||||
ticker, err := req.Do(ctx)
|
||||
assert.NoError(t, err)
|
||||
t.Logf("ticker: %+v", ticker)
|
||||
})
|
||||
|
||||
t.Run("GetDepthRequest", func(t *testing.T) {
|
||||
req := client.NewGetDepthRequest()
|
||||
req.Symbol("BTCUSDT_SPBL")
|
||||
depth, err := req.Do(ctx)
|
||||
assert.NoError(t, err)
|
||||
t.Logf("depth: %+v", depth)
|
||||
})
|
||||
|
||||
t.Run("GetServerTimeRequest", func(t *testing.T) {
|
||||
req := client.NewGetServerTimeRequest()
|
||||
serverTime, err := req.Do(ctx)
|
||||
assert.NoError(t, err)
|
||||
t.Logf("time: %+v", serverTime)
|
||||
})
|
||||
|
||||
t.Run("GetAccountAssetsRequest", func(t *testing.T) {
|
||||
req := client.NewGetAccountAssetsRequest()
|
||||
assets, err := req.Do(ctx)
|
||||
assert.NoError(t, err)
|
||||
t.Logf("assets: %+v", assets)
|
||||
})
|
||||
|
||||
t.Run("GetAccountTransfersRequest", func(t *testing.T) {
|
||||
req := client.NewGetAccountTransfersRequest()
|
||||
req.CoinId(1)
|
||||
req.FromType(AccountExchange)
|
||||
transfers, err := req.Do(ctx)
|
||||
|
||||
assert.NoError(t, err)
|
||||
t.Logf("transfers: %+v", transfers)
|
||||
})
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package bitgetapi
|
||||
|
||||
//go:generate -command GetRequest requestgen -method GET -responseType .APIResponse -responseDataField Data
|
||||
//go:generate -command PostRequest requestgen -method POST -responseType .APIResponse -responseDataField Data
|
||||
|
||||
import (
|
||||
"github.com/c9s/requestgen"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
type AccountAsset struct {
|
||||
CoinId int64 `json:"coinId"`
|
||||
CoinName string `json:"coinName"`
|
||||
Available fixedpoint.Value `json:"available"`
|
||||
Frozen fixedpoint.Value `json:"frozen"`
|
||||
Lock fixedpoint.Value `json:"lock"`
|
||||
UTime types.MillisecondTimestamp `json:"uTime"`
|
||||
}
|
||||
|
||||
//go:generate GetRequest -url "/api/spot/v1/account/assets" -type GetAccountAssetsRequest -responseDataType []AccountAsset
|
||||
type GetAccountAssetsRequest struct {
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
}
|
||||
|
||||
func (c *RestClient) NewGetAccountAssetsRequest() *GetAccountAssetsRequest {
|
||||
return &GetAccountAssetsRequest{client: c}
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
// Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Data -url /api/spot/v1/account/assets -type GetAccountAssetsRequest -responseDataType []AccountAsset"; DO NOT EDIT.
|
||||
|
||||
package bitgetapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (g *GetAccountAssetsRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
query := url.Values{}
|
||||
for _k, _v := range params {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParameters builds and checks the parameters and return the result in a map object
|
||||
func (g *GetAccountAssetsRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (g *GetAccountAssetsRequest) GetParametersQuery() (url.Values, error) {
|
||||
query := url.Values{}
|
||||
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
if g.isVarSlice(_v) {
|
||||
g.iterateSlice(_v, func(it interface{}) {
|
||||
query.Add(_k+"[]", fmt.Sprintf("%v", it))
|
||||
})
|
||||
} else {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
||||
func (g *GetAccountAssetsRequest) GetParametersJSON() ([]byte, error) {
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(params)
|
||||
}
|
||||
|
||||
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
||||
func (g *GetAccountAssetsRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (g *GetAccountAssetsRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
||||
for _k, _v := range slugs {
|
||||
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
||||
url = needleRE.ReplaceAllString(url, _v)
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
func (g *GetAccountAssetsRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
||||
sliceValue := reflect.ValueOf(slice)
|
||||
for _i := 0; _i < sliceValue.Len(); _i++ {
|
||||
it := sliceValue.Index(_i).Interface()
|
||||
_f(it)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GetAccountAssetsRequest) isVarSlice(_v interface{}) bool {
|
||||
rt := reflect.TypeOf(_v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *GetAccountAssetsRequest) GetSlugsMap() (map[string]string, error) {
|
||||
slugs := map[string]string{}
|
||||
params, err := g.GetSlugParameters()
|
||||
if err != nil {
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
slugs[_k] = fmt.Sprintf("%v", _v)
|
||||
}
|
||||
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
func (g *GetAccountAssetsRequest) Do(ctx context.Context) ([]AccountAsset, error) {
|
||||
|
||||
// no body params
|
||||
var params interface{}
|
||||
query := url.Values{}
|
||||
|
||||
apiURL := "/api/spot/v1/account/assets"
|
||||
|
||||
req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := g.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiResponse APIResponse
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data []AccountAsset
|
||||
if err := json.Unmarshal(apiResponse.Data, &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package bitgetapi
|
||||
|
||||
//go:generate -command GetRequest requestgen -method GET -responseType .APIResponse -responseDataField Data
|
||||
//go:generate -command PostRequest requestgen -method POST -responseType .APIResponse -responseDataField Data
|
||||
|
||||
import (
|
||||
"github.com/c9s/requestgen"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
type Account struct {
|
||||
UserId types.StrInt64 `json:"user_id"`
|
||||
InviterId types.StrInt64 `json:"inviter_id"`
|
||||
Ips string `json:"ips"`
|
||||
Authorities []string `json:"authorities"`
|
||||
ParentId types.StrInt64 `json:"parentId"`
|
||||
Trader bool `json:"trader"`
|
||||
}
|
||||
|
||||
//go:generate GetRequest -url "/api/spot/v1/account/getInfo" -type GetAccountRequest -responseDataType .Account
|
||||
type GetAccountRequest struct {
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
}
|
||||
|
||||
func (c *RestClient) NewGetAccountRequest() *GetAccountRequest {
|
||||
return &GetAccountRequest{client: c}
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
// Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Data -url /api/spot/v1/account/getInfo -type GetAccountRequest -responseDataType .Account"; DO NOT EDIT.
|
||||
|
||||
package bitgetapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (g *GetAccountRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
query := url.Values{}
|
||||
for _k, _v := range params {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParameters builds and checks the parameters and return the result in a map object
|
||||
func (g *GetAccountRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (g *GetAccountRequest) GetParametersQuery() (url.Values, error) {
|
||||
query := url.Values{}
|
||||
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
if g.isVarSlice(_v) {
|
||||
g.iterateSlice(_v, func(it interface{}) {
|
||||
query.Add(_k+"[]", fmt.Sprintf("%v", it))
|
||||
})
|
||||
} else {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
||||
func (g *GetAccountRequest) GetParametersJSON() ([]byte, error) {
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(params)
|
||||
}
|
||||
|
||||
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
||||
func (g *GetAccountRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (g *GetAccountRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
||||
for _k, _v := range slugs {
|
||||
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
||||
url = needleRE.ReplaceAllString(url, _v)
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
func (g *GetAccountRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
||||
sliceValue := reflect.ValueOf(slice)
|
||||
for _i := 0; _i < sliceValue.Len(); _i++ {
|
||||
it := sliceValue.Index(_i).Interface()
|
||||
_f(it)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GetAccountRequest) isVarSlice(_v interface{}) bool {
|
||||
rt := reflect.TypeOf(_v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *GetAccountRequest) GetSlugsMap() (map[string]string, error) {
|
||||
slugs := map[string]string{}
|
||||
params, err := g.GetSlugParameters()
|
||||
if err != nil {
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
slugs[_k] = fmt.Sprintf("%v", _v)
|
||||
}
|
||||
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
func (g *GetAccountRequest) Do(ctx context.Context) (*Account, error) {
|
||||
|
||||
// no body params
|
||||
var params interface{}
|
||||
query := url.Values{}
|
||||
|
||||
apiURL := "/api/spot/v1/account/getInfo"
|
||||
|
||||
req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := g.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiResponse APIResponse
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data Account
|
||||
if err := json.Unmarshal(apiResponse.Data, &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &data, nil
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
package bitgetapi
|
||||
|
||||
//go:generate -command GetRequest requestgen -method GET -responseType .APIResponse -responseDataField Data
|
||||
//go:generate -command PostRequest requestgen -method POST -responseType .APIResponse -responseDataField Data
|
||||
|
||||
import (
|
||||
"github.com/c9s/requestgen"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
type AccountType string
|
||||
|
||||
const (
|
||||
AccountExchange AccountType = "EXCHANGE"
|
||||
AccountContract AccountType = "CONTRACT"
|
||||
)
|
||||
|
||||
type Transfer struct {
|
||||
CTime types.MillisecondTimestamp `json:"cTime"`
|
||||
CoinId string `json:"coinId"`
|
||||
CoinName string `json:"coinName"`
|
||||
GroupType string `json:"groupType"`
|
||||
BizType string `json:"bizType"`
|
||||
Quantity fixedpoint.Value `json:"quantity"`
|
||||
Balance fixedpoint.Value `json:"balance"`
|
||||
Fees fixedpoint.Value `json:"fees"`
|
||||
BillId string `json:"billId"`
|
||||
}
|
||||
|
||||
//go:generate GetRequest -url "/api/spot/v1/account/transferRecords" -type GetAccountTransfersRequest -responseDataType []Transfer
|
||||
type GetAccountTransfersRequest struct {
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
|
||||
coinId int `param:"coinId"`
|
||||
fromType AccountType `param:"fromType"`
|
||||
after string `param:"after"`
|
||||
before string `param:"before"`
|
||||
}
|
||||
|
||||
func (c *RestClient) NewGetAccountTransfersRequest() *GetAccountTransfersRequest {
|
||||
return &GetAccountTransfersRequest{client: c}
|
||||
}
|
|
@ -1,193 +0,0 @@
|
|||
// Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Data -url /api/spot/v1/account/transferRecords -type GetAccountTransfersRequest -responseDataType []Transfer"; DO NOT EDIT.
|
||||
|
||||
package bitgetapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (g *GetAccountTransfersRequest) CoinId(coinId int) *GetAccountTransfersRequest {
|
||||
g.coinId = coinId
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetAccountTransfersRequest) FromType(fromType AccountType) *GetAccountTransfersRequest {
|
||||
g.fromType = fromType
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetAccountTransfersRequest) After(after string) *GetAccountTransfersRequest {
|
||||
g.after = after
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetAccountTransfersRequest) Before(before string) *GetAccountTransfersRequest {
|
||||
g.before = before
|
||||
return g
|
||||
}
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (g *GetAccountTransfersRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
query := url.Values{}
|
||||
for _k, _v := range params {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParameters builds and checks the parameters and return the result in a map object
|
||||
func (g *GetAccountTransfersRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
// check coinId field -> json key coinId
|
||||
coinId := g.coinId
|
||||
|
||||
// assign parameter of coinId
|
||||
params["coinId"] = coinId
|
||||
// check fromType field -> json key fromType
|
||||
fromType := g.fromType
|
||||
|
||||
// TEMPLATE check-valid-values
|
||||
switch fromType {
|
||||
case AccountExchange, AccountContract:
|
||||
params["fromType"] = fromType
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("fromType value %v is invalid", fromType)
|
||||
|
||||
}
|
||||
// END TEMPLATE check-valid-values
|
||||
|
||||
// assign parameter of fromType
|
||||
params["fromType"] = fromType
|
||||
// check after field -> json key after
|
||||
after := g.after
|
||||
|
||||
// assign parameter of after
|
||||
params["after"] = after
|
||||
// check before field -> json key before
|
||||
before := g.before
|
||||
|
||||
// assign parameter of before
|
||||
params["before"] = before
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (g *GetAccountTransfersRequest) GetParametersQuery() (url.Values, error) {
|
||||
query := url.Values{}
|
||||
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
if g.isVarSlice(_v) {
|
||||
g.iterateSlice(_v, func(it interface{}) {
|
||||
query.Add(_k+"[]", fmt.Sprintf("%v", it))
|
||||
})
|
||||
} else {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
||||
func (g *GetAccountTransfersRequest) GetParametersJSON() ([]byte, error) {
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(params)
|
||||
}
|
||||
|
||||
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
||||
func (g *GetAccountTransfersRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (g *GetAccountTransfersRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
||||
for _k, _v := range slugs {
|
||||
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
||||
url = needleRE.ReplaceAllString(url, _v)
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
func (g *GetAccountTransfersRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
||||
sliceValue := reflect.ValueOf(slice)
|
||||
for _i := 0; _i < sliceValue.Len(); _i++ {
|
||||
it := sliceValue.Index(_i).Interface()
|
||||
_f(it)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GetAccountTransfersRequest) isVarSlice(_v interface{}) bool {
|
||||
rt := reflect.TypeOf(_v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *GetAccountTransfersRequest) GetSlugsMap() (map[string]string, error) {
|
||||
slugs := map[string]string{}
|
||||
params, err := g.GetSlugParameters()
|
||||
if err != nil {
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
slugs[_k] = fmt.Sprintf("%v", _v)
|
||||
}
|
||||
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
func (g *GetAccountTransfersRequest) Do(ctx context.Context) ([]Transfer, error) {
|
||||
|
||||
// empty params for GET operation
|
||||
var params interface{}
|
||||
query, err := g.GetParametersQuery()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
apiURL := "/api/spot/v1/account/transferRecords"
|
||||
|
||||
req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := g.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiResponse APIResponse
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data []Transfer
|
||||
if err := json.Unmarshal(apiResponse.Data, &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package bitgetapi
|
||||
|
||||
//go:generate -command GetRequest requestgen -method GET -responseType .APIResponse -responseDataField Data
|
||||
//go:generate -command PostRequest requestgen -method POST -responseType .APIResponse -responseDataField Data
|
||||
|
||||
import (
|
||||
"github.com/c9s/requestgen"
|
||||
)
|
||||
|
||||
//go:generate GetRequest -url "/api/spot/v1/market/tickers" -type GetAllTickersRequest -responseDataType []Ticker
|
||||
type GetAllTickersRequest struct {
|
||||
client requestgen.APIClient
|
||||
}
|
||||
|
||||
func (c *RestClient) NewGetAllTickersRequest() *GetAllTickersRequest {
|
||||
return &GetAllTickersRequest{client: c}
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
// Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Data -url /api/spot/v1/market/tickers -type GetAllTickersRequest -responseDataType []Ticker"; DO NOT EDIT.
|
||||
|
||||
package bitgetapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (g *GetAllTickersRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
query := url.Values{}
|
||||
for _k, _v := range params {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParameters builds and checks the parameters and return the result in a map object
|
||||
func (g *GetAllTickersRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (g *GetAllTickersRequest) GetParametersQuery() (url.Values, error) {
|
||||
query := url.Values{}
|
||||
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
if g.isVarSlice(_v) {
|
||||
g.iterateSlice(_v, func(it interface{}) {
|
||||
query.Add(_k+"[]", fmt.Sprintf("%v", it))
|
||||
})
|
||||
} else {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
||||
func (g *GetAllTickersRequest) GetParametersJSON() ([]byte, error) {
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(params)
|
||||
}
|
||||
|
||||
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
||||
func (g *GetAllTickersRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (g *GetAllTickersRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
||||
for _k, _v := range slugs {
|
||||
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
||||
url = needleRE.ReplaceAllString(url, _v)
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
func (g *GetAllTickersRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
||||
sliceValue := reflect.ValueOf(slice)
|
||||
for _i := 0; _i < sliceValue.Len(); _i++ {
|
||||
it := sliceValue.Index(_i).Interface()
|
||||
_f(it)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GetAllTickersRequest) isVarSlice(_v interface{}) bool {
|
||||
rt := reflect.TypeOf(_v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *GetAllTickersRequest) GetSlugsMap() (map[string]string, error) {
|
||||
slugs := map[string]string{}
|
||||
params, err := g.GetSlugParameters()
|
||||
if err != nil {
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
slugs[_k] = fmt.Sprintf("%v", _v)
|
||||
}
|
||||
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
func (g *GetAllTickersRequest) Do(ctx context.Context) ([]Ticker, error) {
|
||||
|
||||
// no body params
|
||||
var params interface{}
|
||||
query := url.Values{}
|
||||
|
||||
apiURL := "/api/spot/v1/market/tickers"
|
||||
|
||||
req, err := g.client.NewRequest(ctx, "GET", apiURL, query, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := g.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiResponse APIResponse
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data []Ticker
|
||||
if err := json.Unmarshal(apiResponse.Data, &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package bitgetapi
|
||||
|
||||
//go:generate -command GetRequest requestgen -method GET -responseType .APIResponse -responseDataField Data
|
||||
//go:generate -command PostRequest requestgen -method POST -responseType .APIResponse -responseDataField Data
|
||||
|
||||
import (
|
||||
"github.com/c9s/requestgen"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
type Candle struct {
|
||||
Open fixedpoint.Value `json:"open"`
|
||||
High fixedpoint.Value `json:"high"`
|
||||
Low fixedpoint.Value `json:"low"`
|
||||
Close fixedpoint.Value `json:"close"`
|
||||
QuoteVol fixedpoint.Value `json:"quoteVol"`
|
||||
BaseVol fixedpoint.Value `json:"baseVol"`
|
||||
UsdtVol fixedpoint.Value `json:"usdtVol"`
|
||||
Ts types.MillisecondTimestamp `json:"ts"`
|
||||
}
|
||||
|
||||
//go:generate GetRequest -url "/api/spot/v1/market/candles" -type GetCandlesRequest -responseDataType []Candle
|
||||
type GetCandlesRequest struct {
|
||||
client requestgen.APIClient
|
||||
}
|
||||
|
||||
func (c *RestClient) NewGetCandlesRequest() *GetCandlesRequest {
|
||||
return &GetCandlesRequest{client: c}
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
// Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Data -url /api/spot/v1/market/candles -type GetCandlesRequest -responseDataType []Candle"; DO NOT EDIT.
|
||||
|
||||
package bitgetapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (g *GetCandlesRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
query := url.Values{}
|
||||
for _k, _v := range params {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParameters builds and checks the parameters and return the result in a map object
|
||||
func (g *GetCandlesRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (g *GetCandlesRequest) GetParametersQuery() (url.Values, error) {
|
||||
query := url.Values{}
|
||||
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
if g.isVarSlice(_v) {
|
||||
g.iterateSlice(_v, func(it interface{}) {
|
||||
query.Add(_k+"[]", fmt.Sprintf("%v", it))
|
||||
})
|
||||
} else {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
||||
func (g *GetCandlesRequest) GetParametersJSON() ([]byte, error) {
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(params)
|
||||
}
|
||||
|
||||
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
||||
func (g *GetCandlesRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (g *GetCandlesRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
||||
for _k, _v := range slugs {
|
||||
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
||||
url = needleRE.ReplaceAllString(url, _v)
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
func (g *GetCandlesRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
||||
sliceValue := reflect.ValueOf(slice)
|
||||
for _i := 0; _i < sliceValue.Len(); _i++ {
|
||||
it := sliceValue.Index(_i).Interface()
|
||||
_f(it)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GetCandlesRequest) isVarSlice(_v interface{}) bool {
|
||||
rt := reflect.TypeOf(_v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *GetCandlesRequest) GetSlugsMap() (map[string]string, error) {
|
||||
slugs := map[string]string{}
|
||||
params, err := g.GetSlugParameters()
|
||||
if err != nil {
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
slugs[_k] = fmt.Sprintf("%v", _v)
|
||||
}
|
||||
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
func (g *GetCandlesRequest) Do(ctx context.Context) ([]Candle, error) {
|
||||
|
||||
// no body params
|
||||
var params interface{}
|
||||
query := url.Values{}
|
||||
|
||||
apiURL := "/api/spot/v1/market/candles"
|
||||
|
||||
req, err := g.client.NewRequest(ctx, "GET", apiURL, query, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := g.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiResponse APIResponse
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data []Candle
|
||||
if err := json.Unmarshal(apiResponse.Data, &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package bitgetapi
|
||||
|
||||
//go:generate -command GetRequest requestgen -method GET -responseType .APIResponse -responseDataField Data
|
||||
//go:generate -command PostRequest requestgen -method POST -responseType .APIResponse -responseDataField Data
|
||||
|
||||
import (
|
||||
"github.com/c9s/requestgen"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
type Depth struct {
|
||||
Asks [][]fixedpoint.Value `json:"asks"`
|
||||
Bids [][]fixedpoint.Value `json:"bids"`
|
||||
Timestamp types.MillisecondTimestamp `json:"timestamp"`
|
||||
}
|
||||
|
||||
//go:generate GetRequest -url "/api/spot/v1/market/depth" -type GetDepthRequest -responseDataType .Depth
|
||||
type GetDepthRequest struct {
|
||||
client requestgen.APIClient
|
||||
|
||||
symbol string `param:"symbol"`
|
||||
stepType string `param:"type" default:"step0"`
|
||||
limit *int `param:"limit"`
|
||||
}
|
||||
|
||||
func (c *RestClient) NewGetDepthRequest() *GetDepthRequest {
|
||||
return &GetDepthRequest{client: c}
|
||||
}
|
|
@ -1,175 +0,0 @@
|
|||
// Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Data -url /api/spot/v1/market/depth -type GetDepthRequest -responseDataType .Depth"; DO NOT EDIT.
|
||||
|
||||
package bitgetapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (g *GetDepthRequest) Symbol(symbol string) *GetDepthRequest {
|
||||
g.symbol = symbol
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetDepthRequest) StepType(stepType string) *GetDepthRequest {
|
||||
g.stepType = stepType
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetDepthRequest) Limit(limit int) *GetDepthRequest {
|
||||
g.limit = &limit
|
||||
return g
|
||||
}
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (g *GetDepthRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
query := url.Values{}
|
||||
for _k, _v := range params {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParameters builds and checks the parameters and return the result in a map object
|
||||
func (g *GetDepthRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
// check symbol field -> json key symbol
|
||||
symbol := g.symbol
|
||||
|
||||
// assign parameter of symbol
|
||||
params["symbol"] = symbol
|
||||
// check stepType field -> json key type
|
||||
stepType := g.stepType
|
||||
|
||||
// assign parameter of stepType
|
||||
params["type"] = stepType
|
||||
// check limit field -> json key limit
|
||||
if g.limit != nil {
|
||||
limit := *g.limit
|
||||
|
||||
// assign parameter of limit
|
||||
params["limit"] = limit
|
||||
} else {
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (g *GetDepthRequest) GetParametersQuery() (url.Values, error) {
|
||||
query := url.Values{}
|
||||
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
if g.isVarSlice(_v) {
|
||||
g.iterateSlice(_v, func(it interface{}) {
|
||||
query.Add(_k+"[]", fmt.Sprintf("%v", it))
|
||||
})
|
||||
} else {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
||||
func (g *GetDepthRequest) GetParametersJSON() ([]byte, error) {
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(params)
|
||||
}
|
||||
|
||||
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
||||
func (g *GetDepthRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (g *GetDepthRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
||||
for _k, _v := range slugs {
|
||||
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
||||
url = needleRE.ReplaceAllString(url, _v)
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
func (g *GetDepthRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
||||
sliceValue := reflect.ValueOf(slice)
|
||||
for _i := 0; _i < sliceValue.Len(); _i++ {
|
||||
it := sliceValue.Index(_i).Interface()
|
||||
_f(it)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GetDepthRequest) isVarSlice(_v interface{}) bool {
|
||||
rt := reflect.TypeOf(_v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *GetDepthRequest) GetSlugsMap() (map[string]string, error) {
|
||||
slugs := map[string]string{}
|
||||
params, err := g.GetSlugParameters()
|
||||
if err != nil {
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
slugs[_k] = fmt.Sprintf("%v", _v)
|
||||
}
|
||||
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
func (g *GetDepthRequest) Do(ctx context.Context) (*Depth, error) {
|
||||
|
||||
// empty params for GET operation
|
||||
var params interface{}
|
||||
query, err := g.GetParametersQuery()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
apiURL := "/api/spot/v1/market/depth"
|
||||
|
||||
req, err := g.client.NewRequest(ctx, "GET", apiURL, query, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := g.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiResponse APIResponse
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data Depth
|
||||
if err := json.Unmarshal(apiResponse.Data, &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &data, nil
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
package bitgetapi
|
||||
|
||||
//go:generate -command GetRequest requestgen -method GET -responseType .APIResponse -responseDataField Data
|
||||
//go:generate -command PostRequest requestgen -method POST -responseType .APIResponse -responseDataField Data
|
||||
|
||||
import (
|
||||
"github.com/c9s/requestgen"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
type Fill struct {
|
||||
AccountId types.StrInt64 `json:"accountId"`
|
||||
Symbol string `json:"symbol"`
|
||||
OrderId types.StrInt64 `json:"orderId"`
|
||||
FillId types.StrInt64 `json:"fillId"`
|
||||
OrderType OrderType `json:"orderType"`
|
||||
Side OrderSide `json:"side"`
|
||||
FillPrice fixedpoint.Value `json:"fillPrice"`
|
||||
FillQuantity fixedpoint.Value `json:"fillQuantity"`
|
||||
FillTotalAmount fixedpoint.Value `json:"fillTotalAmount"`
|
||||
CreationTime types.MillisecondTimestamp `json:"cTime"`
|
||||
FeeCurrency string `json:"feeCcy"`
|
||||
Fees fixedpoint.Value `json:"fees"`
|
||||
}
|
||||
|
||||
//go:generate GetRequest -url "/api/spot/v1/trade/fills" -type GetFillsRequest -responseDataType .ServerTime
|
||||
type GetFillsRequest struct {
|
||||
client requestgen.AuthenticatedAPIClient
|
||||
|
||||
// after - order id
|
||||
after *string `param:"after"`
|
||||
|
||||
// before - order id
|
||||
before *string `param:"before"`
|
||||
|
||||
limit *string `param:"limit"`
|
||||
}
|
||||
|
||||
func (c *RestClient) NewGetFillsRequest() *GetFillsRequest {
|
||||
return &GetFillsRequest{client: c}
|
||||
}
|
|
@ -1,182 +0,0 @@
|
|||
// Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Data -url /api/spot/v1/trade/fills -type GetFillsRequest -responseDataType .ServerTime"; DO NOT EDIT.
|
||||
|
||||
package bitgetapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (g *GetFillsRequest) After(after string) *GetFillsRequest {
|
||||
g.after = &after
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetFillsRequest) Before(before string) *GetFillsRequest {
|
||||
g.before = &before
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetFillsRequest) Limit(limit string) *GetFillsRequest {
|
||||
g.limit = &limit
|
||||
return g
|
||||
}
|
||||
|
||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||
func (g *GetFillsRequest) GetQueryParameters() (url.Values, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
query := url.Values{}
|
||||
for _k, _v := range params {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParameters builds and checks the parameters and return the result in a map object
|
||||
func (g *GetFillsRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
// check after field -> json key after
|
||||
if g.after != nil {
|
||||
after := *g.after
|
||||
|
||||
// assign parameter of after
|
||||
params["after"] = after
|
||||
} else {
|
||||
}
|
||||
// check before field -> json key before
|
||||
if g.before != nil {
|
||||
before := *g.before
|
||||
|
||||
// assign parameter of before
|
||||
params["before"] = before
|
||||
} else {
|
||||
}
|
||||
// check limit field -> json key limit
|
||||
if g.limit != nil {
|
||||
limit := *g.limit
|
||||
|
||||
// assign parameter of limit
|
||||
params["limit"] = limit
|
||||
} else {
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||
func (g *GetFillsRequest) GetParametersQuery() (url.Values, error) {
|
||||
query := url.Values{}
|
||||
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
if g.isVarSlice(_v) {
|
||||
g.iterateSlice(_v, func(it interface{}) {
|
||||
query.Add(_k+"[]", fmt.Sprintf("%v", it))
|
||||
})
|
||||
} else {
|
||||
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||
}
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
||||
func (g *GetFillsRequest) GetParametersJSON() ([]byte, error) {
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(params)
|
||||
}
|
||||
|
||||
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
||||
func (g *GetFillsRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (g *GetFillsRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
||||
for _k, _v := range slugs {
|
||||
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
||||
url = needleRE.ReplaceAllString(url, _v)
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
func (g *GetFillsRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
||||
sliceValue := reflect.ValueOf(slice)
|
||||
for _i := 0; _i < sliceValue.Len(); _i++ {
|
||||
it := sliceValue.Index(_i).Interface()
|
||||
_f(it)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GetFillsRequest) isVarSlice(_v interface{}) bool {
|
||||
rt := reflect.TypeOf(_v)
|
||||
switch rt.Kind() {
|
||||
case reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *GetFillsRequest) GetSlugsMap() (map[string]string, error) {
|
||||
slugs := map[string]string{}
|
||||
params, err := g.GetSlugParameters()
|
||||
if err != nil {
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
for _k, _v := range params {
|
||||
slugs[_k] = fmt.Sprintf("%v", _v)
|
||||
}
|
||||
|
||||
return slugs, nil
|
||||
}
|
||||
|
||||
func (g *GetFillsRequest) Do(ctx context.Context) (*types.MillisecondTimestamp, error) {
|
||||
|
||||
// empty params for GET operation
|
||||
var params interface{}
|
||||
query, err := g.GetParametersQuery()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
apiURL := "/api/spot/v1/trade/fills"
|
||||
|
||||
req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := g.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiResponse APIResponse
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data types.MillisecondTimestamp
|
||||
if err := json.Unmarshal(apiResponse.Data, &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &data, nil
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user