mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +00:00
Compare commits
227 Commits
822abfa3da
...
ac31fd0da2
Author | SHA1 | Date | |
---|---|---|---|
|
ac31fd0da2 | ||
|
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 | ||
|
714275fedb | ||
|
b27fc896f9 | ||
|
cf42d9d0b0 | ||
|
8773c220f5 | ||
|
b4bb7b6716 | ||
|
57a68f8063 | ||
|
c35805916a |
4
.github/workflows/docker.yml
vendored
4
.github/workflows/docker.yml
vendored
|
@ -20,7 +20,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v3
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
# list of Docker images to use as base name for tags
|
# list of Docker images to use as base name for tags
|
||||||
images: |
|
images: |
|
||||||
|
@ -38,7 +38,7 @@ jobs:
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v3
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: Login to DockerHub
|
- name: Login to DockerHub
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
|
|
10
.github/workflows/go.yml
vendored
10
.github/workflows/go.yml
vendored
|
@ -2,8 +2,10 @@ name: Go
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ main ]
|
branches:
|
||||||
|
- "main"
|
||||||
pull_request:
|
pull_request:
|
||||||
|
types: [synchronize, opened, reopened]
|
||||||
branches:
|
branches:
|
||||||
- "main"
|
- "main"
|
||||||
- "v*"
|
- "v*"
|
||||||
|
@ -27,7 +29,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
# lfs: 'true'
|
# lfs: 'true'
|
||||||
ssh-key: ${{ secrets.git_ssh_key }}
|
ssh-key: ${{ secrets.git_ssh_key }}
|
||||||
|
@ -88,13 +90,13 @@ jobs:
|
||||||
sed -i -e '/_requestgen.go/d' coverage_dnum.txt
|
sed -i -e '/_requestgen.go/d' coverage_dnum.txt
|
||||||
|
|
||||||
- name: Revive Check
|
- name: Revive Check
|
||||||
uses: morphy2k/revive-action@v2.5.9 # https://github.com/mgechev/revive/issues/956
|
uses: morphy2k/revive-action@v2.5.10 # https://github.com/mgechev/revive/issues/956
|
||||||
with:
|
with:
|
||||||
reporter: github-pr-review
|
reporter: github-pr-review
|
||||||
fail_on_error: true
|
fail_on_error: true
|
||||||
|
|
||||||
- name: Upload Coverage Report
|
- name: Upload Coverage Report
|
||||||
uses: codecov/codecov-action@v3
|
uses: codecov/codecov-action@v4
|
||||||
with:
|
with:
|
||||||
files: ./coverage.txt,./coverage_dnum.txt
|
files: ./coverage.txt,./coverage_dnum.txt
|
||||||
|
|
||||||
|
|
4
.github/workflows/node.yml
vendored
4
.github/workflows/node.yml
vendored
|
@ -21,9 +21,9 @@ jobs:
|
||||||
node-version: [ 16.x ]
|
node-version: [ 16.x ]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
- run: npm install -g yarn
|
- 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 .
|
|
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
|
@ -16,13 +16,13 @@ jobs:
|
||||||
id: get_version
|
id: get_version
|
||||||
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
|
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: "1.21"
|
go-version: "1.21"
|
||||||
- name: Install Node
|
- name: Install Node
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: "16"
|
node-version: "16"
|
||||||
- name: Build
|
- 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
|
# 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.
|
# to the chart and its templates, including the app version.
|
||||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
# 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
|
# 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
|
# 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.
|
# 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
|
mountPath: /config
|
||||||
|
|
||||||
# the "env" entries will override the environment variables from envFrom.
|
# 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:
|
envFrom:
|
||||||
- secretRef:
|
- secretRef:
|
||||||
name: {{ .Values.dotenv.secret | default .Release.Name }}
|
name: {{ .Values.dotenv.secret | default .Release.Name }}
|
||||||
|
|
|
@ -75,11 +75,11 @@ webserver:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
metrics:
|
metrics:
|
||||||
enabled: false
|
enabled: true
|
||||||
port: 9090
|
port: 9090
|
||||||
|
|
||||||
logFormatter:
|
logFormatter:
|
||||||
enabled: false
|
enabled: true
|
||||||
format: json
|
format: json
|
||||||
|
|
||||||
grpc:
|
grpc:
|
||||||
|
@ -89,6 +89,18 @@ grpc:
|
||||||
debug:
|
debug:
|
||||||
enabled: false
|
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:
|
resources:
|
||||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
# 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
|
# choice for the user. This also increases chances charts run on environments with little
|
||||||
|
|
|
@ -21,7 +21,7 @@ logging:
|
||||||
trade: true
|
trade: true
|
||||||
order: true
|
order: true
|
||||||
fields:
|
fields:
|
||||||
env: staging
|
env: local
|
||||||
|
|
||||||
sessions:
|
sessions:
|
||||||
max:
|
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
|
# 0.1 pip is 0.01, here we use 10, so we will get 18000.00, 18001.00 and
|
||||||
# 18002.00
|
# 18002.00
|
||||||
pips: 10
|
pips: 10
|
||||||
persistence:
|
## profitFixer is used for fixing the profit stats and the position
|
||||||
type: redis
|
# 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 userdatastream](bbgo_userdatastream.md) - Listen to session events (orderUpdate, tradeUpdate, balanceUpdate, balanceSnapshot)
|
||||||
* [bbgo version](bbgo_version.md) - show version name
|
* [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
|
* [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
|
* [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
|
* [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
|
* [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
|
* [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
|
* [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
|
### Options
|
||||||
|
|
||||||
```
|
```
|
||||||
--deadline duration deadline of the order execution
|
--deadline duration deadline duration of the order execution, e.g. 1h
|
||||||
-h, --help help for execute-order
|
--delay-interval duration order delay time after filled (default 3s)
|
||||||
--price-ticks int the number of price tick for the jump spread, default to 0
|
-h, --help help for execute-order
|
||||||
--session string the exchange session name for sync
|
--order-update-rate-limit string order update rate limit, syntax: 1+1/1m (default "1s")
|
||||||
--side string the trading side: buy or sell
|
--price-ticks int the number of price tick for the jump spread, default to 0
|
||||||
--slice-quantity string slice quantity
|
--session string the exchange session name for sync
|
||||||
--stop-price string stop price (default "0")
|
--side string the trading side: buy or sell
|
||||||
--symbol string the trading pair, like btcusdt
|
--slice-quantity string slice quantity
|
||||||
--target-quantity string target quantity
|
--stop-price string stop price (default "0")
|
||||||
--update-interval duration order update time (default 10s)
|
--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
|
### 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
|
* [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
|
* [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
|
* [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
|
* [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
|
* [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 loans](bbgo_margin_loans.md) - query loans history
|
||||||
* [bbgo margin repays](bbgo_margin_repays.md) - query repay 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
|
* [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
|
* [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
|
* [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
|
* [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
|
* [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
|
* [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
|
* [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
|
* [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
|
* [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
|
* [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
|
* [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
|
* [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
|
* [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
|
* [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
|
* [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
|
* [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,
|
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
|
```sh
|
||||||
TELEGRAM_BOT_AUTH_TOKEN=itsme55667788
|
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.SetPublicOnly()
|
||||||
stream.Subscribe(types.BookChannel, symbol, types.SubscribeOptions{})
|
stream.Subscribe(types.BookChannel, symbol, types.SubscribeOptions{})
|
||||||
|
|
||||||
streamBook := types.NewStreamBook(symbol)
|
streamBook := types.NewStreamBook(symbol, exchange.Name())
|
||||||
streamBook.BindStream(stream)
|
streamBook.BindStream(stream)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|
96
go.mod
96
go.mod
|
@ -2,16 +2,16 @@
|
||||||
|
|
||||||
module github.com/c9s/bbgo
|
module github.com/c9s/bbgo
|
||||||
|
|
||||||
go 1.21
|
go 1.21.0
|
||||||
|
|
||||||
toolchain go1.21.6
|
toolchain go1.21.6
|
||||||
|
|
||||||
require (
|
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/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/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/c9s/rockhopper/v2 v2.0.4
|
||||||
github.com/cenkalti/backoff/v4 v4.2.0
|
github.com/cenkalti/backoff/v4 v4.2.0
|
||||||
github.com/cheggaaa/pb/v3 v3.0.8
|
github.com/cheggaaa/pb/v3 v3.0.8
|
||||||
|
@ -20,13 +20,13 @@ require (
|
||||||
github.com/fatih/camelcase v1.0.0
|
github.com/fatih/camelcase v1.0.0
|
||||||
github.com/fatih/color v1.14.1
|
github.com/fatih/color v1.14.1
|
||||||
github.com/gertd/go-pluralize v0.2.1
|
github.com/gertd/go-pluralize v0.2.1
|
||||||
github.com/gin-contrib/cors v1.3.1
|
github.com/gin-contrib/cors v1.7.2
|
||||||
github.com/gin-gonic/gin v1.9.1
|
github.com/gin-gonic/gin v1.10.0
|
||||||
github.com/go-redis/redis/v8 v8.8.0
|
github.com/go-redis/redis/v8 v8.11.5
|
||||||
github.com/go-sql-driver/mysql v1.8.1
|
github.com/go-sql-driver/mysql v1.8.1
|
||||||
github.com/gofrs/flock v0.8.1
|
github.com/gofrs/flock v0.8.1
|
||||||
github.com/google/uuid v1.4.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/gorilla/websocket v1.5.1
|
github.com/gorilla/websocket v1.5.3
|
||||||
github.com/heroku/rollrus v0.2.0
|
github.com/heroku/rollrus v0.2.0
|
||||||
github.com/jedib0t/go-pretty/v6 v6.5.8
|
github.com/jedib0t/go-pretty/v6 v6.5.8
|
||||||
github.com/jmoiron/sqlx v1.3.4
|
github.com/jmoiron/sqlx v1.3.4
|
||||||
|
@ -55,72 +55,77 @@ require (
|
||||||
github.com/zserge/lorca v0.1.9
|
github.com/zserge/lorca v0.1.9
|
||||||
go.uber.org/mock v0.4.0
|
go.uber.org/mock v0.4.0
|
||||||
go.uber.org/multierr v1.11.0
|
go.uber.org/multierr v1.11.0
|
||||||
golang.org/x/oauth2 v0.15.0
|
golang.org/x/oauth2 v0.22.0
|
||||||
golang.org/x/sync v0.7.0
|
golang.org/x/sync v0.8.0
|
||||||
golang.org/x/time v0.5.0
|
golang.org/x/time v0.6.0
|
||||||
gonum.org/v1/gonum v0.8.2
|
gonum.org/v1/gonum v0.8.2
|
||||||
google.golang.org/api v0.153.0
|
google.golang.org/api v0.194.0
|
||||||
google.golang.org/grpc v1.59.0
|
google.golang.org/grpc v1.65.0
|
||||||
google.golang.org/protobuf v1.31.0
|
google.golang.org/protobuf v1.34.2
|
||||||
gopkg.in/tucnak/telebot.v2 v2.5.0
|
gopkg.in/tucnak/telebot.v2 v2.5.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/compute v1.23.3 // indirect
|
cloud.google.com/go/auth v0.9.1 // indirect
|
||||||
cloud.google.com/go/compute/metadata v0.2.3 // 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
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
github.com/VividCortex/ewma v1.1.1 // indirect
|
github.com/VividCortex/ewma v1.1.1 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bitly/go-simplejson v0.5.1 // indirect
|
github.com/bitly/go-simplejson v0.5.1 // indirect
|
||||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||||
github.com/bytedance/sonic v1.9.1 // indirect
|
github.com/bytedance/sonic v1.12.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/bytedance/sonic/loader v0.2.0 // indirect
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // 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/cockroachdb/apd v1.1.0 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 // 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/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/denisenkom/go-mssqldb v0.12.3 // indirect
|
github.com/denisenkom/go-mssqldb v0.12.3 // indirect
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // 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/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/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/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/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.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/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/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/golang/protobuf v1.5.3 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/google/s2a-go v0.1.7 // indirect
|
github.com/google/s2a-go v0.1.8 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // 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/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect
|
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // 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/builder v0.0.0-20180802200727-47ae307949d0 // indirect
|
||||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // 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/lestrrat-go/strftime v1.0.0 // indirect
|
||||||
github.com/lib/pq v1.10.9 // indirect
|
github.com/lib/pq v1.10.9 // indirect
|
||||||
github.com/magiconair/properties v1.8.7 // indirect
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.15 // 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/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // 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.3 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.0 // indirect
|
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // 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/client_model v0.2.0 // indirect
|
||||||
github.com/prometheus/common v0.32.1 // indirect
|
github.com/prometheus/common v0.32.1 // indirect
|
||||||
|
@ -137,23 +142,24 @@ require (
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
github.com/tebeka/strftime v0.1.3 // indirect
|
github.com/tebeka/strftime v0.1.3 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // 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
|
github.com/ziutek/mymysql v1.5.4 // indirect
|
||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
go.opentelemetry.io/otel v0.19.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v0.19.0 // indirect
|
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v0.19.0 // indirect
|
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||||
golang.org/x/arch v0.3.0 // indirect
|
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||||
golang.org/x/crypto v0.22.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/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect
|
||||||
golang.org/x/image v0.5.0 // indirect
|
golang.org/x/image v0.5.0 // indirect
|
||||||
golang.org/x/mod v0.17.0 // indirect
|
golang.org/x/mod v0.20.0 // indirect
|
||||||
golang.org/x/net v0.24.0 // indirect
|
golang.org/x/net v0.28.0 // indirect
|
||||||
golang.org/x/sys v0.19.0 // indirect
|
golang.org/x/sys v0.24.0 // indirect
|
||||||
golang.org/x/term v0.19.0 // indirect
|
golang.org/x/term v0.23.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.17.0 // indirect
|
||||||
golang.org/x/tools v0.20.0 // indirect
|
golang.org/x/tools v0.24.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // 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.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.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
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.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.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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
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.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/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/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
|
||||||
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
|
cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
|
||||||
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/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
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/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
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/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/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.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.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
||||||
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/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
||||||
github.com/Masterminds/squirrel v1.5.3 h1:YPpoceAcxuzIljlr5iWpNKaql7hLeG1KLSrhvdHpkZc=
|
github.com/Masterminds/squirrel v1.5.3 h1:YPpoceAcxuzIljlr5iWpNKaql7hLeG1KLSrhvdHpkZc=
|
||||||
github.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=
|
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/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
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 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
|
||||||
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
|
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.6.0 h1:sXPkfix+SgBojJmkt+sNJbJBQZOJK5GFP/WtAu+B5r0=
|
||||||
github.com/adshao/go-binance/v2 v2.5.0/go.mod h1:41Up2dG4NfMXpCldrDPETEtiOq+pHoGsFZ73xGgaumo=
|
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/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-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/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/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 h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
|
||||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
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.12.1 h1:jWl5Qz1fy7X1ioY74WqO0KjAMtAGQs4sYnjiEBiyX24=
|
||||||
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
github.com/bytedance/sonic v1.12.1/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
|
||||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
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 h1:25+n1MLv0yvCsD56xv4nqIus3oLHL9GuPAZDLIqmX1U=
|
||||||
github.com/c-bata/goptuna v0.8.1/go.mod h1:knmS8+Iyq5PPy1YUeIEq0pMFR4Y6x7z/CySc9HlZTCY=
|
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.4.3 h1:0QZ27RVBLb9QuBKfiSBTOB5zSUuasrJm2p6/GZZHZZw=
|
||||||
github.com/c9s/requestgen v1.3.6/go.mod h1:QwkZudcv84kJ8g9+E0RDTj+13btFXbTvv2aI+zbuLbc=
|
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 h1:1cQEzU7rzCSz09B2RYdyPWwBW9gZ/DoFqD1b2xLLmAk=
|
||||||
github.com/c9s/rockhopper/v2 v2.0.4/go.mod h1:x0XuYI2Su3kS/74UYu/3Cqc9m5Dtzqh7j7JZarczfss=
|
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=
|
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/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 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.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
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 h1:bC8oemdChbke2FHIIGy9mn4DPJ2caZYQnfbRqwmdCoA=
|
||||||
github.com/cheggaaa/pb/v3 v3.0.8/go.mod h1:UICbiLec/XO6Hw6k+BHEtHeQFzzBH4i2/qk/ow1EJTA=
|
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/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.0/go.mod h1:Miac6hA1ohdDUTagnvJy/q+aNnEk16qWUdb8ZVhvCN0=
|
||||||
github.com/chewxy/math32 v1.0.6/go.mod h1:dOB2rcuFrCn6UHrze36WSLVPKtzPMRAQvBvUwkSsLqs=
|
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/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/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/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/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 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
|
||||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
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.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 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
|
||||||
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
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/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 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
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.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 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
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.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
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 h1:M3uASbVjMnTsPb0PNqg+E/24Vwigyo/tvyMTtAlLgiA=
|
||||||
github.com/gertd/go-pluralize v0.2.1/go.mod h1:rbYaKDbsXxmRfr8uygAEKhOWsjyrrqrkHVpZvoOp8zk=
|
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/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.7.2 h1:oLDHxdg8W/XDoN/8zamqk/Drgt4oVZDvaV0YmvVICQw=
|
||||||
github.com/gin-contrib/cors v1.3.1/go.mod h1:jjEJ4268OPZUcU7k9Pm653S7lXUGcqMADzFA61xsmDk=
|
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 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
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.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
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-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/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.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.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
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 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
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 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
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 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
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.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
|
||||||
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||||
github.com/go-redis/redis/v8 v8.8.0 h1:fDZP58UN/1RD3DjtTXP/fFZ04TFohSYhjZDkcDe2dnw=
|
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||||
github.com/go-redis/redis/v8 v8.8.0/go.mod h1:F7resOH5Kdug49Otu24RjHWwgK7u9AmtqWMnCV1iP5Y=
|
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.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 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
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.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 h1:UHSEyLZUwX9Qoi99vVwvewiMC8mM2bf7XEM2nqvzEn8=
|
||||||
github.com/go-test/deep v1.0.6/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
|
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.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
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 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
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=
|
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.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
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.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
|
||||||
github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc=
|
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 v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.0.0/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-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/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/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.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
|
||||||
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
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.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.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.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
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 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
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.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.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.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s=
|
||||||
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/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
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/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/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.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.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
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-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/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=
|
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/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 h1:b3AgcXJKFJNUwbQOC2S69/+mxuTpe4laznem9VJdPEo=
|
||||||
github.com/heroku/rollrus v0.2.0/go.mod h1:B3MwEcr9nmf4xj0Sr5l9eSht7wLKMa1C+9ajgAU79ek=
|
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/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.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
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/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/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.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.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.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
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.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
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/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.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.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
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.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.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=
|
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/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-20171009123644-5344a9259b21/go.mod h1:N0SVk0uhy+E1PZ3C9ctsPRlvOPAFPkCNlcPBDkt0N3U=
|
||||||
github.com/leesper/go_rng v0.0.0-20190531154944-a612b043e353/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.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
|
||||||
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
|
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/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
|
||||||
github.com/lestrrat-go/file-rotatelogs v2.2.0+incompatible h1:eXEwY0f2h6mcobdAxm4VRSWds4tqmlLdUqxu8ybiEEA=
|
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.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.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.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.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0=
|
||||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
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 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
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=
|
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/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-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/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 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
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/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.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||||
github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4=
|
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
||||||
github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
|
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
||||||
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/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
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 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.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
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/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.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1/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.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.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.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 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
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=
|
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/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 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
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.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
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/valyala/fastjson v1.5.1 h1:SXaQZVSwLjZOVhDEhjiCcDtnX0Feu7Z7A1+C5atpoHM=
|
github.com/valyala/fastjson v1.5.1 h1:SXaQZVSwLjZOVhDEhjiCcDtnX0Feu7Z7A1+C5atpoHM=
|
||||||
github.com/valyala/fastjson v1.5.1/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
github.com/valyala/fastjson v1.5.1/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
||||||
github.com/wcharczuk/go-chart/v2 v2.1.0 h1:tY2slqVQ6bN+yHSnDYwZebLQFkphK4WNrVwnt7CJZ2I=
|
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.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/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.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/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/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||||
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
|
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.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
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/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
|
||||||
go.opentelemetry.io/otel v0.19.0/go.mod h1:j9bF567N9EfomkSidSfmMwIwIBuP37AMAIzVW85OxSg=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
|
||||||
go.opentelemetry.io/otel/metric v0.19.0 h1:dtZ1Ju44gkJkYvo+3qGqVXmf88tc+a42edOywypengg=
|
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
|
||||||
go.opentelemetry.io/otel/metric v0.19.0/go.mod h1:8f9fglJPRnXuskQmKpnad31lcLJ2VmNNqIsx/uIwBSc=
|
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
|
||||||
go.opentelemetry.io/otel/oteltest v0.19.0 h1:YVfA0ByROYqTwOxqHVZYZExzEpfZor+MU1rU+ip2v9Q=
|
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
|
||||||
go.opentelemetry.io/otel/oteltest v0.19.0/go.mod h1:tI4yxwh8U21v7JD6R3BcA/2+RBoTKFexE/PJ/nSO7IA=
|
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
|
||||||
go.opentelemetry.io/otel/trace v0.19.0 h1:1ucYlenXIDA1OlHVLDZKX0ObXV5RLaq06DtUKz5e5zc=
|
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
|
||||||
go.opentelemetry.io/otel/trace v0.19.0/go.mod h1:4IXiNextNOpPnRlI4ryK69mn5iC84bjBWZQA5DXz/qg=
|
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.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.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
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.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
go.uber.org/zap v1.10.0/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=
|
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.9.0 h1:ub9TgUInamJ8mrZIGlBG6/4TqWeMszd4N8lNorbrr6k=
|
||||||
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
golang.org/x/arch v0.9.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
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-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
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-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-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.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.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
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-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-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/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.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.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.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.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
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-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-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/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-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-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-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-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-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-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-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-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-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-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-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-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-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.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.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
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-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-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-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-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-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.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
|
golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA=
|
||||||
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
|
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-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-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/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-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-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-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-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.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
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-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-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-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-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-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-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-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-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-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-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-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/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-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-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-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-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-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-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-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-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-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-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-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.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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
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-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.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.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
|
||||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
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.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.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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.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.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.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.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
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-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-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.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.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
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-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-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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-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-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-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.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.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||||
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
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-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-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/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.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.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
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.194.0 h1:dztZKG9HgtIpbI35FhfuSNR/zmaMVdxNlntHj1sIS4s=
|
||||||
google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY=
|
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.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.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.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.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
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.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-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-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
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-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-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-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/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8=
|
||||||
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY=
|
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||||
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/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
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.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
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.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.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.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
|
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
|
||||||
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
|
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/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-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
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.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
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-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.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
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 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-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-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/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/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/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.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
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/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
|
||||||
modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
|
modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
|
||||||
modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
|
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/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
|
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
|
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.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) {
|
func (b *ActiveOrderBook) filterExistingOrders(orders []types.Order) (existingOrders types.OrderSlice) {
|
||||||
for _, o := range orders {
|
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) {
|
if b.Exists(o) {
|
||||||
existingOrders.Add(o)
|
existingOrders.Add(o)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ import "github.com/c9s/bbgo/pkg/types"
|
||||||
const MaxNumOfKLines = 5_000
|
const MaxNumOfKLines = 5_000
|
||||||
const MaxNumOfKLinesTruncate = 100
|
const MaxNumOfKLinesTruncate = 100
|
||||||
|
|
||||||
|
const CapacityOfKLineWindowLimit = 5_000
|
||||||
|
|
||||||
// MarketDataStore receives and maintain the public market data of a single symbol
|
// MarketDataStore receives and maintain the public market data of a single symbol
|
||||||
//go:generate callbackgen -type MarketDataStore
|
//go:generate callbackgen -type MarketDataStore
|
||||||
type MarketDataStore struct {
|
type MarketDataStore struct {
|
||||||
|
@ -57,10 +59,20 @@ func (store *MarketDataStore) AddKLine(k types.KLine) {
|
||||||
}
|
}
|
||||||
window.Add(k)
|
window.Add(k)
|
||||||
|
|
||||||
if len(*window) > MaxNumOfKLines {
|
truncateKLineWindowIfNeeded(window)
|
||||||
*window = (*window)[MaxNumOfKLinesTruncate-1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
store.EmitKLineClosed(k)
|
store.EmitKLineClosed(k)
|
||||||
store.EmitKLineWindowUpdate(k.Interval, *window)
|
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",
|
Help: "bbgo exchange session connection status",
|
||||||
},
|
},
|
||||||
[]string{
|
[]string{
|
||||||
"exchange", // exchange name
|
"session",
|
||||||
"channel", // channel: user or market
|
"exchange", // exchange name
|
||||||
"margin", // margin type: none, margin or isolated
|
"channel", // channel: user or market
|
||||||
"symbol", // margin symbol of the connection.
|
"margin_type", // margin type: none, margin or isolated
|
||||||
|
"symbol", // margin symbol of the connection.
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
metricsLockedBalances = prometheus.NewGaugeVec(
|
metricsBalanceLockedMetrics = prometheus.NewGaugeVec(
|
||||||
prometheus.GaugeOpts{
|
prometheus.GaugeOpts{
|
||||||
Name: "bbgo_balances_locked",
|
Name: "bbgo_balances_locked",
|
||||||
Help: "bbgo exchange locked balances",
|
Help: "bbgo exchange locked balances",
|
||||||
},
|
},
|
||||||
[]string{
|
[]string{
|
||||||
"exchange", // exchange name
|
"session",
|
||||||
"margin", // margin of connection. 1 or 0
|
"exchange", // exchange name
|
||||||
"symbol", // margin symbol of the connection.
|
"margin_type", // margin of connection. 1 or 0
|
||||||
|
"symbol", // margin symbol of the connection.
|
||||||
"currency",
|
"currency",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
metricsAvailableBalances = prometheus.NewGaugeVec(
|
metricsBalanceAvailableMetrics = prometheus.NewGaugeVec(
|
||||||
prometheus.GaugeOpts{
|
prometheus.GaugeOpts{
|
||||||
Name: "bbgo_balances_available",
|
Name: "bbgo_balances_available",
|
||||||
Help: "bbgo exchange available balances",
|
Help: "bbgo exchange available balances",
|
||||||
},
|
},
|
||||||
[]string{
|
[]string{
|
||||||
"exchange", // exchange name
|
"session",
|
||||||
"margin", // margin of connection. none, margin or isolated
|
"exchange", // exchange name
|
||||||
"symbol", // margin symbol of the connection.
|
"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",
|
"currency",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -48,9 +107,10 @@ var (
|
||||||
Help: "bbgo exchange session total balances",
|
Help: "bbgo exchange session total balances",
|
||||||
},
|
},
|
||||||
[]string{
|
[]string{
|
||||||
"exchange", // exchange name
|
"session",
|
||||||
"margin", // margin of connection. none, margin or isolated
|
"exchange", // exchange name
|
||||||
"symbol", // margin symbol of the connection.
|
"margin_type", // margin of connection. none, margin or isolated
|
||||||
|
"symbol", // margin symbol of the connection.
|
||||||
"currency",
|
"currency",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -61,11 +121,12 @@ var (
|
||||||
Help: "bbgo exchange session trades",
|
Help: "bbgo exchange session trades",
|
||||||
},
|
},
|
||||||
[]string{
|
[]string{
|
||||||
"exchange", // exchange name
|
"session",
|
||||||
"margin", // margin of connection. none, margin or isolated
|
"exchange", // exchange name
|
||||||
"symbol", // margin symbol of the connection.
|
"margin_type", // margin of connection. none, margin or isolated
|
||||||
"side", // side: buy or sell
|
"symbol", // margin symbol of the connection.
|
||||||
"liquidity", // maker or taker
|
"side", // side: buy or sell
|
||||||
|
"liquidity", // maker or taker
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -75,26 +136,28 @@ var (
|
||||||
Help: "bbgo trading volume",
|
Help: "bbgo trading volume",
|
||||||
},
|
},
|
||||||
[]string{
|
[]string{
|
||||||
"exchange", // exchange name
|
"session",
|
||||||
"margin", // margin of connection. none, margin or isolated
|
"exchange", // exchange name
|
||||||
"symbol", // margin symbol of the connection.
|
"margin_type", // margin of connection. none, margin or isolated
|
||||||
"side", // side: buy or sell
|
"symbol", // margin symbol of the connection.
|
||||||
"liquidity", // maker or taker
|
"side", // side: buy or sell
|
||||||
|
"liquidity", // maker or taker
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
metricsLastUpdateTimeBalance = prometheus.NewGaugeVec(
|
metricsLastUpdateTimeMetrics = prometheus.NewGaugeVec(
|
||||||
prometheus.GaugeOpts{
|
prometheus.GaugeOpts{
|
||||||
Name: "bbgo_last_update_time",
|
Name: "bbgo_last_update_time",
|
||||||
Help: "bbgo last update time of different channel",
|
Help: "bbgo last update time of different channel",
|
||||||
},
|
},
|
||||||
[]string{
|
[]string{
|
||||||
"exchange", // exchange name
|
"session",
|
||||||
"margin", // margin of connection. none, margin or isolated
|
"exchange", // exchange name
|
||||||
"channel", // channel: user, market
|
"margin_type", // margin of connection. none, margin or isolated
|
||||||
"data_type", // type: balance, ticker, kline, orderbook, trade, order
|
"channel", // channel: user, market
|
||||||
"symbol", // for market data, trade and order
|
"data_type", // type: balance, ticker, kline, orderbook, trade, order
|
||||||
"currency", // for balance
|
"symbol", // for market data, trade and order
|
||||||
|
"currency", // for balance
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -103,10 +166,14 @@ func init() {
|
||||||
prometheus.MustRegister(
|
prometheus.MustRegister(
|
||||||
metricsConnectionStatus,
|
metricsConnectionStatus,
|
||||||
metricsTotalBalances,
|
metricsTotalBalances,
|
||||||
metricsLockedBalances,
|
metricsBalanceNetMetrics,
|
||||||
metricsAvailableBalances,
|
metricsBalanceLockedMetrics,
|
||||||
|
metricsBalanceAvailableMetrics,
|
||||||
|
metricsBalanceDebtMetrics,
|
||||||
|
metricsBalanceBorrowedMetrics,
|
||||||
|
metricsBalanceInterestMetrics,
|
||||||
metricsTradesTotal,
|
metricsTradesTotal,
|
||||||
metricsTradingVolume,
|
metricsTradingVolume,
|
||||||
metricsLastUpdateTimeBalance,
|
metricsLastUpdateTimeMetrics,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,9 @@ var quantityReduceDelta = fixedpoint.NewFromFloat(0.005)
|
||||||
// This is for the maximum retries
|
// This is for the maximum retries
|
||||||
const submitOrderRetryLimit = 5
|
const submitOrderRetryLimit = 5
|
||||||
|
|
||||||
|
// BaseOrderExecutor provides the common accessors for order executor
|
||||||
type BaseOrderExecutor struct {
|
type BaseOrderExecutor struct {
|
||||||
|
exchange types.Exchange
|
||||||
session *ExchangeSession
|
session *ExchangeSession
|
||||||
activeMakerOrders *ActiveOrderBook
|
activeMakerOrders *ActiveOrderBook
|
||||||
orderStore *core.OrderStore
|
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
|
// 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 {
|
func (e *BaseOrderExecutor) GracefulCancel(ctx context.Context, orders ...types.Order) error {
|
||||||
if err := e.activeMakerOrders.GracefulCancel(ctx, e.session.Exchange, orders...); err != nil {
|
if err := e.activeMakerOrders.GracefulCancel(ctx, e.exchange, orders...); err != nil {
|
||||||
return errors.Wrap(err, "graceful cancel error")
|
return errors.Wrap(err, "graceful cancel order error")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -84,6 +86,7 @@ func NewGeneralOrderExecutor(
|
||||||
executor := &GeneralOrderExecutor{
|
executor := &GeneralOrderExecutor{
|
||||||
BaseOrderExecutor: BaseOrderExecutor{
|
BaseOrderExecutor: BaseOrderExecutor{
|
||||||
session: session,
|
session: session,
|
||||||
|
exchange: session.Exchange,
|
||||||
activeMakerOrders: NewActiveOrderBook(symbol),
|
activeMakerOrders: NewActiveOrderBook(symbol),
|
||||||
orderStore: orderStore,
|
orderStore: orderStore,
|
||||||
},
|
},
|
||||||
|
@ -111,7 +114,7 @@ func (e *GeneralOrderExecutor) SetMaxRetries(maxRetries uint) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *GeneralOrderExecutor) startMarginAssetUpdater(ctx context.Context) {
|
func (e *GeneralOrderExecutor) startMarginAssetUpdater(ctx context.Context) {
|
||||||
marginService, ok := e.session.Exchange.(types.MarginBorrowRepayService)
|
marginService, ok := e.exchange.(types.MarginBorrowRepayService)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Warnf("session %s (%T) exchange does not support MarginBorrowRepayService", e.session.Name, e.session.Exchange)
|
log.Warnf("session %s (%T) exchange does not support MarginBorrowRepayService", e.session.Name, e.session.Exchange)
|
||||||
return
|
return
|
||||||
|
|
|
@ -22,6 +22,7 @@ func NewSimpleOrderExecutor(session *ExchangeSession) *SimpleOrderExecutor {
|
||||||
return &SimpleOrderExecutor{
|
return &SimpleOrderExecutor{
|
||||||
BaseOrderExecutor: BaseOrderExecutor{
|
BaseOrderExecutor: BaseOrderExecutor{
|
||||||
session: session,
|
session: session,
|
||||||
|
exchange: session.Exchange,
|
||||||
activeMakerOrders: NewActiveOrderBook(""),
|
activeMakerOrders: NewActiveOrderBook(""),
|
||||||
orderStore: core.NewOrderStore(""),
|
orderStore: core.NewOrderStore(""),
|
||||||
},
|
},
|
||||||
|
|
|
@ -12,12 +12,16 @@ type Quota struct {
|
||||||
Locked fixedpoint.Value
|
Locked fixedpoint.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add adds the fund to the available quota
|
||||||
func (q *Quota) Add(fund fixedpoint.Value) {
|
func (q *Quota) Add(fund fixedpoint.Value) {
|
||||||
q.mu.Lock()
|
q.mu.Lock()
|
||||||
q.Available = q.Available.Add(fund)
|
q.Available = q.Available.Add(fund)
|
||||||
q.mu.Unlock()
|
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 {
|
func (q *Quota) Lock(fund fixedpoint.Value) bool {
|
||||||
if fund.Compare(q.Available) > 0 {
|
if fund.Compare(q.Available) > 0 {
|
||||||
return false
|
return false
|
||||||
|
@ -31,12 +35,15 @@ func (q *Quota) Lock(fund fixedpoint.Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Commit commits the locked fund
|
||||||
func (q *Quota) Commit() {
|
func (q *Quota) Commit() {
|
||||||
q.mu.Lock()
|
q.mu.Lock()
|
||||||
q.Locked = fixedpoint.Zero
|
q.Locked = fixedpoint.Zero
|
||||||
q.mu.Unlock()
|
q.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rollback rolls back the locked fund
|
||||||
|
// this will move the locked fund to the available quota
|
||||||
func (q *Quota) Rollback() {
|
func (q *Quota) Rollback() {
|
||||||
q.mu.Lock()
|
q.mu.Lock()
|
||||||
q.Available = q.Available.Add(q.Locked)
|
q.Available = q.Available.Add(q.Locked)
|
||||||
|
@ -44,12 +51,21 @@ func (q *Quota) Rollback() {
|
||||||
q.mu.Unlock()
|
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 {
|
type QuotaTransaction struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
BaseAsset Quota
|
BaseAsset Quota
|
||||||
QuoteAsset Quota
|
QuoteAsset Quota
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Commit commits the transaction
|
||||||
func (m *QuotaTransaction) Commit() bool {
|
func (m *QuotaTransaction) Commit() bool {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
m.BaseAsset.Commit()
|
m.BaseAsset.Commit()
|
||||||
|
@ -58,6 +74,7 @@ func (m *QuotaTransaction) Commit() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rollback rolls back the transaction
|
||||||
func (m *QuotaTransaction) Rollback() bool {
|
func (m *QuotaTransaction) Rollback() bool {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
m.BaseAsset.Rollback()
|
m.BaseAsset.Rollback()
|
||||||
|
|
|
@ -54,11 +54,11 @@ type ExchangeSession struct {
|
||||||
PublicOnly bool `json:"publicOnly,omitempty" yaml:"publicOnly"`
|
PublicOnly bool `json:"publicOnly,omitempty" yaml:"publicOnly"`
|
||||||
|
|
||||||
// PrivateChannels is used for filtering the private user data channel, .e.g, orders, trades, balances.. etc
|
// 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"`
|
PrivateChannels []string `json:"privateChannels,omitempty" yaml:"privateChannels,omitempty"`
|
||||||
|
|
||||||
// PrivateChannelSymbols is used for filtering the private user data channel, .e.g, order symbol subscription.
|
// 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"`
|
PrivateChannelSymbols []string `json:"privateChannelSymbols,omitempty" yaml:"privateChannelSymbols,omitempty"`
|
||||||
|
|
||||||
Margin bool `json:"margin,omitempty" yaml:"margin"`
|
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)
|
return fmt.Errorf("market %s is not defined", symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
session.logger.Infof("environment config: %+v", environ.environmentConfig)
|
||||||
|
|
||||||
disableMarketDataStore := environ.environmentConfig != nil && environ.environmentConfig.DisableMarketDataStore
|
disableMarketDataStore := environ.environmentConfig != nil && environ.environmentConfig.DisableMarketDataStore
|
||||||
disableSessionTradeBuffer := environ.environmentConfig != nil && environ.environmentConfig.DisableSessionTradeBuffer
|
disableSessionTradeBuffer := environ.environmentConfig != nil && environ.environmentConfig.DisableSessionTradeBuffer
|
||||||
maxSessionTradeBufferSize := 0
|
maxSessionTradeBufferSize := 0
|
||||||
|
@ -464,7 +466,7 @@ func (session *ExchangeSession) initSymbol(ctx context.Context, environ *Environ
|
||||||
for _, sub := range session.Subscriptions {
|
for _, sub := range session.Subscriptions {
|
||||||
switch sub.Channel {
|
switch sub.Channel {
|
||||||
case types.BookChannel:
|
case types.BookChannel:
|
||||||
book := types.NewStreamBook(sub.Symbol)
|
book := types.NewStreamBook(sub.Symbol, session.ExchangeName)
|
||||||
book.BindStream(session.MarketDataStream)
|
book.BindStream(session.MarketDataStream)
|
||||||
session.orderBooks[sub.Symbol] = book
|
session.orderBooks[sub.Symbol] = book
|
||||||
|
|
||||||
|
@ -886,91 +888,106 @@ func (session *ExchangeSession) InitExchange(name string, ex types.Exchange) err
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *ExchangeSession) MarginType() string {
|
func (session *ExchangeSession) MarginType() types.MarginType {
|
||||||
margin := "none"
|
|
||||||
if session.Margin {
|
if session.Margin {
|
||||||
margin = "margin"
|
|
||||||
if session.IsolatedMargin {
|
if session.IsolatedMargin {
|
||||||
margin = "isolated"
|
return types.MarginTypeIsolatedMargin
|
||||||
|
} else {
|
||||||
|
return types.MarginTypeCrossMargin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return margin
|
|
||||||
|
return types.MarginTypeSpot
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *ExchangeSession) metricsBalancesUpdater(balances types.BalanceMap) {
|
func (session *ExchangeSession) metricsBalancesUpdater(balances types.BalanceMap) {
|
||||||
for currency, balance := range balances {
|
for currency, balance := range balances {
|
||||||
labels := prometheus.Labels{
|
labels := prometheus.Labels{
|
||||||
"exchange": session.ExchangeName.String(),
|
"session": session.Name,
|
||||||
"margin": session.MarginType(),
|
"exchange": session.ExchangeName.String(),
|
||||||
"symbol": session.IsolatedMarginSymbol,
|
"margin_type": string(session.MarginType()),
|
||||||
"currency": currency,
|
"symbol": session.IsolatedMarginSymbol,
|
||||||
|
"currency": currency,
|
||||||
}
|
}
|
||||||
|
|
||||||
metricsTotalBalances.With(labels).Set(balance.Total().Float64())
|
metricsTotalBalances.With(labels).Set(balance.Total().Float64())
|
||||||
metricsLockedBalances.With(labels).Set(balance.Locked.Float64())
|
metricsBalanceNetMetrics.With(labels).Set(balance.Net().Float64())
|
||||||
metricsAvailableBalances.With(labels).Set(balance.Available.Float64())
|
metricsBalanceAvailableMetrics.With(labels).Set(balance.Available.Float64())
|
||||||
metricsLastUpdateTimeBalance.With(prometheus.Labels{
|
metricsBalanceLockedMetrics.With(labels).Set(balance.Locked.Float64())
|
||||||
"exchange": session.ExchangeName.String(),
|
|
||||||
"margin": session.MarginType(),
|
// margin metrics
|
||||||
"channel": "user",
|
metricsBalanceDebtMetrics.With(labels).Set(balance.Debt().Float64())
|
||||||
"data_type": "balance",
|
metricsBalanceBorrowedMetrics.With(labels).Set(balance.Borrowed.Float64())
|
||||||
"symbol": "",
|
metricsBalanceInterestMetrics.With(labels).Set(balance.Interest.Float64())
|
||||||
"currency": currency,
|
|
||||||
|
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()
|
}).SetToCurrentTime()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *ExchangeSession) metricsOrderUpdater(order types.Order) {
|
func (session *ExchangeSession) metricsOrderUpdater(order types.Order) {
|
||||||
metricsLastUpdateTimeBalance.With(prometheus.Labels{
|
metricsLastUpdateTimeMetrics.With(prometheus.Labels{
|
||||||
"exchange": session.ExchangeName.String(),
|
"session": session.Name,
|
||||||
"margin": session.MarginType(),
|
"exchange": session.ExchangeName.String(),
|
||||||
"channel": "user",
|
"margin_type": string(session.MarginType()),
|
||||||
"data_type": "order",
|
"channel": "user",
|
||||||
"symbol": order.Symbol,
|
"data_type": "order",
|
||||||
"currency": "",
|
"symbol": order.Symbol,
|
||||||
|
"currency": "",
|
||||||
}).SetToCurrentTime()
|
}).SetToCurrentTime()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *ExchangeSession) metricsTradeUpdater(trade types.Trade) {
|
func (session *ExchangeSession) metricsTradeUpdater(trade types.Trade) {
|
||||||
labels := prometheus.Labels{
|
labels := prometheus.Labels{
|
||||||
"exchange": session.ExchangeName.String(),
|
"session": session.Name,
|
||||||
"margin": session.MarginType(),
|
"exchange": session.ExchangeName.String(),
|
||||||
"side": trade.Side.String(),
|
"margin_type": string(session.MarginType()),
|
||||||
"symbol": trade.Symbol,
|
"side": trade.Side.String(),
|
||||||
"liquidity": trade.Liquidity(),
|
"symbol": trade.Symbol,
|
||||||
|
"liquidity": trade.Liquidity(),
|
||||||
}
|
}
|
||||||
metricsTradingVolume.With(labels).Add(trade.Quantity.Mul(trade.Price).Float64())
|
metricsTradingVolume.With(labels).Add(trade.Quantity.Mul(trade.Price).Float64())
|
||||||
metricsTradesTotal.With(labels).Inc()
|
metricsTradesTotal.With(labels).Inc()
|
||||||
metricsLastUpdateTimeBalance.With(prometheus.Labels{
|
metricsLastUpdateTimeMetrics.With(prometheus.Labels{
|
||||||
"exchange": session.ExchangeName.String(),
|
"session": session.Name,
|
||||||
"margin": session.MarginType(),
|
"exchange": session.ExchangeName.String(),
|
||||||
"channel": "user",
|
"margin_type": string(session.MarginType()),
|
||||||
"data_type": "trade",
|
"channel": "user",
|
||||||
"symbol": trade.Symbol,
|
"data_type": "trade",
|
||||||
"currency": "",
|
"symbol": trade.Symbol,
|
||||||
|
"currency": "",
|
||||||
}).SetToCurrentTime()
|
}).SetToCurrentTime()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *ExchangeSession) bindMarketDataStreamMetrics(stream types.Stream) {
|
func (session *ExchangeSession) bindMarketDataStreamMetrics(stream types.Stream) {
|
||||||
stream.OnBookUpdate(func(book types.SliceOrderBook) {
|
stream.OnBookUpdate(func(book types.SliceOrderBook) {
|
||||||
metricsLastUpdateTimeBalance.With(prometheus.Labels{
|
metricsLastUpdateTimeMetrics.With(prometheus.Labels{
|
||||||
"exchange": session.ExchangeName.String(),
|
"session": session.Name,
|
||||||
"margin": session.MarginType(),
|
"exchange": session.ExchangeName.String(),
|
||||||
"channel": "market",
|
"margin_type": string(session.MarginType()),
|
||||||
"data_type": "book",
|
"channel": "market",
|
||||||
"symbol": book.Symbol,
|
"data_type": "book",
|
||||||
"currency": "",
|
"symbol": book.Symbol,
|
||||||
|
"currency": "",
|
||||||
}).SetToCurrentTime()
|
}).SetToCurrentTime()
|
||||||
})
|
})
|
||||||
stream.OnKLineClosed(func(kline types.KLine) {
|
stream.OnKLineClosed(func(kline types.KLine) {
|
||||||
metricsLastUpdateTimeBalance.With(prometheus.Labels{
|
metricsLastUpdateTimeMetrics.With(prometheus.Labels{
|
||||||
"exchange": session.ExchangeName.String(),
|
"session": session.Name,
|
||||||
"margin": session.MarginType(),
|
"exchange": session.ExchangeName.String(),
|
||||||
"channel": "market",
|
"margin_type": string(session.MarginType()),
|
||||||
"data_type": "kline",
|
"channel": "market",
|
||||||
"symbol": kline.Symbol,
|
"data_type": "kline",
|
||||||
"currency": "",
|
"symbol": kline.Symbol,
|
||||||
|
"currency": "",
|
||||||
}).SetToCurrentTime()
|
}).SetToCurrentTime()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -982,18 +999,20 @@ func (session *ExchangeSession) bindUserDataStreamMetrics(stream types.Stream) {
|
||||||
stream.OnOrderUpdate(session.metricsOrderUpdater)
|
stream.OnOrderUpdate(session.metricsOrderUpdater)
|
||||||
stream.OnDisconnect(func() {
|
stream.OnDisconnect(func() {
|
||||||
metricsConnectionStatus.With(prometheus.Labels{
|
metricsConnectionStatus.With(prometheus.Labels{
|
||||||
"channel": "user",
|
"channel": "user",
|
||||||
"exchange": session.ExchangeName.String(),
|
"session": session.Name,
|
||||||
"margin": session.MarginType(),
|
"exchange": session.ExchangeName.String(),
|
||||||
"symbol": session.IsolatedMarginSymbol,
|
"margin_type": string(session.MarginType()),
|
||||||
|
"symbol": session.IsolatedMarginSymbol,
|
||||||
}).Set(0.0)
|
}).Set(0.0)
|
||||||
})
|
})
|
||||||
stream.OnConnect(func() {
|
stream.OnConnect(func() {
|
||||||
metricsConnectionStatus.With(prometheus.Labels{
|
metricsConnectionStatus.With(prometheus.Labels{
|
||||||
"channel": "user",
|
"channel": "user",
|
||||||
"exchange": session.ExchangeName.String(),
|
"session": session.Name,
|
||||||
"margin": session.MarginType(),
|
"exchange": session.ExchangeName.String(),
|
||||||
"symbol": session.IsolatedMarginSymbol,
|
"margin_type": string(session.MarginType()),
|
||||||
|
"symbol": session.IsolatedMarginSymbol,
|
||||||
}).Set(1.0)
|
}).Set(1.0)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,18 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Strategy method calls:
|
// Strategy method calls:
|
||||||
// -> Initialize() (optional method)
|
|
||||||
// -> Defaults() (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)
|
// -> Validate() (optional method)
|
||||||
// -> Run() (optional method)
|
// -> Run() (optional method)
|
||||||
// -> Shutdown(shutdownCtx context.Context, wg *sync.WaitGroup)
|
// -> Shutdown(shutdownCtx context.Context, wg *sync.WaitGroup)
|
||||||
|
@ -112,6 +122,12 @@ func (trader *Trader) DisableLogging() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (trader *Trader) Configure(userConfig *Config) error {
|
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 {
|
if userConfig.RiskControls != nil {
|
||||||
trader.SetRiskControls(userConfig.RiskControls)
|
trader.SetRiskControls(userConfig.RiskControls)
|
||||||
}
|
}
|
||||||
|
@ -171,12 +187,6 @@ func (trader *Trader) SetRiskControls(riskControls *RiskControls) {
|
||||||
func (trader *Trader) RunSingleExchangeStrategy(
|
func (trader *Trader) RunSingleExchangeStrategy(
|
||||||
ctx context.Context, strategy SingleExchangeStrategy, session *ExchangeSession, orderExecutor OrderExecutor,
|
ctx context.Context, strategy SingleExchangeStrategy, session *ExchangeSession, orderExecutor OrderExecutor,
|
||||||
) error {
|
) 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 {
|
if shutdown, ok := strategy.(StrategyShutdown); ok {
|
||||||
trader.gracefulShutdown.OnShutdown(shutdown.Shutdown)
|
trader.gracefulShutdown.OnShutdown(shutdown.Shutdown)
|
||||||
}
|
}
|
||||||
|
@ -238,12 +248,6 @@ func (trader *Trader) injectFieldsAndSubscribe(ctx context.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if defaulter, ok := strategy.(StrategyDefaulter); ok {
|
|
||||||
if err := defaulter.Defaults(); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if subscriber, ok := strategy.(ExchangeSessionSubscriber); ok {
|
if subscriber, ok := strategy.(ExchangeSessionSubscriber); ok {
|
||||||
subscriber.Subscribe(session)
|
subscriber.Subscribe(session)
|
||||||
} else {
|
} 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 {
|
if subscriber, ok := strategy.(CrossExchangeSessionSubscriber); ok {
|
||||||
subscriber.CrossSubscribe(trader.environment.sessions)
|
subscriber.CrossSubscribe(trader.environment.sessions)
|
||||||
} else {
|
} else {
|
||||||
|
@ -356,8 +354,23 @@ func (trader *Trader) Run(ctx context.Context) error {
|
||||||
return trader.environment.Connect(ctx)
|
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 {
|
func (trader *Trader) Initialize(ctx context.Context) error {
|
||||||
return trader.IterateStrategies(func(strategy StrategyID) 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 {
|
if initializer, ok := strategy.(StrategyInitializer); ok {
|
||||||
return initializer.Initialize()
|
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)
|
return fmt.Errorf("session %s not found", sessionName)
|
||||||
}
|
}
|
||||||
|
|
||||||
orderBook := types.NewMutexOrderBook(symbol)
|
orderBook := types.NewMutexOrderBook(symbol, session.Exchange.Name())
|
||||||
|
|
||||||
s := session.Exchange.NewStream()
|
s := session.Exchange.NewStream()
|
||||||
s.SetPublicOnly()
|
s.SetPublicOnly()
|
||||||
|
|
|
@ -3,19 +3,14 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/bbgo"
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"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
|
// go run ./cmd/bbgo submit-order --session=ftx --symbol=BTCUSDT --side=buy --price=18000 --quantity=0.001
|
||||||
var submitOrderCmd = &cobra.Command{
|
var submitOrderCmd = &cobra.Command{
|
||||||
Use: "submit-order --session SESSION --symbol SYMBOL --side SIDE --quantity QUANTITY [--price PRICE]",
|
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().Bool("market", false, "submit order as a market order")
|
||||||
submitOrderCmd.Flags().String("margin-side-effect", "", "margin order side effect")
|
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(listOrdersCmd)
|
||||||
RootCmd.AddCommand(getOrderCmd)
|
RootCmd.AddCommand(getOrderCmd)
|
||||||
RootCmd.AddCommand(submitOrderCmd)
|
RootCmd.AddCommand(submitOrderCmd)
|
||||||
RootCmd.AddCommand(executeOrderCmd)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,10 @@ package binance
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/c9s/bbgo/pkg/exchange/binance/binanceapi"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/exchange/binance/binanceapi"
|
||||||
|
|
||||||
"github.com/adshao/go-binance/v2/futures"
|
"github.com/adshao/go-binance/v2/futures"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
@ -42,11 +43,10 @@ func toGlobalFuturesPositions(futuresPositions []*binanceapi.FuturesAccountPosit
|
||||||
retFuturesPositions := make(types.FuturesPositionMap)
|
retFuturesPositions := make(types.FuturesPositionMap)
|
||||||
for _, futuresPosition := range futuresPositions {
|
for _, futuresPosition := range futuresPositions {
|
||||||
retFuturesPositions[futuresPosition.Symbol] = types.FuturesPosition{ // TODO: types.FuturesPosition
|
retFuturesPositions[futuresPosition.Symbol] = types.FuturesPosition{ // TODO: types.FuturesPosition
|
||||||
Isolated: futuresPosition.Isolated,
|
Isolated: futuresPosition.Isolated,
|
||||||
AverageCost: fixedpoint.MustNewFromString(futuresPosition.EntryPrice),
|
AverageCost: fixedpoint.MustNewFromString(futuresPosition.EntryPrice),
|
||||||
ApproximateAverageCost: fixedpoint.MustNewFromString(futuresPosition.EntryPrice),
|
Base: fixedpoint.MustNewFromString(futuresPosition.PositionAmt),
|
||||||
Base: fixedpoint.MustNewFromString(futuresPosition.PositionAmt),
|
Quote: fixedpoint.MustNewFromString(futuresPosition.Notional),
|
||||||
Quote: fixedpoint.MustNewFromString(futuresPosition.Notional),
|
|
||||||
|
|
||||||
PositionRisk: &types.PositionRisk{
|
PositionRisk: &types.PositionRisk{
|
||||||
Leverage: fixedpoint.MustNewFromString(futuresPosition.Leverage),
|
Leverage: fixedpoint.MustNewFromString(futuresPosition.Leverage),
|
||||||
|
|
|
@ -796,13 +796,24 @@ func (e *Exchange) QueryOrder(ctx context.Context, q types.OrderQuery) (*types.O
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var order *binance.Order
|
|
||||||
if e.IsMargin {
|
if e.IsMargin {
|
||||||
order, err = e.client.NewGetMarginOrderService().Symbol(q.Symbol).OrderID(orderID).Do(ctx)
|
order, err := e.client.NewGetMarginOrderService().Symbol(q.Symbol).OrderID(orderID).Do(ctx)
|
||||||
} else {
|
if err != nil {
|
||||||
order, err = e.client.NewGetOrderService().Symbol(q.Symbol).OrderID(orderID).Do(ctx)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -994,7 +1005,6 @@ func (e *Exchange) submitMarginOrder(ctx context.Context, order types.SubmitOrde
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// could be IOC or FOK
|
|
||||||
if len(order.TimeInForce) > 0 {
|
if len(order.TimeInForce) > 0 {
|
||||||
// TODO: check the TimeInForce value
|
// TODO: check the TimeInForce value
|
||||||
req.TimeInForce(binance.TimeInForceType(order.TimeInForce))
|
req.TimeInForce(binance.TimeInForceType(order.TimeInForce))
|
||||||
|
|
|
@ -247,29 +247,6 @@ func toGlobalTradeV3(t v3.Trade) ([]types.Trade, error) {
|
||||||
return trades, nil
|
return trades, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func toGlobalTradeV2(t max.Trade) (*types.Trade, error) {
|
|
||||||
isMargin := t.WalletType == max.WalletTypeMargin
|
|
||||||
side := toGlobalSideType(t.Side)
|
|
||||||
return &types.Trade{
|
|
||||||
ID: t.ID,
|
|
||||||
OrderID: t.OrderID,
|
|
||||||
Price: t.Price,
|
|
||||||
Symbol: toGlobalSymbol(t.Market),
|
|
||||||
Exchange: types.ExchangeMax,
|
|
||||||
Quantity: t.Volume,
|
|
||||||
Side: side,
|
|
||||||
IsBuyer: t.IsBuyer(),
|
|
||||||
IsMaker: t.IsMaker(),
|
|
||||||
Fee: t.Fee,
|
|
||||||
FeeCurrency: toGlobalCurrency(t.FeeCurrency),
|
|
||||||
QuoteQuantity: t.Funds,
|
|
||||||
Time: types.Time(t.CreatedAt),
|
|
||||||
IsMargin: isMargin,
|
|
||||||
IsIsolated: false,
|
|
||||||
IsFutures: false,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func toGlobalDepositStatus(a max.DepositState) types.DepositStatus {
|
func toGlobalDepositStatus(a max.DepositState) types.DepositStatus {
|
||||||
switch a {
|
switch a {
|
||||||
|
|
||||||
|
@ -284,11 +261,21 @@ func toGlobalDepositStatus(a max.DepositState) types.DepositStatus {
|
||||||
|
|
||||||
case max.DepositStateAccepted:
|
case max.DepositStateAccepted:
|
||||||
return types.DepositSuccess
|
return types.DepositSuccess
|
||||||
|
|
||||||
|
case max.DepositStateFailed: // v3 state
|
||||||
|
return types.DepositRejected
|
||||||
|
|
||||||
|
case max.DepositStateProcessing: // v3 states
|
||||||
|
return types.DepositPending
|
||||||
|
|
||||||
|
case max.DepositStateDone: // v3 states
|
||||||
|
return types.DepositSuccess
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// other states goes to this
|
// other states goes to this
|
||||||
// max.DepositStateSuspect, max.DepositStateSuspended
|
// max.DepositStateSuspect, max.DepositStateSuspended
|
||||||
log.Warnf("unsupported deposit state %q from max exchange", a)
|
log.Errorf("unsupported deposit state %q from max exchange", a)
|
||||||
return types.DepositStatus(a)
|
return types.DepositStatus(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,11 @@ const (
|
||||||
DepositStateSuspended DepositState = "suspended"
|
DepositStateSuspended DepositState = "suspended"
|
||||||
DepositStateAccepted DepositState = "accepted"
|
DepositStateAccepted DepositState = "accepted"
|
||||||
DepositStateChecking DepositState = "checking"
|
DepositStateChecking DepositState = "checking"
|
||||||
|
|
||||||
|
// v3 states
|
||||||
|
DepositStateProcessing DepositState = "processing"
|
||||||
|
DepositStateFailed DepositState = "failed"
|
||||||
|
DepositStateDone DepositState = "done"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Deposit struct {
|
type Deposit struct {
|
||||||
|
|
|
@ -136,6 +136,12 @@ func (c *CancelOrderRequest) GetSlugsMap() (map[string]string, error) {
|
||||||
return slugs, nil
|
return slugs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPath returns the request path of the API
|
||||||
|
func (c *CancelOrderRequest) GetPath() string {
|
||||||
|
return "/api/v3/order"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do generates the request object and send the request object to the API endpoint
|
||||||
func (c *CancelOrderRequest) Do(ctx context.Context) (*max.Order, error) {
|
func (c *CancelOrderRequest) Do(ctx context.Context) (*max.Order, error) {
|
||||||
|
|
||||||
params, err := c.GetParameters()
|
params, err := c.GetParameters()
|
||||||
|
@ -144,7 +150,9 @@ func (c *CancelOrderRequest) Do(ctx context.Context) (*max.Order, error) {
|
||||||
}
|
}
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
|
|
||||||
apiURL := "/api/v3/order"
|
var apiURL string
|
||||||
|
|
||||||
|
apiURL = c.GetPath()
|
||||||
|
|
||||||
req, err := c.client.NewAuthenticatedRequest(ctx, "DELETE", apiURL, query, params)
|
req, err := c.client.NewAuthenticatedRequest(ctx, "DELETE", apiURL, query, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -157,8 +165,32 @@ func (c *CancelOrderRequest) Do(ctx context.Context) (*max.Order, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiResponse max.Order
|
var apiResponse max.Order
|
||||||
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
|
return &apiResponse, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,10 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/c9s/bbgo/pkg/exchange/max/maxapi"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
max "github.com/c9s/bbgo/pkg/exchange/max/maxapi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *CancelWalletOrderAllRequest) Side(side string) *CancelWalletOrderAllRequest {
|
func (c *CancelWalletOrderAllRequest) Side(side string) *CancelWalletOrderAllRequest {
|
||||||
|
@ -166,6 +165,12 @@ func (c *CancelWalletOrderAllRequest) GetSlugsMap() (map[string]string, error) {
|
||||||
return slugs, nil
|
return slugs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPath returns the request path of the API
|
||||||
|
func (c *CancelWalletOrderAllRequest) GetPath() string {
|
||||||
|
return "/api/v3/wallet/:walletType/orders"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do generates the request object and send the request object to the API endpoint
|
||||||
func (c *CancelWalletOrderAllRequest) Do(ctx context.Context) ([]OrderCancelResponse, error) {
|
func (c *CancelWalletOrderAllRequest) Do(ctx context.Context) ([]OrderCancelResponse, error) {
|
||||||
|
|
||||||
params, err := c.GetParameters()
|
params, err := c.GetParameters()
|
||||||
|
@ -174,7 +179,9 @@ func (c *CancelWalletOrderAllRequest) Do(ctx context.Context) ([]OrderCancelResp
|
||||||
}
|
}
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
|
|
||||||
apiURL := "/api/v3/wallet/:walletType/orders"
|
var apiURL string
|
||||||
|
|
||||||
|
apiURL = c.GetPath()
|
||||||
slugs, err := c.GetSlugsMap()
|
slugs, err := c.GetSlugsMap()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -193,8 +200,32 @@ func (c *CancelWalletOrderAllRequest) Do(ctx context.Context) ([]OrderCancelResp
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiResponse []OrderCancelResponse
|
var apiResponse []OrderCancelResponse
|
||||||
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
|
return apiResponse, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,6 +236,12 @@ func (c *CreateWalletOrderRequest) GetSlugsMap() (map[string]string, error) {
|
||||||
return slugs, nil
|
return slugs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPath returns the request path of the API
|
||||||
|
func (c *CreateWalletOrderRequest) GetPath() string {
|
||||||
|
return "/api/v3/wallet/:walletType/order"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do generates the request object and send the request object to the API endpoint
|
||||||
func (c *CreateWalletOrderRequest) Do(ctx context.Context) (*max.Order, error) {
|
func (c *CreateWalletOrderRequest) Do(ctx context.Context) (*max.Order, error) {
|
||||||
|
|
||||||
params, err := c.GetParameters()
|
params, err := c.GetParameters()
|
||||||
|
@ -244,7 +250,9 @@ func (c *CreateWalletOrderRequest) Do(ctx context.Context) (*max.Order, error) {
|
||||||
}
|
}
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
|
|
||||||
apiURL := "/api/v3/wallet/:walletType/order"
|
var apiURL string
|
||||||
|
|
||||||
|
apiURL = c.GetPath()
|
||||||
slugs, err := c.GetSlugsMap()
|
slugs, err := c.GetSlugsMap()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -263,8 +271,32 @@ func (c *CreateWalletOrderRequest) Do(ctx context.Context) (*max.Order, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiResponse max.Order
|
var apiResponse max.Order
|
||||||
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
|
return &apiResponse, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,13 +109,21 @@ func (g *GetMarginADRatioRequest) GetSlugsMap() (map[string]string, error) {
|
||||||
return slugs, nil
|
return slugs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPath returns the request path of the API
|
||||||
|
func (g *GetMarginADRatioRequest) GetPath() string {
|
||||||
|
return "/api/v3/wallet/m/ad_ratio"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do generates the request object and send the request object to the API endpoint
|
||||||
func (g *GetMarginADRatioRequest) Do(ctx context.Context) (*ADRatio, error) {
|
func (g *GetMarginADRatioRequest) Do(ctx context.Context) (*ADRatio, error) {
|
||||||
|
|
||||||
// no body params
|
// no body params
|
||||||
var params interface{}
|
var params interface{}
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
|
|
||||||
apiURL := "/api/v3/wallet/m/ad_ratio"
|
var apiURL string
|
||||||
|
|
||||||
|
apiURL = g.GetPath()
|
||||||
|
|
||||||
req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params)
|
req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -128,8 +136,32 @@ func (g *GetMarginADRatioRequest) Do(ctx context.Context) (*ADRatio, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiResponse ADRatio
|
var apiResponse ADRatio
|
||||||
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
|
return &apiResponse, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,6 +136,12 @@ func (g *GetOrderRequest) GetSlugsMap() (map[string]string, error) {
|
||||||
return slugs, nil
|
return slugs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPath returns the request path of the API
|
||||||
|
func (g *GetOrderRequest) GetPath() string {
|
||||||
|
return "/api/v3/order"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do generates the request object and send the request object to the API endpoint
|
||||||
func (g *GetOrderRequest) Do(ctx context.Context) (*max.Order, error) {
|
func (g *GetOrderRequest) Do(ctx context.Context) (*max.Order, error) {
|
||||||
|
|
||||||
// empty params for GET operation
|
// empty params for GET operation
|
||||||
|
@ -145,7 +151,9 @@ func (g *GetOrderRequest) Do(ctx context.Context) (*max.Order, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
apiURL := "/api/v3/order"
|
var apiURL string
|
||||||
|
|
||||||
|
apiURL = g.GetPath()
|
||||||
|
|
||||||
req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params)
|
req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -158,8 +166,32 @@ func (g *GetOrderRequest) Do(ctx context.Context) (*max.Order, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiResponse max.Order
|
var apiResponse max.Order
|
||||||
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
|
return &apiResponse, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,6 +135,12 @@ func (g *GetOrderTradesRequest) GetSlugsMap() (map[string]string, error) {
|
||||||
return slugs, nil
|
return slugs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPath returns the request path of the API
|
||||||
|
func (g *GetOrderTradesRequest) GetPath() string {
|
||||||
|
return "/api/v3/order/trades"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do generates the request object and send the request object to the API endpoint
|
||||||
func (g *GetOrderTradesRequest) Do(ctx context.Context) ([]Trade, error) {
|
func (g *GetOrderTradesRequest) Do(ctx context.Context) ([]Trade, error) {
|
||||||
|
|
||||||
// empty params for GET operation
|
// empty params for GET operation
|
||||||
|
@ -144,7 +150,9 @@ func (g *GetOrderTradesRequest) Do(ctx context.Context) ([]Trade, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
apiURL := "/api/v3/order/trades"
|
var apiURL string
|
||||||
|
|
||||||
|
apiURL = g.GetPath()
|
||||||
|
|
||||||
req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params)
|
req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -157,8 +165,32 @@ func (g *GetOrderTradesRequest) Do(ctx context.Context) ([]Trade, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiResponse []Trade
|
var apiResponse []Trade
|
||||||
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
|
return apiResponse, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ func (s *Client) NewGetWalletTradesRequest(walletType WalletType) *GetWalletTrad
|
||||||
return &GetWalletTradesRequest{client: s.Client, walletType: walletType}
|
return &GetWalletTradesRequest{client: s.Client, walletType: walletType}
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:generate GetRequest -url "/api/v3/wallet/:walletType/new/trades" -type GetWalletTradesRequest -responseType []Trade
|
//go:generate GetRequest -url "/api/v3/wallet/:walletType/trades" -type GetWalletTradesRequest -responseType []Trade
|
||||||
type GetWalletTradesRequest struct {
|
type GetWalletTradesRequest struct {
|
||||||
client requestgen.AuthenticatedAPIClient
|
client requestgen.AuthenticatedAPIClient
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by "requestgen -debug -method GET -url /api/v3/wallet/:walletType/new/trades -type GetWalletTradesRequest -responseType []"github.com/c9s/bbgo/pkg/exchange/max/maxapi/v3".Trade"; DO NOT EDIT.
|
// Code generated by "requestgen -debug -method GET -url /api/v3/wallet/:walletType/trades -type GetWalletTradesRequest -responseType []"github.com/c9s/bbgo/pkg/exchange/max/maxapi/v3".Trade"; DO NOT EDIT.
|
||||||
|
|
||||||
package v3
|
package v3
|
||||||
|
|
||||||
|
@ -216,7 +216,7 @@ func (g *GetWalletTradesRequest) Do(ctx context.Context) ([]Trade, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
apiURL := "/api/v3/wallet/:walletType/new/trades"
|
apiURL := "/api/v3/wallet/:walletType/trades"
|
||||||
slugs, err := g.GetSlugsMap()
|
slugs, err := g.GetSlugsMap()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,29 @@
|
||||||
|
package mysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/c9s/rockhopper/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
AddMigration("main", up_main_addPositionIndex, down_main_addPositionIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
func up_main_addPositionIndex(ctx context.Context, tx rockhopper.SQLExecutor) (err error) {
|
||||||
|
// This code is executed when the migration is applied.
|
||||||
|
_, err = tx.ExecContext(ctx, "CREATE INDEX positions_traded_at ON positions (traded_at, profit);")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func down_main_addPositionIndex(ctx context.Context, tx rockhopper.SQLExecutor) (err error) {
|
||||||
|
// This code is executed when the migration is rolled back.
|
||||||
|
_, err = tx.ExecContext(ctx, "DROP INDEX positions_traded_at ON positions;")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package sqlite3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/c9s/rockhopper/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
AddMigration("main", up_main_addPositionIndex, down_main_addPositionIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
func up_main_addPositionIndex(ctx context.Context, tx rockhopper.SQLExecutor) (err error) {
|
||||||
|
// This code is executed when the migration is applied.
|
||||||
|
_, err = tx.ExecContext(ctx, "CREATE INDEX positions_traded_at ON positions (traded_at, profit);")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func down_main_addPositionIndex(ctx context.Context, tx rockhopper.SQLExecutor) (err error) {
|
||||||
|
// This code is executed when the migration is rolled back.
|
||||||
|
_, err = tx.ExecContext(ctx, "DROP INDEX positions_traded_at;")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package priceresolver
|
package pricesolver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -9,8 +9,8 @@ import (
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SimplePriceResolver implements a map-structure-based price index
|
// SimplePriceSolver implements a map-structure-based price index
|
||||||
type SimplePriceResolver struct {
|
type SimplePriceSolver struct {
|
||||||
// symbolPrices stores the latest trade price by mapping symbol to price
|
// symbolPrices stores the latest trade price by mapping symbol to price
|
||||||
symbolPrices map[string]fixedpoint.Value
|
symbolPrices map[string]fixedpoint.Value
|
||||||
markets types.MarketMap
|
markets types.MarketMap
|
||||||
|
@ -28,8 +28,8 @@ type SimplePriceResolver struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSimplePriceResolver(markets types.MarketMap) *SimplePriceResolver {
|
func NewSimplePriceResolver(markets types.MarketMap) *SimplePriceSolver {
|
||||||
return &SimplePriceResolver{
|
return &SimplePriceSolver{
|
||||||
markets: markets,
|
markets: markets,
|
||||||
symbolPrices: make(map[string]fixedpoint.Value),
|
symbolPrices: make(map[string]fixedpoint.Value),
|
||||||
pricesByBase: make(map[string]map[string]fixedpoint.Value),
|
pricesByBase: make(map[string]map[string]fixedpoint.Value),
|
||||||
|
@ -37,7 +37,7 @@ func NewSimplePriceResolver(markets types.MarketMap) *SimplePriceResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *SimplePriceResolver) Update(symbol string, price fixedpoint.Value) {
|
func (m *SimplePriceSolver) Update(symbol string, price fixedpoint.Value) {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
@ -65,11 +65,11 @@ func (m *SimplePriceResolver) Update(symbol string, price fixedpoint.Value) {
|
||||||
baseMap[market.BaseCurrency] = price
|
baseMap[market.BaseCurrency] = price
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *SimplePriceResolver) UpdateFromTrade(trade types.Trade) {
|
func (m *SimplePriceSolver) UpdateFromTrade(trade types.Trade) {
|
||||||
m.Update(trade.Symbol, trade.Price)
|
m.Update(trade.Symbol, trade.Price)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *SimplePriceResolver) inferencePrice(asset string, assetPrice fixedpoint.Value, preferredFiats ...string) (fixedpoint.Value, bool) {
|
func (m *SimplePriceSolver) inferencePrice(asset string, assetPrice fixedpoint.Value, preferredFiats ...string) (fixedpoint.Value, bool) {
|
||||||
// log.Infof("inferencePrice %s = %f", asset, assetPrice.Float64())
|
// log.Infof("inferencePrice %s = %f", asset, assetPrice.Float64())
|
||||||
quotePrices, ok := m.pricesByBase[asset]
|
quotePrices, ok := m.pricesByBase[asset]
|
||||||
if ok {
|
if ok {
|
||||||
|
@ -112,7 +112,7 @@ func (m *SimplePriceResolver) inferencePrice(asset string, assetPrice fixedpoint
|
||||||
return fixedpoint.Zero, false
|
return fixedpoint.Zero, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *SimplePriceResolver) ResolvePrice(asset string, preferredFiats ...string) (fixedpoint.Value, bool) {
|
func (m *SimplePriceSolver) ResolvePrice(asset string, preferredFiats ...string) (fixedpoint.Value, bool) {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
return m.inferencePrice(asset, fixedpoint.One, preferredFiats...)
|
return m.inferencePrice(asset, fixedpoint.One, preferredFiats...)
|
|
@ -1,4 +1,4 @@
|
||||||
package priceresolver
|
package pricesolver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
|
@ -75,6 +75,8 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type BasicCircuitBreaker struct {
|
type BasicCircuitBreaker struct {
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
MaximumConsecutiveTotalLoss fixedpoint.Value `json:"maximumConsecutiveTotalLoss"`
|
MaximumConsecutiveTotalLoss fixedpoint.Value `json:"maximumConsecutiveTotalLoss"`
|
||||||
|
|
||||||
MaximumConsecutiveLossTimes int `json:"maximumConsecutiveLossTimes"`
|
MaximumConsecutiveLossTimes int `json:"maximumConsecutiveLossTimes"`
|
||||||
|
@ -116,15 +118,20 @@ type BasicCircuitBreaker struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBasicCircuitBreaker(strategyID, strategyInstance string) *BasicCircuitBreaker {
|
func NewBasicCircuitBreaker(strategyID, strategyInstance string) *BasicCircuitBreaker {
|
||||||
return &BasicCircuitBreaker{
|
b := &BasicCircuitBreaker{
|
||||||
|
Enabled: true,
|
||||||
MaximumConsecutiveLossTimes: 8,
|
MaximumConsecutiveLossTimes: 8,
|
||||||
MaximumHaltTimes: 3,
|
MaximumHaltTimes: 3,
|
||||||
MaximumHaltTimesExceededPanic: false,
|
MaximumHaltTimesExceededPanic: false,
|
||||||
HaltDuration: types.Duration(30 * time.Minute),
|
|
||||||
strategyID: strategyID,
|
HaltDuration: types.Duration(1 * time.Hour),
|
||||||
strategyInstance: strategyInstance,
|
strategyID: strategyID,
|
||||||
metricsLabels: prometheus.Labels{"strategy": strategyID, "strategyInstance": strategyInstance},
|
strategyInstance: strategyInstance,
|
||||||
|
metricsLabels: prometheus.Labels{"strategy": strategyID, "strategyInstance": strategyInstance},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.updateMetrics()
|
||||||
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BasicCircuitBreaker) getMetricsLabels() prometheus.Labels {
|
func (b *BasicCircuitBreaker) getMetricsLabels() prometheus.Labels {
|
||||||
|
@ -180,7 +187,7 @@ func (b *BasicCircuitBreaker) RecordProfit(profit fixedpoint.Value, now time.Tim
|
||||||
b.winRatio = float64(b.winTimes) / float64(b.lossTimes)
|
b.winRatio = float64(b.winTimes) / float64(b.lossTimes)
|
||||||
}
|
}
|
||||||
|
|
||||||
b.updateMetrics()
|
defer b.updateMetrics()
|
||||||
|
|
||||||
if b.MaximumConsecutiveLossTimes > 0 && b.consecutiveLossTimes >= b.MaximumConsecutiveLossTimes {
|
if b.MaximumConsecutiveLossTimes > 0 && b.consecutiveLossTimes >= b.MaximumConsecutiveLossTimes {
|
||||||
b.halt(now, "exceeded MaximumConsecutiveLossTimes")
|
b.halt(now, "exceeded MaximumConsecutiveLossTimes")
|
||||||
|
@ -221,21 +228,25 @@ func (b *BasicCircuitBreaker) reset() {
|
||||||
b.updateMetrics()
|
b.updateMetrics()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BasicCircuitBreaker) IsHalted(now time.Time) bool {
|
func (b *BasicCircuitBreaker) IsHalted(now time.Time) (string, bool) {
|
||||||
|
if !b.Enabled {
|
||||||
|
return "disabled", false
|
||||||
|
}
|
||||||
|
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
defer b.mu.Unlock()
|
defer b.mu.Unlock()
|
||||||
|
|
||||||
if !b.halted {
|
if !b.halted {
|
||||||
return false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if it's an expired halt
|
// check if it's an expired halt
|
||||||
if now.After(b.haltTo) {
|
if now.After(b.haltTo) {
|
||||||
b.reset()
|
b.reset()
|
||||||
return false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return b.haltReason, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BasicCircuitBreaker) halt(now time.Time, reason string) {
|
func (b *BasicCircuitBreaker) halt(now time.Time, reason string) {
|
||||||
|
@ -249,6 +260,8 @@ func (b *BasicCircuitBreaker) halt(now time.Time, reason string) {
|
||||||
haltCounterMetrics.With(labels).Set(float64(b.haltCounter))
|
haltCounterMetrics.With(labels).Set(float64(b.haltCounter))
|
||||||
haltMetrics.With(labels).Set(1.0)
|
haltMetrics.With(labels).Set(1.0)
|
||||||
|
|
||||||
|
defer b.updateMetrics()
|
||||||
|
|
||||||
if b.MaximumHaltTimesExceededPanic && b.haltCounter > b.MaximumHaltTimes {
|
if b.MaximumHaltTimesExceededPanic && b.haltCounter > b.MaximumHaltTimes {
|
||||||
panic(fmt.Errorf("total %d halt times > maximumHaltTimesExceededPanic %d", b.haltCounter, b.MaximumHaltTimes))
|
panic(fmt.Errorf("total %d halt times > maximumHaltTimesExceededPanic %d", b.haltCounter, b.MaximumHaltTimes))
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ func Test_ModifiedQuantity(t *testing.T) {
|
||||||
BaseCurrency: "BTC",
|
BaseCurrency: "BTC",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
orderExecutor := bbgo.NewGeneralOrderExecutor(nil, "BTCUSDT", "strategy", "strategy-1", pos)
|
orderExecutor := bbgo.NewGeneralOrderExecutor(&bbgo.ExchangeSession{}, "BTCUSDT", "strategy", "strategy-1", pos)
|
||||||
riskControl := NewPositionRiskControl(orderExecutor, fixedpoint.NewFromInt(10), fixedpoint.NewFromInt(2))
|
riskControl := NewPositionRiskControl(orderExecutor, fixedpoint.NewFromInt(10), fixedpoint.NewFromInt(2))
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package audacitymaker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/bbgo"
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
"github.com/c9s/bbgo/pkg/datatype/floats"
|
"github.com/c9s/bbgo/pkg/datatype/floats"
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
|
@ -38,7 +39,7 @@ func (s *PerTrade) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Gener
|
||||||
position := orderExecutor.Position()
|
position := orderExecutor.Position()
|
||||||
symbol := position.Symbol
|
symbol := position.Symbol
|
||||||
// ger best bid/ask, not used yet
|
// ger best bid/ask, not used yet
|
||||||
s.StreamBook = types.NewStreamBook(symbol)
|
s.StreamBook = types.NewStreamBook(symbol, session.ExchangeName)
|
||||||
s.StreamBook.BindStream(session.MarketDataStream)
|
s.StreamBook.BindStream(session.MarketDataStream)
|
||||||
|
|
||||||
// use queue to do time-series rolling
|
// use queue to do time-series rolling
|
||||||
|
@ -59,7 +60,7 @@ func (s *PerTrade) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Gener
|
||||||
|
|
||||||
session.MarketDataStream.OnMarketTrade(func(trade types.Trade) {
|
session.MarketDataStream.OnMarketTrade(func(trade types.Trade) {
|
||||||
|
|
||||||
//log.Infof("%s trade @ %f", trade.Side, trade.Price.Float64())
|
// log.Infof("%s trade @ %f", trade.Side, trade.Price.Float64())
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
|
@ -80,10 +81,10 @@ func (s *PerTrade) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Gener
|
||||||
sellTradesNumber.Update(1)
|
sellTradesNumber.Update(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
//canceled := s.orderExecutor.GracefulCancel(ctx)
|
// canceled := s.orderExecutor.GracefulCancel(ctx)
|
||||||
//if canceled != nil {
|
// if canceled != nil {
|
||||||
// _ = s.orderExecutor.GracefulCancel(ctx)
|
// _ = s.orderExecutor.GracefulCancel(ctx)
|
||||||
//}
|
// }
|
||||||
|
|
||||||
sizeFraction := buyTradeSize.Sum() / sellTradeSize.Sum()
|
sizeFraction := buyTradeSize.Sum() / sellTradeSize.Sum()
|
||||||
numberFraction := buyTradesNumber.Sum() / sellTradesNumber.Sum()
|
numberFraction := buyTradesNumber.Sum() / sellTradesNumber.Sum()
|
||||||
|
@ -112,15 +113,15 @@ func (s *PerTrade) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Gener
|
||||||
if outlier(orderFlowSizeMinMax.Tail(100), threshold) > 0 && outlier(orderFlowNumberMinMax.Tail(100), threshold) > 0 {
|
if outlier(orderFlowSizeMinMax.Tail(100), threshold) > 0 && outlier(orderFlowNumberMinMax.Tail(100), threshold) > 0 {
|
||||||
_ = s.orderExecutor.GracefulCancel(ctx)
|
_ = s.orderExecutor.GracefulCancel(ctx)
|
||||||
log.Infof("long!!")
|
log.Infof("long!!")
|
||||||
//_ = s.placeTrade(ctx, types.SideTypeBuy, s.Quantity, symbol)
|
// _ = s.placeTrade(ctx, types.SideTypeBuy, s.Quantity, symbol)
|
||||||
_ = s.placeOrder(ctx, types.SideTypeBuy, s.Quantity, bid.Price, symbol)
|
_ = s.placeOrder(ctx, types.SideTypeBuy, s.Quantity, bid.Price, symbol)
|
||||||
//_ = s.placeOrder(ctx, types.SideTypeSell, s.Quantity, ask.Price.Mul(fixedpoint.NewFromFloat(1.0005)), symbol)
|
// _ = s.placeOrder(ctx, types.SideTypeSell, s.Quantity, ask.Price.Mul(fixedpoint.NewFromFloat(1.0005)), symbol)
|
||||||
} else if outlier(orderFlowSizeMinMax.Tail(100), threshold) < 0 && outlier(orderFlowNumberMinMax.Tail(100), threshold) < 0 {
|
} else if outlier(orderFlowSizeMinMax.Tail(100), threshold) < 0 && outlier(orderFlowNumberMinMax.Tail(100), threshold) < 0 {
|
||||||
_ = s.orderExecutor.GracefulCancel(ctx)
|
_ = s.orderExecutor.GracefulCancel(ctx)
|
||||||
log.Infof("short!!")
|
log.Infof("short!!")
|
||||||
//_ = s.placeTrade(ctx, types.SideTypeSell, s.Quantity, symbol)
|
// _ = s.placeTrade(ctx, types.SideTypeSell, s.Quantity, symbol)
|
||||||
_ = s.placeOrder(ctx, types.SideTypeSell, s.Quantity, ask.Price, symbol)
|
_ = s.placeOrder(ctx, types.SideTypeSell, s.Quantity, ask.Price, symbol)
|
||||||
//_ = s.placeOrder(ctx, types.SideTypeBuy, s.Quantity, bid.Price.Mul(fixedpoint.NewFromFloat(0.9995)), symbol)
|
// _ = s.placeOrder(ctx, types.SideTypeBuy, s.Quantity, bid.Price.Mul(fixedpoint.NewFromFloat(0.9995)), symbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +139,9 @@ func (s *PerTrade) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Gener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PerTrade) placeOrder(ctx context.Context, side types.SideType, quantity fixedpoint.Value, price fixedpoint.Value, symbol string) error {
|
func (s *PerTrade) placeOrder(
|
||||||
|
ctx context.Context, side types.SideType, quantity fixedpoint.Value, price fixedpoint.Value, symbol string,
|
||||||
|
) error {
|
||||||
market, _ := s.session.Market(symbol)
|
market, _ := s.session.Market(symbol)
|
||||||
_, err := s.orderExecutor.SubmitOrders(ctx, types.SubmitOrder{
|
_, err := s.orderExecutor.SubmitOrders(ctx, types.SubmitOrder{
|
||||||
Symbol: symbol,
|
Symbol: symbol,
|
||||||
|
|
|
@ -5,13 +5,14 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/robfig/cron/v3"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/bbgo"
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
indicatorv2 "github.com/c9s/bbgo/pkg/indicator/v2"
|
indicatorv2 "github.com/c9s/bbgo/pkg/indicator/v2"
|
||||||
"github.com/c9s/bbgo/pkg/strategy/common"
|
"github.com/c9s/bbgo/pkg/strategy/common"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
"github.com/robfig/cron/v3"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const ID = "autobuy"
|
const ID = "autobuy"
|
||||||
|
@ -31,6 +32,7 @@ type Strategy struct {
|
||||||
Symbol string `json:"symbol"`
|
Symbol string `json:"symbol"`
|
||||||
Schedule string `json:"schedule"`
|
Schedule string `json:"schedule"`
|
||||||
MinBaseBalance fixedpoint.Value `json:"minBaseBalance"`
|
MinBaseBalance fixedpoint.Value `json:"minBaseBalance"`
|
||||||
|
OrderType types.OrderType `json:"orderType"`
|
||||||
PriceType types.PriceType `json:"priceType"`
|
PriceType types.PriceType `json:"priceType"`
|
||||||
Bollinger *types.BollingerSetting `json:"bollinger"`
|
Bollinger *types.BollingerSetting `json:"bollinger"`
|
||||||
DryRun bool `json:"dryRun"`
|
DryRun bool `json:"dryRun"`
|
||||||
|
@ -64,13 +66,39 @@ func (s *Strategy) InstanceID() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) Validate() error {
|
func (s *Strategy) Validate() error {
|
||||||
|
if s.Symbol == "" {
|
||||||
|
return fmt.Errorf("symbol is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Schedule == "" {
|
||||||
|
return fmt.Errorf("schedule is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.MinBaseBalance.Sign() <= 0 {
|
||||||
|
return fmt.Errorf("minBaseBalance must be greater than 0")
|
||||||
|
}
|
||||||
|
|
||||||
if err := s.QuantityOrAmount.Validate(); err != nil {
|
if err := s.QuantityOrAmount.Validate(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.Bollinger != nil {
|
||||||
|
if s.Bollinger.Interval == "" {
|
||||||
|
return fmt.Errorf("bollinger interval is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Bollinger.BandWidth <= 0 {
|
||||||
|
return fmt.Errorf("bollinger band width must be greater than 0")
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) Defaults() error {
|
func (s *Strategy) Defaults() error {
|
||||||
|
if s.OrderType == "" {
|
||||||
|
s.OrderType = types.OrderTypeLimit
|
||||||
|
}
|
||||||
|
|
||||||
if s.PriceType == "" {
|
if s.PriceType == "" {
|
||||||
s.PriceType = types.PriceTypeMaker
|
s.PriceType = types.PriceTypeMaker
|
||||||
}
|
}
|
||||||
|
@ -78,13 +106,17 @@ func (s *Strategy) Defaults() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) {
|
func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) {
|
||||||
session.Subscribe(types.KLineChannel, s.Symbol, types.SubscribeOptions{Interval: s.Bollinger.Interval})
|
if s.Bollinger != nil {
|
||||||
|
session.Subscribe(types.KLineChannel, s.Symbol, types.SubscribeOptions{Interval: s.Bollinger.Interval})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
|
func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
|
||||||
s.Strategy.Initialize(ctx, s.Environment, session, s.Market, ID, s.InstanceID())
|
s.Strategy.Initialize(ctx, s.Environment, session, s.Market, ID, s.InstanceID())
|
||||||
|
|
||||||
s.boll = session.Indicators(s.Symbol).BOLL(s.Bollinger.IntervalWindow, s.Bollinger.BandWidth)
|
if s.Bollinger != nil {
|
||||||
|
s.boll = session.Indicators(s.Symbol).BOLL(s.Bollinger.IntervalWindow, s.Bollinger.BandWidth)
|
||||||
|
}
|
||||||
|
|
||||||
s.OrderExecutor.ActiveMakerOrders().OnFilled(func(order types.Order) {
|
s.OrderExecutor.ActiveMakerOrders().OnFilled(func(order types.Order) {
|
||||||
s.autobuy(ctx)
|
s.autobuy(ctx)
|
||||||
|
@ -128,9 +160,9 @@ func (s *Strategy) autobuy(ctx context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
side := types.SideTypeBuy
|
side := types.SideTypeBuy
|
||||||
price := s.PriceType.Map(ticker, side)
|
price := s.PriceType.GetPrice(ticker, side)
|
||||||
|
|
||||||
if price.Float64() > s.boll.UpBand.Last(0) {
|
if s.boll != nil && price.Float64() > s.boll.UpBand.Last(0) {
|
||||||
log.Infof("price %s is higher than upper band %f, skip", price.String(), s.boll.UpBand.Last(0))
|
log.Infof("price %s is higher than upper band %f, skip", price.String(), s.boll.UpBand.Last(0))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -145,7 +177,7 @@ func (s *Strategy) autobuy(ctx context.Context) {
|
||||||
submitOrder := types.SubmitOrder{
|
submitOrder := types.SubmitOrder{
|
||||||
Symbol: s.Symbol,
|
Symbol: s.Symbol,
|
||||||
Side: side,
|
Side: side,
|
||||||
Type: types.OrderTypeLimitMaker,
|
Type: s.OrderType,
|
||||||
Quantity: quantity,
|
Quantity: quantity,
|
||||||
Price: price,
|
Price: price,
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ type Strategy struct {
|
||||||
// boll is the BOLLINGER indicator we used for predicting the price.
|
// boll is the BOLLINGER indicator we used for predicting the price.
|
||||||
boll *indicator.BOLL
|
boll *indicator.BOLL
|
||||||
|
|
||||||
CancelProfitOrdersOnShutdown bool `json: "shutdownCancelProfitOrders"`
|
CancelProfitOrdersOnShutdown bool `json:"shutdownCancelProfitOrders"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) ID() string {
|
func (s *Strategy) ID() string {
|
||||||
|
|
|
@ -6,9 +6,10 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/bbgo"
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func generateTestOrder(side types.SideType, status types.OrderStatus, createdAt time.Time) types.Order {
|
func generateTestOrder(side types.SideType, status types.OrderStatus, createdAt time.Time) types.Order {
|
||||||
|
@ -29,7 +30,7 @@ func Test_RecoverState(t *testing.T) {
|
||||||
t.Run("new strategy", func(t *testing.T) {
|
t.Run("new strategy", func(t *testing.T) {
|
||||||
currentRound := Round{}
|
currentRound := Round{}
|
||||||
position := types.NewPositionFromMarket(strategy.Market)
|
position := types.NewPositionFromMarket(strategy.Market)
|
||||||
orderExecutor := bbgo.NewGeneralOrderExecutor(nil, strategy.Symbol, ID, "", position)
|
orderExecutor := bbgo.NewGeneralOrderExecutor(&bbgo.ExchangeSession{}, strategy.Symbol, ID, "", position)
|
||||||
state, err := recoverState(context.Background(), 5, currentRound, orderExecutor)
|
state, err := recoverState(context.Background(), 5, currentRound, orderExecutor)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, WaitToOpenPosition, state)
|
assert.Equal(t, WaitToOpenPosition, state)
|
||||||
|
@ -47,7 +48,7 @@ func Test_RecoverState(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
position := types.NewPositionFromMarket(strategy.Market)
|
position := types.NewPositionFromMarket(strategy.Market)
|
||||||
orderExecutor := bbgo.NewGeneralOrderExecutor(nil, strategy.Symbol, ID, "", position)
|
orderExecutor := bbgo.NewGeneralOrderExecutor(&bbgo.ExchangeSession{}, strategy.Symbol, ID, "", position)
|
||||||
state, err := recoverState(context.Background(), 5, currentRound, orderExecutor)
|
state, err := recoverState(context.Background(), 5, currentRound, orderExecutor)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, OpenPositionReady, state)
|
assert.Equal(t, OpenPositionReady, state)
|
||||||
|
@ -65,7 +66,7 @@ func Test_RecoverState(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
position := types.NewPositionFromMarket(strategy.Market)
|
position := types.NewPositionFromMarket(strategy.Market)
|
||||||
orderExecutor := bbgo.NewGeneralOrderExecutor(nil, strategy.Symbol, ID, "", position)
|
orderExecutor := bbgo.NewGeneralOrderExecutor(&bbgo.ExchangeSession{}, strategy.Symbol, ID, "", position)
|
||||||
state, err := recoverState(context.Background(), 5, currentRound, orderExecutor)
|
state, err := recoverState(context.Background(), 5, currentRound, orderExecutor)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, OpenPositionOrderFilled, state)
|
assert.Equal(t, OpenPositionOrderFilled, state)
|
||||||
|
@ -83,7 +84,7 @@ func Test_RecoverState(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
position := types.NewPositionFromMarket(strategy.Market)
|
position := types.NewPositionFromMarket(strategy.Market)
|
||||||
orderExecutor := bbgo.NewGeneralOrderExecutor(nil, strategy.Symbol, ID, "", position)
|
orderExecutor := bbgo.NewGeneralOrderExecutor(&bbgo.ExchangeSession{}, strategy.Symbol, ID, "", position)
|
||||||
state, err := recoverState(context.Background(), 5, currentRound, orderExecutor)
|
state, err := recoverState(context.Background(), 5, currentRound, orderExecutor)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, OpenPositionOrdersCancelling, state)
|
assert.Equal(t, OpenPositionOrdersCancelling, state)
|
||||||
|
@ -101,7 +102,7 @@ func Test_RecoverState(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
position := types.NewPositionFromMarket(strategy.Market)
|
position := types.NewPositionFromMarket(strategy.Market)
|
||||||
orderExecutor := bbgo.NewGeneralOrderExecutor(nil, strategy.Symbol, ID, "", position)
|
orderExecutor := bbgo.NewGeneralOrderExecutor(&bbgo.ExchangeSession{}, strategy.Symbol, ID, "", position)
|
||||||
state, err := recoverState(context.Background(), 5, currentRound, orderExecutor)
|
state, err := recoverState(context.Background(), 5, currentRound, orderExecutor)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, OpenPositionOrdersCancelling, state)
|
assert.Equal(t, OpenPositionOrdersCancelling, state)
|
||||||
|
@ -122,7 +123,7 @@ func Test_RecoverState(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
position := types.NewPositionFromMarket(strategy.Market)
|
position := types.NewPositionFromMarket(strategy.Market)
|
||||||
orderExecutor := bbgo.NewGeneralOrderExecutor(nil, strategy.Symbol, ID, "", position)
|
orderExecutor := bbgo.NewGeneralOrderExecutor(&bbgo.ExchangeSession{}, strategy.Symbol, ID, "", position)
|
||||||
state, err := recoverState(context.Background(), 5, currentRound, orderExecutor)
|
state, err := recoverState(context.Background(), 5, currentRound, orderExecutor)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, TakeProfitReady, state)
|
assert.Equal(t, TakeProfitReady, state)
|
||||||
|
@ -143,7 +144,7 @@ func Test_RecoverState(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
position := types.NewPositionFromMarket(strategy.Market)
|
position := types.NewPositionFromMarket(strategy.Market)
|
||||||
orderExecutor := bbgo.NewGeneralOrderExecutor(nil, strategy.Symbol, ID, "", position)
|
orderExecutor := bbgo.NewGeneralOrderExecutor(&bbgo.ExchangeSession{}, strategy.Symbol, ID, "", position)
|
||||||
state, err := recoverState(context.Background(), 5, currentRound, orderExecutor)
|
state, err := recoverState(context.Background(), 5, currentRound, orderExecutor)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, WaitToOpenPosition, state)
|
assert.Equal(t, WaitToOpenPosition, state)
|
||||||
|
|
|
@ -27,6 +27,10 @@ func (s *Strategy) placeTakeProfitOrders(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
roundPosition := types.NewPositionFromMarket(s.Market)
|
roundPosition := types.NewPositionFromMarket(s.Market)
|
||||||
|
roundPosition.SetExchangeFeeRate(s.ExchangeSession.ExchangeName, types.ExchangeFee{
|
||||||
|
MakerFeeRate: s.ExchangeSession.MakerFeeRate,
|
||||||
|
TakerFeeRate: s.ExchangeSession.TakerFeeRate,
|
||||||
|
})
|
||||||
|
|
||||||
for _, trade := range trades {
|
for _, trade := range trades {
|
||||||
s.logger.Infof("add trade into the position of this round %s", trade.String())
|
s.logger.Infof("add trade into the position of this round %s", trade.String())
|
||||||
|
|
|
@ -236,7 +236,7 @@ func (s *Strategy) scanDepositHistory(ctx context.Context, asset string, duratio
|
||||||
s.watchingDeposits[deposit.TransactionID] = deposit
|
s.watchingDeposits[deposit.TransactionID] = deposit
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// ignore all initial deposit history that are already success
|
// ignore all initial deposits that are already in success status
|
||||||
logger.Infof("ignored succeess deposit: %s %+v", deposit.TransactionID, deposit)
|
logger.Infof("ignored succeess deposit: %s %+v", deposit.TransactionID, deposit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -854,12 +854,12 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
s.highestPrice = 0
|
s.highestPrice = 0
|
||||||
s.lowestPrice = 0
|
s.lowestPrice = 0
|
||||||
} else if s.Position.IsLong() {
|
} else if s.Position.IsLong() {
|
||||||
s.buyPrice = s.Position.ApproximateAverageCost.Float64()
|
s.buyPrice = s.Position.AverageCost.Float64()
|
||||||
s.sellPrice = 0
|
s.sellPrice = 0
|
||||||
s.highestPrice = math.Max(s.buyPrice, s.highestPrice)
|
s.highestPrice = math.Max(s.buyPrice, s.highestPrice)
|
||||||
s.lowestPrice = s.buyPrice
|
s.lowestPrice = s.buyPrice
|
||||||
} else if s.Position.IsShort() {
|
} else if s.Position.IsShort() {
|
||||||
s.sellPrice = s.Position.ApproximateAverageCost.Float64()
|
s.sellPrice = s.Position.AverageCost.Float64()
|
||||||
s.buyPrice = 0
|
s.buyPrice = 0
|
||||||
s.highestPrice = s.sellPrice
|
s.highestPrice = s.sellPrice
|
||||||
if s.lowestPrice == 0 {
|
if s.lowestPrice == 0 {
|
||||||
|
|
|
@ -354,12 +354,12 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
s.highestPrice = 0
|
s.highestPrice = 0
|
||||||
s.lowestPrice = 0
|
s.lowestPrice = 0
|
||||||
} else if s.Position.IsLong() {
|
} else if s.Position.IsLong() {
|
||||||
s.buyPrice = s.Position.ApproximateAverageCost.Float64()
|
s.buyPrice = s.Position.AverageCost.Float64()
|
||||||
s.sellPrice = 0
|
s.sellPrice = 0
|
||||||
s.highestPrice = math.Max(s.buyPrice, s.highestPrice)
|
s.highestPrice = math.Max(s.buyPrice, s.highestPrice)
|
||||||
s.lowestPrice = 0
|
s.lowestPrice = 0
|
||||||
} else {
|
} else {
|
||||||
s.sellPrice = s.Position.ApproximateAverageCost.Float64()
|
s.sellPrice = s.Position.AverageCost.Float64()
|
||||||
s.buyPrice = 0
|
s.buyPrice = 0
|
||||||
s.highestPrice = 0
|
s.highestPrice = 0
|
||||||
if s.lowestPrice == 0 {
|
if s.lowestPrice == 0 {
|
||||||
|
|
|
@ -440,9 +440,9 @@ for t in 1 .. n:
|
||||||
return argmax(alpha[t,si] over si)
|
return argmax(alpha[t,si] over si)
|
||||||
*/
|
*/
|
||||||
func hmm(y_t []float64, x_t []float64, l int) float64 {
|
func hmm(y_t []float64, x_t []float64, l int) float64 {
|
||||||
al := make([]float64, l)
|
al := make([]float64, 0, l)
|
||||||
an := make([]float64, l)
|
an := make([]float64, 0, l)
|
||||||
as := make([]float64, l)
|
as := make([]float64, 0, l)
|
||||||
long := 0.
|
long := 0.
|
||||||
neut := 0.
|
neut := 0.
|
||||||
short := 0.
|
short := 0.
|
||||||
|
@ -453,9 +453,9 @@ func hmm(y_t []float64, x_t []float64, l int) float64 {
|
||||||
sin := make([]float64, 3)
|
sin := make([]float64, 3)
|
||||||
sis := make([]float64, 3)
|
sis := make([]float64, 3)
|
||||||
for i := -1; i <= 1; i++ {
|
for i := -1; i <= 1; i++ {
|
||||||
sil = append(sil, x_t[n-1-1]*transitProbability(i, j))
|
sil = append(sil, 0, x_t[n-1-1]*transitProbability(i, j))
|
||||||
sin = append(sin, x_t[n-1-1]*transitProbability(i, j))
|
sin = append(sin, 0, x_t[n-1-1]*transitProbability(i, j))
|
||||||
sis = append(sis, x_t[n-1-1]*transitProbability(i, j))
|
sis = append(sis, 0, x_t[n-1-1]*transitProbability(i, j))
|
||||||
}
|
}
|
||||||
if j > 0 {
|
if j > 0 {
|
||||||
_, longArr := floats.MinMax(sil, 3)
|
_, longArr := floats.MinMax(sil, 3)
|
||||||
|
|
|
@ -262,7 +262,7 @@ func (s *Strategy) generateOrder(ctx context.Context) (*types.SubmitOrder, error
|
||||||
}
|
}
|
||||||
quantity = market.RoundDownQuantityByPrecision(quantity)
|
quantity = market.RoundDownQuantityByPrecision(quantity)
|
||||||
|
|
||||||
price := s.PriceType.Map(ticker, side)
|
price := s.PriceType.GetPrice(ticker, side)
|
||||||
|
|
||||||
if s.MaxAmount.Float64() > 0 {
|
if s.MaxAmount.Float64() > 0 {
|
||||||
quantity = bbgo.AdjustQuantityByMaxAmount(quantity, price, s.MaxAmount)
|
quantity = bbgo.AdjustQuantityByMaxAmount(quantity, price, s.MaxAmount)
|
||||||
|
|
|
@ -98,7 +98,7 @@ func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) {
|
||||||
func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
|
func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
|
||||||
s.Strategy.Initialize(ctx, s.Environment, session, s.Market, ID, s.InstanceID())
|
s.Strategy.Initialize(ctx, s.Environment, session, s.Market, ID, s.InstanceID())
|
||||||
|
|
||||||
s.book = types.NewStreamBook(s.Symbol)
|
s.book = types.NewStreamBook(s.Symbol, session.Exchange.Name())
|
||||||
s.book.BindStream(session.MarketDataStream)
|
s.book.BindStream(session.MarketDataStream)
|
||||||
|
|
||||||
s.liquidityOrderBook = bbgo.NewActiveOrderBook(s.Symbol)
|
s.liquidityOrderBook = bbgo.NewActiveOrderBook(s.Symbol)
|
||||||
|
|
|
@ -513,7 +513,9 @@ func notifyUsdPnL(profit fixedpoint.Value) {
|
||||||
bbgo.Notify(title)
|
bbgo.Notify(title)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) iocOrderExecution(ctx context.Context, session *bbgo.ExchangeSession, orders [3]types.SubmitOrder, ratio float64) (types.OrderSlice, error) {
|
func (s *Strategy) iocOrderExecution(
|
||||||
|
ctx context.Context, session *bbgo.ExchangeSession, orders [3]types.SubmitOrder, ratio float64,
|
||||||
|
) (types.OrderSlice, error) {
|
||||||
service, ok := session.Exchange.(types.ExchangeOrderQueryService)
|
service, ok := session.Exchange.(types.ExchangeOrderQueryService)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("exchange does not support ExchangeOrderQueryService")
|
return nil, errors.New("exchange does not support ExchangeOrderQueryService")
|
||||||
|
@ -700,7 +702,9 @@ func (s *Strategy) waitWebSocketOrderDone(ctx context.Context, orderID uint64, t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) waitOrdersAndCollectTrades(ctx context.Context, service types.ExchangeOrderQueryService, createdOrders types.OrderSlice) (map[uint64][]types.Trade, types.OrderSlice, error) {
|
func (s *Strategy) waitOrdersAndCollectTrades(
|
||||||
|
ctx context.Context, service types.ExchangeOrderQueryService, createdOrders types.OrderSlice,
|
||||||
|
) (map[uint64][]types.Trade, types.OrderSlice, error) {
|
||||||
var err error
|
var err error
|
||||||
var orderTrades = make(map[uint64][]types.Trade)
|
var orderTrades = make(map[uint64][]types.Trade)
|
||||||
var updatedOrders types.OrderSlice
|
var updatedOrders types.OrderSlice
|
||||||
|
@ -763,7 +767,9 @@ func (s *Strategy) analyzeOrders(orders types.OrderSlice) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) buildArbMarkets(session *bbgo.ExchangeSession, symbols []string, separateStream bool, sigC sigchan.Chan) (map[string]*ArbMarket, error) {
|
func (s *Strategy) buildArbMarkets(
|
||||||
|
session *bbgo.ExchangeSession, symbols []string, separateStream bool, sigC sigchan.Chan,
|
||||||
|
) (map[string]*ArbMarket, error) {
|
||||||
markets := make(map[string]*ArbMarket)
|
markets := make(map[string]*ArbMarket)
|
||||||
// build market object
|
// build market object
|
||||||
for _, symbol := range symbols {
|
for _, symbol := range symbols {
|
||||||
|
@ -790,7 +796,7 @@ func (s *Strategy) buildArbMarkets(session *bbgo.ExchangeSession, symbols []stri
|
||||||
Speed: types.SpeedHigh,
|
Speed: types.SpeedHigh,
|
||||||
})
|
})
|
||||||
|
|
||||||
book := types.NewStreamBook(symbol)
|
book := types.NewStreamBook(symbol, session.ExchangeName)
|
||||||
priceUpdater := func(_ types.SliceOrderBook) {
|
priceUpdater := func(_ types.SliceOrderBook) {
|
||||||
bestBid, bestAsk, _ := book.BestBidAndAsk()
|
bestBid, bestAsk, _ := book.BestBidAndAsk()
|
||||||
if bestAsk.Equals(m.bestAsk) && bestBid.Equals(m.bestBid) {
|
if bestAsk.Equals(m.bestAsk) && bestBid.Equals(m.bestBid) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
"github.com/c9s/bbgo/pkg/bbgo"
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
"github.com/c9s/bbgo/pkg/core"
|
"github.com/c9s/bbgo/pkg/core"
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
"github.com/c9s/bbgo/pkg/priceresolver"
|
"github.com/c9s/bbgo/pkg/pricesolver"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ type Strategy struct {
|
||||||
|
|
||||||
faultBalanceRecords map[string][]TimeBalance
|
faultBalanceRecords map[string][]TimeBalance
|
||||||
|
|
||||||
priceResolver *priceresolver.SimplePriceResolver
|
priceResolver *pricesolver.SimplePriceSolver
|
||||||
|
|
||||||
sessions map[string]*bbgo.ExchangeSession
|
sessions map[string]*bbgo.ExchangeSession
|
||||||
orderBooks map[string]*bbgo.ActiveOrderBook
|
orderBooks map[string]*bbgo.ActiveOrderBook
|
||||||
|
@ -372,7 +372,7 @@ func (s *Strategy) CrossRun(ctx context.Context, _ bbgo.OrderExecutionRouter, se
|
||||||
// session.Market(symbol)
|
// session.Market(symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.priceResolver = priceresolver.NewSimplePriceResolver(markets)
|
s.priceResolver = pricesolver.NewSimplePriceResolver(markets)
|
||||||
|
|
||||||
bbgo.OnShutdown(ctx, func(ctx context.Context, wg *sync.WaitGroup) {
|
bbgo.OnShutdown(ctx, func(ctx context.Context, wg *sync.WaitGroup) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
|
@ -393,7 +393,7 @@ func (s *Strategy) CrossRun(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.pricingBook = types.NewStreamBook(s.HedgeSymbol)
|
s.pricingBook = types.NewStreamBook(s.HedgeSymbol, s.hedgeSession.ExchangeName)
|
||||||
s.pricingBook.BindStream(s.hedgeSession.MarketDataStream)
|
s.pricingBook.BindStream(s.hedgeSession.MarketDataStream)
|
||||||
|
|
||||||
s.stopC = make(chan struct{})
|
s.stopC = make(chan struct{})
|
||||||
|
|
|
@ -44,7 +44,7 @@ func TestStrategy_generateMakerOrders(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pricingBook := types.NewStreamBook("BTCUSDT")
|
pricingBook := types.NewStreamBook("BTCUSDT", types.ExchangeBinance)
|
||||||
pricingBook.Load(types.SliceOrderBook{
|
pricingBook.Load(types.SliceOrderBook{
|
||||||
Symbol: "BTCUSDT",
|
Symbol: "BTCUSDT",
|
||||||
Bids: types.PriceVolumeSlice{
|
Bids: types.PriceVolumeSlice{
|
||||||
|
|
|
@ -153,11 +153,11 @@ func (s *Strategy) CrossRun(ctx context.Context, _ bbgo.OrderExecutionRouter, se
|
||||||
})
|
})
|
||||||
|
|
||||||
if s.SourceExchange != "" {
|
if s.SourceExchange != "" {
|
||||||
s.sourceBook = types.NewStreamBook(s.Symbol)
|
s.sourceBook = types.NewStreamBook(s.Symbol, sourceSession.ExchangeName)
|
||||||
s.sourceBook.BindStream(s.sourceSession.MarketDataStream)
|
s.sourceBook.BindStream(s.sourceSession.MarketDataStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.tradingBook = types.NewStreamBook(s.Symbol)
|
s.tradingBook = types.NewStreamBook(s.Symbol, tradingSession.ExchangeName)
|
||||||
s.tradingBook.BindStream(s.tradingSession.MarketDataStream)
|
s.tradingBook.BindStream(s.tradingSession.MarketDataStream)
|
||||||
|
|
||||||
s.tradingSession.UserDataStream.OnTradeUpdate(func(trade types.Trade) {
|
s.tradingSession.UserDataStream.OnTradeUpdate(func(trade types.Trade) {
|
||||||
|
|
85
pkg/strategy/xmaker/metrics.go
Normal file
85
pkg/strategy/xmaker/metrics.go
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
package xmaker
|
||||||
|
|
||||||
|
import "github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
||||||
|
var openOrderBidExposureInUsdMetrics = prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Name: "xmaker_open_order_bid_exposure_in_usd",
|
||||||
|
Help: "",
|
||||||
|
}, []string{"strategy_type", "strategy_id", "exchange", "symbol"})
|
||||||
|
|
||||||
|
var openOrderAskExposureInUsdMetrics = prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Name: "xmaker_open_order_ask_exposure_in_usd",
|
||||||
|
Help: "",
|
||||||
|
}, []string{"strategy_type", "strategy_id", "exchange", "symbol"})
|
||||||
|
|
||||||
|
var makerBestBidPriceMetrics = prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Name: "xmaker_maker_best_bid_price",
|
||||||
|
Help: "",
|
||||||
|
}, []string{"strategy_type", "strategy_id", "exchange", "symbol"})
|
||||||
|
|
||||||
|
var makerBestAskPriceMetrics = prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Name: "xmaker_maker_best_ask_price",
|
||||||
|
Help: "",
|
||||||
|
}, []string{"strategy_type", "strategy_id", "exchange", "symbol"})
|
||||||
|
|
||||||
|
var bidMarginMetrics = prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Name: "xmaker_bid_margin",
|
||||||
|
Help: "the current bid margin (dynamic)",
|
||||||
|
}, []string{"strategy_type", "strategy_id", "exchange", "symbol"})
|
||||||
|
|
||||||
|
var askMarginMetrics = prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Name: "xmaker_ask_margin",
|
||||||
|
Help: "the current ask margin (dynamic)",
|
||||||
|
}, []string{"strategy_type", "strategy_id", "exchange", "symbol"})
|
||||||
|
|
||||||
|
var aggregatedSignalMetrics = prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Name: "xmaker_aggregated_signal",
|
||||||
|
Help: "",
|
||||||
|
}, []string{"strategy_type", "strategy_id", "exchange", "symbol"})
|
||||||
|
|
||||||
|
var configNumOfLayersMetrics = prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Name: "xmaker_config_num_of_layers",
|
||||||
|
Help: "",
|
||||||
|
}, []string{"strategy_type", "strategy_id", "symbol"})
|
||||||
|
|
||||||
|
var configMaxExposureMetrics = prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Name: "xmaker_config_max_exposure",
|
||||||
|
Help: "",
|
||||||
|
}, []string{"strategy_type", "strategy_id", "symbol"})
|
||||||
|
|
||||||
|
var configBidMarginMetrics = prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Name: "xmaker_config_bid_margin",
|
||||||
|
Help: "",
|
||||||
|
}, []string{"strategy_type", "strategy_id", "symbol"})
|
||||||
|
|
||||||
|
var configAskMarginMetrics = prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Name: "xmaker_config_ask_margin",
|
||||||
|
Help: "",
|
||||||
|
}, []string{"strategy_type", "strategy_id", "symbol"})
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
prometheus.MustRegister(
|
||||||
|
openOrderBidExposureInUsdMetrics,
|
||||||
|
openOrderAskExposureInUsdMetrics,
|
||||||
|
makerBestBidPriceMetrics,
|
||||||
|
makerBestAskPriceMetrics,
|
||||||
|
bidMarginMetrics,
|
||||||
|
askMarginMetrics,
|
||||||
|
aggregatedSignalMetrics,
|
||||||
|
configNumOfLayersMetrics,
|
||||||
|
configMaxExposureMetrics,
|
||||||
|
configBidMarginMetrics,
|
||||||
|
configAskMarginMetrics,
|
||||||
|
)
|
||||||
|
}
|
87
pkg/strategy/xmaker/signal_boll.go
Normal file
87
pkg/strategy/xmaker/signal_boll.go
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
package xmaker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
|
"github.com/c9s/bbgo/pkg/indicator/v2"
|
||||||
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var bollingerBandSignalMetrics = prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Name: "xmaker_bollinger_band_signal",
|
||||||
|
Help: "",
|
||||||
|
}, []string{"symbol"})
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
prometheus.MustRegister(bollingerBandSignalMetrics)
|
||||||
|
}
|
||||||
|
|
||||||
|
type BollingerBandTrendSignal struct {
|
||||||
|
types.IntervalWindow
|
||||||
|
MinBandWidth float64 `json:"minBandWidth"`
|
||||||
|
MaxBandWidth float64 `json:"maxBandWidth"`
|
||||||
|
|
||||||
|
indicator *indicatorv2.BOLLStream
|
||||||
|
symbol string
|
||||||
|
lastK *types.KLine
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BollingerBandTrendSignal) Bind(ctx context.Context, session *bbgo.ExchangeSession, symbol string) error {
|
||||||
|
if s.MaxBandWidth == 0.0 {
|
||||||
|
s.MaxBandWidth = 2.0
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.MinBandWidth == 0.0 {
|
||||||
|
s.MinBandWidth = 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
s.symbol = symbol
|
||||||
|
s.indicator = session.Indicators(symbol).BOLL(s.IntervalWindow, s.MinBandWidth)
|
||||||
|
|
||||||
|
session.MarketDataStream.OnKLineClosed(types.KLineWith(s.symbol, s.IntervalWindow.Interval, func(kline types.KLine) {
|
||||||
|
s.lastK = &kline
|
||||||
|
}))
|
||||||
|
|
||||||
|
bollingerBandSignalMetrics.WithLabelValues(s.symbol).Set(0.0)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BollingerBandTrendSignal) CalculateSignal(ctx context.Context) (float64, error) {
|
||||||
|
if s.lastK == nil {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
closePrice := s.lastK.Close
|
||||||
|
|
||||||
|
// when bid price is lower than the down band, then it's in the downtrend
|
||||||
|
// when ask price is higher than the up band, then it's in the uptrend
|
||||||
|
lastDownBand := fixedpoint.NewFromFloat(s.indicator.DownBand.Last(0))
|
||||||
|
lastUpBand := fixedpoint.NewFromFloat(s.indicator.UpBand.Last(0))
|
||||||
|
|
||||||
|
maxBandWidth := s.indicator.StdDev.Last(0) * s.MaxBandWidth
|
||||||
|
|
||||||
|
signal := 0.0
|
||||||
|
|
||||||
|
// if the price is inside the band, do not vote
|
||||||
|
if closePrice.Compare(lastDownBand) > 0 && closePrice.Compare(lastUpBand) < 0 {
|
||||||
|
signal = 0.0
|
||||||
|
} else if closePrice.Compare(lastDownBand) < 0 {
|
||||||
|
signal = lastDownBand.Sub(closePrice).Float64() / maxBandWidth * -2.0
|
||||||
|
} else if closePrice.Compare(lastUpBand) > 0 {
|
||||||
|
signal = closePrice.Sub(lastUpBand).Float64() / maxBandWidth * 2.0
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("[BollingerBandTrendSignal] %f up/down = %f/%f, close price = %f",
|
||||||
|
signal,
|
||||||
|
lastUpBand.Float64(),
|
||||||
|
lastDownBand.Float64(),
|
||||||
|
closePrice.Float64())
|
||||||
|
|
||||||
|
bollingerBandSignalMetrics.WithLabelValues(s.symbol).Set(signal)
|
||||||
|
return signal, nil
|
||||||
|
}
|
68
pkg/strategy/xmaker/signal_book.go
Normal file
68
pkg/strategy/xmaker/signal_book.go
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
package xmaker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var orderBookSignalMetrics = prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Name: "xmaker_order_book_signal",
|
||||||
|
Help: "",
|
||||||
|
}, []string{"symbol"})
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
prometheus.MustRegister(orderBookSignalMetrics)
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderBookBestPriceVolumeSignal struct {
|
||||||
|
RatioThreshold fixedpoint.Value `json:"ratioThreshold"`
|
||||||
|
MinVolume fixedpoint.Value `json:"minVolume"`
|
||||||
|
|
||||||
|
symbol string
|
||||||
|
book *types.StreamOrderBook
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *OrderBookBestPriceVolumeSignal) Bind(ctx context.Context, session *bbgo.ExchangeSession, symbol string) error {
|
||||||
|
if s.book == nil {
|
||||||
|
return errors.New("s.book can not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
s.symbol = symbol
|
||||||
|
orderBookSignalMetrics.WithLabelValues(s.symbol).Set(0.0)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *OrderBookBestPriceVolumeSignal) CalculateSignal(ctx context.Context) (float64, error) {
|
||||||
|
bid, ask, ok := s.book.BestBidAndAsk()
|
||||||
|
if !ok {
|
||||||
|
return 0.0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: may use scale to define this
|
||||||
|
sumVol := bid.Volume.Add(ask.Volume)
|
||||||
|
bidRatio := bid.Volume.Div(sumVol)
|
||||||
|
askRatio := ask.Volume.Div(sumVol)
|
||||||
|
denominator := fixedpoint.One.Sub(s.RatioThreshold)
|
||||||
|
signal := 0.0
|
||||||
|
if bid.Volume.Compare(s.MinVolume) < 0 && ask.Volume.Compare(s.MinVolume) < 0 {
|
||||||
|
signal = 0.0
|
||||||
|
} else if bidRatio.Compare(s.RatioThreshold) >= 0 {
|
||||||
|
numerator := bidRatio.Sub(s.RatioThreshold)
|
||||||
|
signal = numerator.Div(denominator).Float64()
|
||||||
|
} else if askRatio.Compare(s.RatioThreshold) >= 0 {
|
||||||
|
numerator := askRatio.Sub(s.RatioThreshold)
|
||||||
|
signal = -numerator.Div(denominator).Float64()
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("[OrderBookBestPriceVolumeSignal] %f bid/ask = %f/%f", signal, bid.Volume.Float64(), ask.Volume.Float64())
|
||||||
|
|
||||||
|
orderBookSignalMetrics.WithLabelValues(s.symbol).Set(signal)
|
||||||
|
return signal, 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