Compare commits

..

227 Commits

Author SHA1 Message Date
c9s
ac31fd0da2
Merge df5838dc9e into 37106c35b7 2024-09-19 09:41:08 +08:00
c9s
37106c35b7
Merge pull request #1748 from c9s/c9s/add-pos-index
Some checks failed
Go / build (1.21, 6.2) (push) Has been cancelled
golang-lint / lint (push) Has been cancelled
IMPROVE: [db] add index on positions table
2024-09-18 17:06:34 +08:00
c9s
8265ada5a0
compile and update migration package 2024-09-18 13:30:56 +08:00
c9s
744ca57c71
migrations: add index on positions table 2024-09-18 13:30:20 +08:00
c9s
17d3097e06
add v1.60.3 release note
Some checks failed
Go / build (1.21, 6.2) (push) Has been cancelled
golang-lint / lint (push) Has been cancelled
2024-09-16 00:31:00 +08:00
c9s
a0c41f89f2
bump version to v1.60.3 2024-09-16 00:31:00 +08:00
c9s
35a6639530
update command doc files 2024-09-16 00:30:59 +08:00
c9s
26b1fd2ae7
xmaker: fix price initialization 2024-09-16 00:29:37 +08:00
c9s
80430fec46
Merge pull request #1744 from lanphan/activeorder
Some checks are pending
Go / build (1.21, 6.2) (push) Waiting to run
golang-lint / lint (push) Waiting to run
2024-09-14 23:19:10 +08:00
Lan Phan
1f8b2b3710 call b.EmitNew() when new order is added into activeorderbook 2024-09-14 18:26:36 +07:00
c9s
25a2203000
add v1.60.2 release note
Some checks failed
Go / build (1.21, 6.2) (push) Has been cancelled
golang-lint / lint (push) Has been cancelled
2024-09-12 17:51:57 +08:00
c9s
aca2c32442
bump version to v1.60.2 2024-09-12 17:51:57 +08:00
c9s
df915d6ee8
update command doc files 2024-09-12 17:51:57 +08:00
c9s
0d6b7b29d5
Merge pull request #1742 from c9s/c9s/fix-ws-close-err
FIX: types/stream: change errorf to warnf
2024-09-12 17:46:24 +08:00
c9s
2784ef4687
Merge pull request #1741 from c9s/c9s/upgrade-requestgen
FIX: upgrade github.com/c9s/requestgen to 1.4.3
2024-09-12 17:37:55 +08:00
c9s
ea8f3a5485
types/stream: change errorf to warnf 2024-09-12 17:35:13 +08:00
c9s
52f32e0ad0
upgrade github.com/c9s/requestgen to 1.4.3 2024-09-12 17:27:30 +08:00
c9s
50cdf617f2
Merge pull request #1740 from c9s/c9s/upgrade-requestgen
FIX: upgrade requestgen and re-generate max cancel order request files
2024-09-12 12:31:08 +08:00
c9s
de0d11b511
max: regenerate order cancel requests 2024-09-11 16:47:20 +08:00
c9s
789bb1e53e
upgrade github.com/c9s/requestgen to 1.4.2 2024-09-11 16:38:35 +08:00
kbearXD
a9b71adce9
Merge pull request #1739 from c9s/kbearXD/dca2/set-exchange-fee-rate
Some checks failed
Go / build (1.21, 6.2) (push) Has been cancelled
golang-lint / lint (push) Has been cancelled
FEATURE: [dca2] set exchange fee rate for round position
2024-09-11 16:15:13 +08:00
kbearXD
f83491af26 FEATURE: [dca2] set exchange fee rate for round position 2024-09-11 15:40:59 +08:00
bailantaotao
82d07a0098
Merge pull request #1738 from c9s/edwin/okx/add-polusdt
Some checks are pending
Go / build (1.21, 6.2) (push) Waiting to run
golang-lint / lint (push) Waiting to run
FEATURE: [okx] update symbols to latest
2024-09-10 17:23:42 +08:00
edwin
619cce53f6 pkg/exchange: update to latest 2024-09-10 17:11:58 +08:00
c9s
643ecde2e9
Merge pull request #1726 from c9s/dependabot/github_actions/morphy2k/revive-action-2.5.10
Some checks are pending
Go / build (1.21, 6.2) (push) Waiting to run
golang-lint / lint (push) Waiting to run
dep: bump morphy2k/revive-action from 2.5.9 to 2.5.10
2024-09-10 10:28:58 +08:00
c9s
d7ddc9c462
Merge pull request #1737 from c9s/c9s/xmaker/ioc-arb
Some checks are pending
Go / build (1.21, 6.2) (push) Waiting to run
golang-lint / lint (push) Waiting to run
FEATURE: [xmaker] implement tryArbitrage
2024-09-09 22:57:20 +08:00
c9s
bd19b63c7b
go: update sum file 2024-09-09 22:23:25 +08:00
c9s
83ed9b0811
go: upgrade go sqlite 2024-09-09 22:23:02 +08:00
c9s
34ef50d889
xmaker: refactor and clean up tryArbitrage 2024-09-09 22:03:06 +08:00
c9s
52925c5643
xmaker: calculate balance for arbitrage 2024-09-09 18:12:46 +08:00
c9s
b4f2748892
xmaker: fix sides 2024-09-09 18:03:03 +08:00
c9s
ceda1e06b9
xmaker: implement tryArbitrage 2024-09-09 17:49:53 +08:00
c9s
bc1715f8ad
Merge pull request #1736 from c9s/kbearXD/session/remove-log
Some checks are pending
Go / build (1.21, 6.2) (push) Waiting to run
golang-lint / lint (push) Waiting to run
MINOR: [session] remove environment nil validation log
2024-09-09 16:17:17 +08:00
c9s
f361b19564
Merge pull request #1734 from c9s/c9s/xmaker/ioc-arb
REFACTOR: [xmaker] refactor for supporting ioc arb [part1]
2024-09-09 16:05:11 +08:00
kbearXD
f44486447e MINOR: [session] remove environment nil validation log 2024-09-09 16:04:04 +08:00
kbearXD
a2eca66af5
Merge pull request #1735 from c9s/kbearXD/dca2/fix-memory-leak
FIX: configure environment
2024-09-09 15:50:24 +08:00
kbearXD
129e2c438e FIX: add debug log 2024-09-09 15:13:02 +08:00
c9s
90749f4873
xmaker: pull out s.UseDepthPrice dependency 2024-09-09 15:04:56 +08:00
c9s
77dfe213e5
xmaker: pull out getLayerPrice and add test against the method 2024-09-09 14:41:41 +08:00
c9s
960ea89d8c
testhelper: add more test helpers 2024-09-09 14:41:27 +08:00
c9s
f24a96c8c3
xmaker: refactor getInitialLayerQuantity for quantity multiplier 2024-09-07 14:19:07 +08:00
c9s
6ad16b7488
xmaker: add EnableArbitrage option and makerBook 2024-09-07 13:47:34 +08:00
c9s
e14f09a914
xmaker: add sourceDepthLevel option 2024-09-06 21:47:43 +08:00
c9s
3cc96ff6ad
Merge pull request #1724 from dropbigfish/main
Some checks failed
Go / build (1.21, 6.2) (push) Has been cancelled
golang-lint / lint (push) Has been cancelled
fix: fix slice init length
2024-09-06 18:06:21 +08:00
c9s
6ea996bec4
Merge pull request #1733 from c9s/c9s/fix-initialize-defaults-steps
FIX: [bbgo] fix the defaults / initialize steps
2024-09-06 17:54:13 +08:00
c9s
ef935f8ca0
Merge pull request #1732 from lanphan/telegram_doc
fix env name
2024-09-06 17:40:26 +08:00
c9s
a282654c02
bbgo: fix the defaults / initialize steps 2024-09-06 17:33:31 +08:00
Lan Phan
336dd7a108 fix env name 2024-09-05 22:51:43 +07:00
kbearXD
f2a443a499
Merge pull request #1728 from c9s/kbearXD/dca2/fix-memory-leak
Some checks are pending
Go / build (1.21, 6.2) (push) Waiting to run
golang-lint / lint (push) Waiting to run
FIX: [core] fix memory leak
2024-09-05 17:52:41 +08:00
kbearXD
63a58e1b12 FIX: fix memory leak 2024-09-05 17:05:58 +08:00
c9s
1b40118bba
Merge pull request #1731 from longhutianjie/main
Some checks are pending
Go / build (1.21, 6.2) (push) Waiting to run
golang-lint / lint (push) Waiting to run
bug: fix json tag
2024-09-05 13:57:31 +08:00
longhutianjie
c75a685cc0
bug: fix json tag 2024-09-04 17:58:27 +08:00
c9s
50262f2a84
Merge pull request #1730 from c9s/c9s/xmaker/market-trade-signal
Some checks are pending
Go / build (1.21, 6.2) (push) Waiting to run
golang-lint / lint (push) Waiting to run
FEATURE: [xmaker] add market trade signal
2024-09-04 16:27:42 +08:00
c9s
9fc3a1b44a
xmaker: rename to aggTradeVolume 2024-09-04 16:09:58 +08:00
c9s
656112de45
xmaker: call signalConfig.TradeVolumeWindowSignal.Bind 2024-09-04 16:07:28 +08:00
c9s
ba73eeaad1
xmaker: add TradeVolumeWindowSignal 2024-09-04 15:59:21 +08:00
c9s
2527c0c7b7
max: convert v3 DepositStateFailed into rejected 2024-09-04 15:00:37 +08:00
c9s
a2f8fe5f72
max: add v3 DepositStateFailed state 2024-09-04 14:59:58 +08:00
c9s
ed51eff242
max: drop unused function 2024-09-04 14:59:10 +08:00
c9s
f6865f664c
add v1.60.1 release note
Some checks are pending
Go / build (1.21, 6.2) (push) Waiting to run
golang-lint / lint (push) Waiting to run
2024-09-04 14:58:07 +08:00
c9s
24de49860f
bump version to v1.60.1 2024-09-04 14:58:07 +08:00
c9s
83dc981c92
update command doc files 2024-09-04 14:58:07 +08:00
c9s
ec68e3c5f6
Merge pull request #1727 from lanphan/ioc
FIX: update timeInForce for binance margin order
2024-09-04 14:38:40 +08:00
c9s
699164484b
Merge pull request #1729 from c9s/c9s/max/fix-v3-deposit-state-conversion
FIX: [max] fix v3 deposit state conversion
2024-09-04 11:41:22 +08:00
c9s
f27afac77b
max: use error log instead of warning log for convertion 2024-09-04 11:20:30 +08:00
c9s
d404b20bd1
deposit2transfer: fix comments 2024-09-04 11:19:43 +08:00
c9s
1b8d7bd805
max: fix v3 deposit state conversion 2024-09-04 11:17:56 +08:00
c9s
7d034d1ba8
bbgo: add stringer method to the quota struct
Some checks failed
Go / build (1.21, 6.2) (push) Has been cancelled
golang-lint / lint (push) Has been cancelled
2024-09-03 03:26:47 +08:00
c9s
7135895006
xmaker: fix MaxExposurePosition check condition 2024-09-03 03:25:37 +08:00
Lan Phan
ba913ce4de update timeInForce for binance margin order 2024-09-03 00:38:17 +07:00
c9s
f12ba1adb9
bbgo: add comments to the quota methods
Some checks are pending
Go / build (1.21, 6.2) (push) Waiting to run
golang-lint / lint (push) Waiting to run
2024-09-02 22:18:13 +08:00
c9s
294e529a98
xmaker: add more logs 2024-09-02 16:08:51 +08:00
c9s
f30aca1b5a
xmaker: update position metrics when restored 2024-09-02 15:51:31 +08:00
c9s
f9b9832fff
add more logs 2024-09-02 15:51:31 +08:00
c9s
2bf1072977
Merge pull request #1725 from c9s/c9s/xmaker/stb-improvements
IMPROVE: [xmaker] improve hedge margin account leverage calculation
2024-09-02 15:29:53 +08:00
dependabot[bot]
01f8b78008
dep: bump morphy2k/revive-action from 2.5.9 to 2.5.10
Bumps [morphy2k/revive-action](https://github.com/morphy2k/revive-action) from 2.5.9 to 2.5.10.
- [Release notes](https://github.com/morphy2k/revive-action/releases)
- [Commits](https://github.com/morphy2k/revive-action/compare/v2.5.9...v2.5.10)

---
updated-dependencies:
- dependency-name: morphy2k/revive-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-02 06:39:35 +00:00
c9s
4d1c357c3d
xmaker: reuse makerMarket field 2024-09-01 17:55:00 +08:00
c9s
a4833524cf
xmaker: add more logs 2024-09-01 16:41:16 +08:00
c9s
ed073264f1
xmaker: add MaxHedgeAccountLeverage option 2024-09-01 15:42:36 +08:00
c9s
ad6056834e
xmaker: separate maximumValueInUsd in a new var 2024-09-01 01:34:25 +08:00
c9s
8b1306a6a6
xmaker: calculate maximum leveraged account value 2024-09-01 01:31:50 +08:00
c9s
d85da78e17
xmaker: improve hedge account credit calculation 2024-09-01 00:58:50 +08:00
dropbigfish
9d581adc04 fix: fix slice init length
Signed-off-by: dropbigfish <fillfish@foxmail.com>
2024-09-01 00:36:43 +08:00
c9s
cff7103ece
fix math import
Some checks failed
Go / build (1.21, 6.2) (push) Has been cancelled
golang-lint / lint (push) Has been cancelled
2024-08-30 22:41:13 +08:00
c9s
d501e8ff4d
xmaker: apply math.Abs on signal for margin scale 2024-08-30 22:38:59 +08:00
c9s
b87213827e
Merge pull request #1723 from c9s/c9s/xmaker/add-signals
FIX: [xmaker] avoid calculate margin from 0.0 signal
2024-08-30 18:01:57 +08:00
c9s
ec80cbfd9f
xmaker: check 0.0 2024-08-30 17:52:28 +08:00
c9s
04bed165d0
Merge pull request #1722 from c9s/c9s/xmaker/add-signals
FEATURE: [xmaker] add signals
2024-08-30 17:50:52 +08:00
c9s
7c4b3e81df
xmaker: add more logs 2024-08-30 17:42:20 +08:00
c9s
cc820d3df0
xmaker: apply margin from signal 2024-08-30 17:39:25 +08:00
c9s
371db8e7d1
xmaker: update signal conditions to metrics 2024-08-30 17:18:29 +08:00
c9s
b8abc065de
xmaker: initialize bollinger band signal 2024-08-30 17:15:12 +08:00
c9s
9ebab4f4f7
xmaker: add signal providers 2024-08-30 15:44:55 +08:00
c9s
d9fb9ff3e0
xmaker: remove unused var 2024-08-29 13:18:50 +08:00
c9s
88d7783843
bbgo/activeOrderBook: filter market order when filtering existing orders 2024-08-29 00:38:44 +08:00
c9s
86e464b1bc
xmaker: when submitting hedge orders, do not add it to the active orderbook 2024-08-29 00:33:04 +08:00
c9s
8e91a023ca
Merge pull request #1721 from c9s/c9s/xmaker/fix-agg-price-method
FIX: [xmaker] fix aggregatePrice method
2024-08-28 22:46:19 +08:00
c9s
8de0c67503
xmaker: fix aggregatePrice function 2024-08-28 22:36:44 +08:00
c9s
e187614179
xmaker: log best bid and best ask 2024-08-28 22:32:56 +08:00
c9s
bda66040e7
Merge pull request #1720 from c9s/c9s/xmaker/margin-credit-improvement
FEATURE: [xmaker] margin credit improvement
2024-08-28 16:53:33 +08:00
c9s
d36bbe5fb5
xmaker: adjust accountUpdater's ticker to 3 min 2024-08-28 16:41:50 +08:00
c9s
77b7b29739
xmaker: adjust credit buffer algo 2024-08-28 16:37:39 +08:00
c9s
1d6282a10b
xmaker: add account updater and handle margin account to add more flexibility 2024-08-28 16:07:11 +08:00
c9s
108fb6138a
xmaker: check hedge balance only when it's spot account 2024-08-28 14:48:38 +08:00
c9s
1e2f086643
xmaker: set notional var back 2024-08-27 22:45:43 +08:00
c9s
6011fd5157
xmaker: set profitChanged only when Hedge is called 2024-08-27 22:45:11 +08:00
c9s
652c9b62e8
Merge pull request #1719 from c9s/c9s/xmaker/stb-improvements
IMPROVE: [xmaker] fix bollinger band price calculation
2024-08-27 20:14:48 +08:00
c9s
9939b5ce68
xmaker: improve bid/ask pricing when UseDepthPrice and DepthQuantity are on 2024-08-27 20:05:46 +08:00
c9s
a740ef10c2
xmaker: add price checker and field logger 2024-08-27 20:05:45 +08:00
c9s
f81ce5ce95
xmaker: improve bollinger band trend detection 2024-08-27 20:05:45 +08:00
c9s
4ae8ad77b3
xmaker: add profit changed flag for notification 2024-08-27 20:05:45 +08:00
c9s
3819feacf3
xmaker: improve dust quantity check 2024-08-27 20:05:45 +08:00
c9s
4af12a7e5d
Merge pull request #1718 from c9s/c9s/xmaker/config-metrics
FEATURE: [xmaker] add more config metrics
2024-08-27 18:09:47 +08:00
c9s
3d4ccd1344
xmaker: integrate bid/ask margin metrics 2024-08-27 15:39:38 +08:00
c9s
b3c8739983
xmaker: add config bid/ask margin metrics 2024-08-27 15:35:39 +08:00
c9s
5edf5a763f
Merge pull request #1717 from c9s/c9s/xmaker/worker-method
REFACTOR: [xmaker] refactor hedge worker and quote worker
2024-08-27 15:32:56 +08:00
c9s
7e65aca62e
xmaker: add more config metrics 2024-08-27 15:22:06 +08:00
c9s
199b86df86
xmaker: add comments 2024-08-27 14:52:27 +08:00
c9s
6fb6467d59
xmaker: refactor hedge worker and quote worker 2024-08-27 14:48:30 +08:00
c9s
2479f2e9fc
Merge pull request #1715 from c9s/c9s/upgrade-pkgs
UPGRADE: [go] upgrade packages that are too old
2024-08-26 19:06:54 +08:00
c9s
e77f0cbacb
Merge pull request #1714 from c9s/dependabot/github_actions/actions/setup-node-4
dep: bump actions/setup-node from 2 to 4
2024-08-26 18:54:54 +08:00
c9s
be386d085a
go: upgrade packages that are too old 2024-08-26 18:54:21 +08:00
c9s
ea93bf959a
Merge pull request #1716 from c9s/c9s/xmaker/stb-improvements
FIX: [xmaker] profit object can be nil
2024-08-26 18:39:29 +08:00
c9s
e3079c134c
xmaker: add todo note 2024-08-26 18:37:02 +08:00
c9s
7367ea73b8
xmaker: profit object can be nil 2024-08-26 18:35:10 +08:00
c9s
f96e0d6552
config: change staging to local 2024-08-26 16:11:48 +08:00
c9s
68e56d76e6
Merge pull request #1713 from c9s/c9s/chart/env-section 2024-08-26 14:59:00 +08:00
dependabot[bot]
ec51eb7cdd
dep: bump actions/setup-node from 2 to 4
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 2 to 4.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v2...v4)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-26 06:21:47 +00:00
c9s
3ec509b379
ci: use list literal 2024-08-26 13:34:20 +08:00
c9s
84edcb0e02
ci: add github actions pull requests types 2024-08-26 13:33:43 +08:00
c9s
866751cc3d
Merge pull request #1712 from c9s/c9s/xmaker/add-profit-fixer
FEATURE: [xmaker] add profit fixer
2024-08-26 13:32:41 +08:00
c9s
80949bf0e1
Merge pull request #1710 from c9s/c9s/xmaker/stb-improvements
IMPROVE: [xmaker] improve stability
2024-08-26 13:32:19 +08:00
c9s
86cc821626
config: add circuit breaker enabled = true 2024-08-26 13:16:40 +08:00
c9s
90bcd25bef
Merge pull request #1711 from lanphan/autoborrowrepay
FEATURE: [binance] add new margin order side effect AUTO_BORROW_REPAY
2024-08-26 13:15:21 +08:00
c9s
f59ff90c5e
bump chart version 2024-08-26 13:04:45 +08:00
c9s
3013e37a38
chart: add env vars section into the chart 2024-08-26 13:03:58 +08:00
c9s
349a3040f3
Merge pull request #1709 from c9s/c9s/xmaker/improve-profit-ticker
IMPROVE: [xmaker] improve profit stats ticker and integrate rate limiter
2024-08-26 12:50:31 +08:00
c9s
7fdb3f671f
risk: add Enabled config to circuitbreaker 2024-08-26 12:50:13 +08:00
c9s
321eb23514
config: add profit fixer to the sample config 2024-08-26 12:46:45 +08:00
c9s
77e185ffa7
xmaker: add profit fixer 2024-08-26 12:45:18 +08:00
c9s
e7fd90ed59
Merge pull request #1708 from c9s/c9s/xmaker/integrate-circuitbreaker
FEATURE: [xmaker] integrate circuit breaker
2024-08-26 12:36:17 +08:00
Lan Phan
9a7517a72a add new sideeffect AUTO_BORROW_REPAY 2024-08-25 12:31:10 +07:00
c9s
9a1d9ae27b
xmaker: rewrite maker order submission logics and integrate metrics 2024-08-24 21:22:35 +08:00
c9s
c76a80da6a
xmaker: add xmaker metrics 2024-08-24 21:22:34 +08:00
c9s
afac81a3e8
all: integrate metrics into stream book 2024-08-24 21:22:34 +08:00
c9s
b0cc009d67
remove travis config 2024-08-24 13:29:45 +08:00
c9s
0df56ad6e7
xmaker: use v2 indicator boll 2024-08-24 13:28:32 +08:00
c9s
1c1959b8a8
all: rename priceresolver to pricesolver
integrate pricesolver into xmaker
2024-08-24 12:28:05 +08:00
c9s
9f01dc28c8
xmaker: remove report ticker and
isolate rate limiter for each different instance
2024-08-24 12:19:34 +08:00
c9s
e8bd370aa2
xmaker: remove duplicated log entry 2024-08-24 12:13:44 +08:00
c9s
5ca1c4fb62
xmaker: rewrite and clean up order submission 2024-08-24 12:13:15 +08:00
c9s
f7dc07327e
xmaker: assign position strategy id and instance id 2024-08-24 12:01:11 +08:00
c9s
6ef8aa62e5
xmaker: integrate CircuitBreaker 2024-08-24 11:58:09 +08:00
c9s
5f65e87e89
change default HaltDuration to 1h 2024-08-24 11:43:12 +08:00
c9s
14fff8dbad
xmaker: integrate circuitbreaker 2024-08-24 11:42:16 +08:00
c9s
92ad80f2f8
bump chart version to 0.4.2 2024-08-23 21:43:00 +08:00
c9s
0a2d442ceb
fix cronjob_sync indentation 2024-08-23 21:42:30 +08:00
c9s
f7f8ecfd15
Merge pull request #1707 from c9s/c9s/xmaker/stb-improvements
FIX: [xmaker] position metrics missing label
2024-08-23 20:12:31 +08:00
c9s
40a0585187
types: fix missing labels 2024-08-23 19:59:56 +08:00
c9s
9f510da78b
xmaker: use margin order to hedge positions 2024-08-23 16:57:29 +08:00
c9s
c2679b4ae1
Merge pull request #1705 from c9s/c9s/k8s/sync-cronjob
FIX: [k8s] fix sync.enabled option
2024-08-23 15:56:55 +08:00
c9s
106a01e508
wrap cronjob with sync.enabled var 2024-08-23 15:19:07 +08:00
c9s
02ff04cfb5
fix default sync schedule 2024-08-23 15:04:00 +08:00
c9s
80ad5c32b5
Merge pull request #1704 from c9s/c9s/k8s/sync-cronjob
FEATURE: [k8s] add cronjob for sync
2024-08-23 14:57:07 +08:00
c9s
e3c4314aed
bump chart versions 2024-08-23 14:23:24 +08:00
c9s
c7f62cf1e5
add since parameter 2024-08-23 14:22:49 +08:00
c9s
4bbb9c5e38
add cronjob for sync 2024-08-23 14:19:33 +08:00
c9s
b2f1f7d735
Merge pull request #1700 from c9s/narumi/autobuy-boll
Fix: [autobuy] fix error when bollinger settings is not set
2024-08-23 13:05:18 +08:00
narumi
1b06fcc961 validate parameters 2024-08-22 14:36:06 +08:00
narumi
b820fccce1 add order type to config 2024-08-22 14:36:06 +08:00
c9s
bb06a6a046
Merge pull request #1703 from c9s/c9s/core/position-metrics
FEATURE: [core] add position metrics
2024-08-22 13:32:39 +08:00
c9s
72575e3cd8
elliottwave: use AverageCost instead 2024-08-22 11:26:46 +08:00
c9s
a900c72032
types/position: drop approximateAverageCost 2024-08-22 11:19:54 +08:00
c9s
5635e31487
types: pull out calculateFeeInQuote method 2024-08-22 11:07:45 +08:00
c9s
e2d68f2a86
types: add fee cost settter to the position 2024-08-22 10:59:38 +08:00
c9s
6718087cb1
Merge pull request #1702 from c9s/c9s/core/improve-metrics
IMPROVE: improve balance related metrics
2024-08-22 10:02:51 +08:00
c9s
9136877207
types: update position metrics after adding trades 2024-08-21 16:35:57 +08:00
c9s
c063df6467
document privateChannels and privateChannelSymbols 2024-08-21 16:24:19 +08:00
c9s
80fc10a1fd
bbgo: add session name to the metrics 2024-08-21 15:46:09 +08:00
c9s
fead99aaa6
add more balance metrics 2024-08-21 15:33:27 +08:00
c9s
40d3a40277
types: add marginType 2024-08-21 15:24:43 +08:00
c9s
055cfbb3ff
Merge pull request #1699 from c9s/c9s/refactor-twap
REFACTOR: [twap] upgrade twap command and add optional order update rate limiter
2024-08-21 15:20:57 +08:00
c9s
d18adfcbc7
Merge pull request #1701 from c9s/release/v1.60
RELEASE: v1.60.0
2024-08-21 14:55:34 +08:00
c9s
48eeae0a10
add v1.60.0 release note 2024-08-21 14:42:59 +08:00
c9s
d855d9bbc0
bump version to v1.60.0 2024-08-21 14:42:59 +08:00
c9s
1a1f700122
update command doc files 2024-08-21 14:42:58 +08:00
c9s
3a2e4dfd26
add new scripts 2024-08-21 14:40:29 +08:00
c9s
6f0cf8f3e0
chmod +x 2024-08-21 14:37:39 +08:00
narumi
731fa9af7e fix error when bollinger settings is not set 2024-08-21 13:28:22 +08:00
c9s
a06b63c897
twap: rename constructor 2024-08-20 18:13:42 +08:00
c9s
ebaf3a330f
twap: pull out submitOrder method 2024-08-20 17:53:19 +08:00
c9s
a0cbf82d97
twap: handle delayInterval after canceling order 2024-08-20 17:51:44 +08:00
c9s
9a2b792ed1
twap: split doneSignal into a single file 2024-08-20 17:49:18 +08:00
c9s
2392fddc3c
fix method name 2024-08-20 17:47:39 +08:00
c9s
c92c395f67
twap: improve rate limiter syntax parser and support order update rate limiter in twap 2024-08-20 17:07:29 +08:00
c9s
48029f95cc
cmd: pull out and refine twap order executor command 2024-08-20 16:24:34 +08:00
c9s
8911f88ed6
Merge pull request #1683 from c9s/dependabot/github_actions/codecov/codecov-action-4
dep: bump codecov/codecov-action from 3 to 4
2024-08-20 14:46:16 +08:00
c9s
a1c77e42f1
Merge pull request #1680 from c9s/dependabot/github_actions/docker/setup-buildx-action-3
dep: bump docker/setup-buildx-action from 1 to 3
2024-08-20 14:42:33 +08:00
c9s
c03f5f47c2
Merge pull request #1684 from c9s/dependabot/github_actions/docker/metadata-action-5
dep: bump docker/metadata-action from 3 to 5
2024-08-20 14:42:20 +08:00
c9s
40260a1204
Merge pull request #1681 from c9s/dependabot/github_actions/actions/checkout-4
dep: bump actions/checkout from 2 to 4
2024-08-20 14:42:10 +08:00
c9s
baffefac07
Merge pull request #1689 from anywhy/fix_float64_series
fix float64 series use mean or stdev function result is zero
2024-08-20 14:41:29 +08:00
c9s
6d3a18ad55
twap: call trade collector process when shutdown 2024-08-20 14:30:08 +08:00
c9s
d1617b6a0b
Merge pull request #1697 from c9s/c9s/refactor-twap
FEATURE: redesign and refactor twap order executor
2024-08-20 14:24:48 +08:00
c9s
b9c41b7ad7
twap: improve cancelContextIfTargetQuantityFilled check method 2024-08-20 14:14:19 +08:00
c9s
0530809834
fix position test 2024-08-20 14:10:22 +08:00
c9s
d8fad8250c
fix duplicated field 2024-08-20 14:01:19 +08:00
c9s
c8aea81505
twap: implement twap mock testing 2024-08-20 14:01:04 +08:00
c9s
cec078f4bf
twap: add stream executor test 2024-08-20 14:01:04 +08:00
c9s
648e10fd7c
binance: fix time in force setting for limit maker 2024-08-20 14:01:04 +08:00
c9s
b7d18e687e
twap: implement orderUpdater 2024-08-20 14:01:03 +08:00
c9s
51c1b995c2
twap: add v2 fixed quantity executor 2024-08-20 14:01:03 +08:00
dependabot[bot]
f845918d80
dep: bump actions/checkout from 2 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-20 05:49:53 +00:00
c9s
47c7714d33
Merge pull request #1698 from c9s/feature/max/update-get-trade-api
FEATURE: update get trades api
2024-08-20 13:49:39 +08:00
c9s
408a41342b
Merge pull request #1692 from c9s/narumi/delete-python
DELETE: delete python
2024-08-20 13:49:17 +08:00
c9s
f7ad141b04
Merge pull request #1693 from anywhy/fix_binance_query_order
fix binance exchange query futures order
2024-08-19 18:01:03 +08:00
kbearXD
90712aff29 FEATURE: update get trades api 2024-08-19 17:05:02 +08:00
c9s
0a83c26fd5
types: add warning to the price type 2024-08-17 14:15:43 +08:00
c9s
1294cd95be
rename twap.Execution to twap.StreamExecutor 2024-08-17 14:09:25 +08:00
c9s
9dd85623b9
types,strategy: refactor price type and add more bbo (best bid offer) 2024-08-17 14:05:29 +08:00
c9s
621a2b86cf
twap: move twap execution to a single package 2024-08-17 13:29:27 +08:00
anywhy
714275fedb fix binance exchange query futures order 2024-08-16 13:06:43 +08:00
anywhy
b27fc896f9 add serie_float64 test case 2024-08-15 16:44:45 +08:00
narumi
cf42d9d0b0 delete python 2024-08-13 17:07:56 +08:00
Any Yang
8773c220f5
fix float64 series use mean or stdev function result is zero 2024-08-07 17:52:39 +08:00
dependabot[bot]
b4bb7b6716
dep: bump docker/metadata-action from 3 to 5
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 3 to 5.
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Upgrade guide](https://github.com/docker/metadata-action/blob/master/UPGRADE.md)
- [Commits](https://github.com/docker/metadata-action/compare/v3...v5)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 06:57:58 +00:00
dependabot[bot]
57a68f8063
dep: bump codecov/codecov-action from 3 to 4
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 06:57:53 +00:00
dependabot[bot]
c35805916a
dep: bump docker/setup-buildx-action from 1 to 3
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 1 to 3.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v1...v3)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 06:57:38 +00:00
187 changed files with 5472 additions and 4388 deletions

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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 .

View File

@ -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

View File

@ -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/...

View File

@ -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

View 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 -}}

View File

@ -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 }}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -9,8 +9,10 @@ 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
--delay-interval duration order delay time after filled (default 3s)
-h, --help help for execute-order -h, --help help for execute-order
--order-update-rate-limit string order update rate limit, syntax: 1+1/1m (default "1s")
--price-ticks int the number of price tick for the jump spread, default to 0 --price-ticks int the number of price tick for the jump spread, default to 0
--session string the exchange session name for sync --session string the exchange session name for sync
--side string the trading side: buy or sell --side string the trading side: buy or sell
@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View 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
View 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
View 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
View 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

View File

@ -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
View File

@ -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
View File

@ -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=

View 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

View 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

View File

@ -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)
} }

View File

@ -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]
}
}

View 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++
}
}

View File

@ -9,34 +9,93 @@ var (
Help: "bbgo exchange session connection status", Help: "bbgo exchange session connection status",
}, },
[]string{ []string{
"session",
"exchange", // exchange name "exchange", // exchange name
"channel", // channel: user or market "channel", // channel: user or market
"margin", // margin type: none, margin or isolated "margin_type", // margin type: none, margin or isolated
"symbol", // margin symbol of the connection. "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{
"session",
"exchange", // exchange name "exchange", // exchange name
"margin", // margin of connection. 1 or 0 "margin_type", // margin of connection. 1 or 0
"symbol", // margin symbol of the connection. "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{
"session",
"exchange", // exchange name "exchange", // exchange name
"margin", // margin of connection. none, margin or isolated "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. "symbol", // margin symbol of the connection.
"currency", "currency",
}, },
@ -48,8 +107,9 @@ var (
Help: "bbgo exchange session total balances", Help: "bbgo exchange session total balances",
}, },
[]string{ []string{
"session",
"exchange", // exchange name "exchange", // exchange name
"margin", // margin of connection. none, margin or isolated "margin_type", // margin of connection. none, margin or isolated
"symbol", // margin symbol of the connection. "symbol", // margin symbol of the connection.
"currency", "currency",
}, },
@ -61,8 +121,9 @@ var (
Help: "bbgo exchange session trades", Help: "bbgo exchange session trades",
}, },
[]string{ []string{
"session",
"exchange", // exchange name "exchange", // exchange name
"margin", // margin of connection. none, margin or isolated "margin_type", // margin of connection. none, margin or isolated
"symbol", // margin symbol of the connection. "symbol", // margin symbol of the connection.
"side", // side: buy or sell "side", // side: buy or sell
"liquidity", // maker or taker "liquidity", // maker or taker
@ -75,22 +136,24 @@ var (
Help: "bbgo trading volume", Help: "bbgo trading volume",
}, },
[]string{ []string{
"session",
"exchange", // exchange name "exchange", // exchange name
"margin", // margin of connection. none, margin or isolated "margin_type", // margin of connection. none, margin or isolated
"symbol", // margin symbol of the connection. "symbol", // margin symbol of the connection.
"side", // side: buy or sell "side", // side: buy or sell
"liquidity", // maker or taker "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{
"session",
"exchange", // exchange name "exchange", // exchange name
"margin", // margin of connection. none, margin or isolated "margin_type", // margin of connection. none, margin or isolated
"channel", // channel: user, market "channel", // channel: user, market
"data_type", // type: balance, ticker, kline, orderbook, trade, order "data_type", // type: balance, ticker, kline, orderbook, trade, order
"symbol", // for market data, trade and order "symbol", // for market data, trade and order
@ -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,
) )
} }

View File

@ -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

View File

@ -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(""),
}, },

View File

@ -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()

View File

@ -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,32 +888,42 @@ 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{
"session": session.Name,
"exchange": session.ExchangeName.String(), "exchange": session.ExchangeName.String(),
"margin": session.MarginType(), "margin_type": string(session.MarginType()),
"symbol": session.IsolatedMarginSymbol, "symbol": session.IsolatedMarginSymbol,
"currency": currency, "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())
// margin metrics
metricsBalanceDebtMetrics.With(labels).Set(balance.Debt().Float64())
metricsBalanceBorrowedMetrics.With(labels).Set(balance.Borrowed.Float64())
metricsBalanceInterestMetrics.With(labels).Set(balance.Interest.Float64())
metricsLastUpdateTimeMetrics.With(prometheus.Labels{
"session": session.Name,
"exchange": session.ExchangeName.String(), "exchange": session.ExchangeName.String(),
"margin": session.MarginType(), "margin_type": string(session.MarginType()),
"channel": "user", "channel": "user",
"data_type": "balance", "data_type": "balance",
"symbol": "", "symbol": "",
@ -922,9 +934,10 @@ func (session *ExchangeSession) metricsBalancesUpdater(balances types.BalanceMap
} }
func (session *ExchangeSession) metricsOrderUpdater(order types.Order) { func (session *ExchangeSession) metricsOrderUpdater(order types.Order) {
metricsLastUpdateTimeBalance.With(prometheus.Labels{ metricsLastUpdateTimeMetrics.With(prometheus.Labels{
"session": session.Name,
"exchange": session.ExchangeName.String(), "exchange": session.ExchangeName.String(),
"margin": session.MarginType(), "margin_type": string(session.MarginType()),
"channel": "user", "channel": "user",
"data_type": "order", "data_type": "order",
"symbol": order.Symbol, "symbol": order.Symbol,
@ -934,17 +947,19 @@ func (session *ExchangeSession) metricsOrderUpdater(order types.Order) {
func (session *ExchangeSession) metricsTradeUpdater(trade types.Trade) { func (session *ExchangeSession) metricsTradeUpdater(trade types.Trade) {
labels := prometheus.Labels{ labels := prometheus.Labels{
"session": session.Name,
"exchange": session.ExchangeName.String(), "exchange": session.ExchangeName.String(),
"margin": session.MarginType(), "margin_type": string(session.MarginType()),
"side": trade.Side.String(), "side": trade.Side.String(),
"symbol": trade.Symbol, "symbol": trade.Symbol,
"liquidity": trade.Liquidity(), "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{
"session": session.Name,
"exchange": session.ExchangeName.String(), "exchange": session.ExchangeName.String(),
"margin": session.MarginType(), "margin_type": string(session.MarginType()),
"channel": "user", "channel": "user",
"data_type": "trade", "data_type": "trade",
"symbol": trade.Symbol, "symbol": trade.Symbol,
@ -954,9 +969,10 @@ func (session *ExchangeSession) metricsTradeUpdater(trade types.Trade) {
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{
"session": session.Name,
"exchange": session.ExchangeName.String(), "exchange": session.ExchangeName.String(),
"margin": session.MarginType(), "margin_type": string(session.MarginType()),
"channel": "market", "channel": "market",
"data_type": "book", "data_type": "book",
"symbol": book.Symbol, "symbol": book.Symbol,
@ -964,9 +980,10 @@ func (session *ExchangeSession) bindMarketDataStreamMetrics(stream types.Stream)
}).SetToCurrentTime() }).SetToCurrentTime()
}) })
stream.OnKLineClosed(func(kline types.KLine) { stream.OnKLineClosed(func(kline types.KLine) {
metricsLastUpdateTimeBalance.With(prometheus.Labels{ metricsLastUpdateTimeMetrics.With(prometheus.Labels{
"session": session.Name,
"exchange": session.ExchangeName.String(), "exchange": session.ExchangeName.String(),
"margin": session.MarginType(), "margin_type": string(session.MarginType()),
"channel": "market", "channel": "market",
"data_type": "kline", "data_type": "kline",
"symbol": kline.Symbol, "symbol": kline.Symbol,
@ -983,16 +1000,18 @@ func (session *ExchangeSession) bindUserDataStreamMetrics(stream types.Stream) {
stream.OnDisconnect(func() { stream.OnDisconnect(func() {
metricsConnectionStatus.With(prometheus.Labels{ metricsConnectionStatus.With(prometheus.Labels{
"channel": "user", "channel": "user",
"session": session.Name,
"exchange": session.ExchangeName.String(), "exchange": session.ExchangeName.String(),
"margin": session.MarginType(), "margin_type": string(session.MarginType()),
"symbol": session.IsolatedMarginSymbol, "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",
"session": session.Name,
"exchange": session.ExchangeName.String(), "exchange": session.ExchangeName.String(),
"margin": session.MarginType(), "margin_type": string(session.MarginType()),
"symbol": session.IsolatedMarginSymbol, "symbol": session.IsolatedMarginSymbol,
}).Set(1.0) }).Set(1.0)
}) })

View File

@ -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
View 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
},
}

View File

@ -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()

View File

@ -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)
} }

View File

@ -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"
@ -44,7 +45,6 @@ func toGlobalFuturesPositions(futuresPositions []*binanceapi.FuturesAccountPosit
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),

View File

@ -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))

View File

@ -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)
} }

View File

@ -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 {

View File

@ -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
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 { if err := response.DecodeJSON(&apiResponse); err != nil {
return nil, err 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
} }

View File

@ -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
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 { if err := response.DecodeJSON(&apiResponse); err != nil {
return nil, err 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
} }

View File

@ -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
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 { if err := response.DecodeJSON(&apiResponse); err != nil {
return nil, err 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
} }

View File

@ -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
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 { if err := response.DecodeJSON(&apiResponse); err != nil {
return nil, err 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
} }

View File

@ -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
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 { if err := response.DecodeJSON(&apiResponse); err != nil {
return nil, err 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
} }

View File

@ -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
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 { if err := response.DecodeJSON(&apiResponse); err != nil {
return nil, err 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
} }

View File

@ -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

View File

@ -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

View File

@ -5,45 +5,42 @@ var spotSymbolMap = map[string]string{
"1INCHEUR": "1INCH-EUR", "1INCHEUR": "1INCH-EUR",
"1INCHUSDC": "1INCH-USDC", "1INCHUSDC": "1INCH-USDC",
"1INCHUSDT": "1INCH-USDT", "1INCHUSDT": "1INCH-USDT",
"AAVEBTC": "AAVE-BTC",
"AAVEEUR": "AAVE-EUR", "AAVEEUR": "AAVE-EUR",
"AAVEUSDC": "AAVE-USDC", "AAVEUSDC": "AAVE-USDC",
"AAVEUSDT": "AAVE-USDT", "AAVEUSDT": "AAVE-USDT",
"ACAUSDC": "ACA-USDC",
"ACAUSDT": "ACA-USDT", "ACAUSDT": "ACA-USDT",
"ACEUSDC": "ACE-USDC", "ACEUSDC": "ACE-USDC",
"ACEUSDT": "ACE-USDT", "ACEUSDT": "ACE-USDT",
"ACHUSDT": "ACH-USDT", "ACHUSDT": "ACH-USDT",
"ADABTC": "ADA-BTC",
"ADAETH": "ADA-ETH",
"ADAEUR": "ADA-EUR", "ADAEUR": "ADA-EUR",
"ADAUSDC": "ADA-USDC", "ADAUSDC": "ADA-USDC",
"ADAUSDT": "ADA-USDT", "ADAUSDT": "ADA-USDT",
"AERGOUSDT": "AERGO-USDT", "AERGOUSDT": "AERGO-USDT",
"AEVOUSDT": "AEVO-USDT", "AEVOUSDT": "AEVO-USDT",
"AGIXUSDC": "AGIX-USDC",
"AGIXUSDT": "AGIX-USDT",
"AGLDUSDC": "AGLD-USDC", "AGLDUSDC": "AGLD-USDC",
"AGLDUSDT": "AGLD-USDT", "AGLDUSDT": "AGLD-USDT",
"AIDOGEUSDT": "AIDOGE-USDT", "AIDOGEUSDT": "AIDOGE-USDT",
"AKITAUSDT": "AKITA-USDT", "ALCXUSDC": "ALCX-USDC",
"ALCXUSDT": "ALCX-USDT", "ALCXUSDT": "ALCX-USDT",
"ALGOEUR": "ALGO-EUR", "ALGOEUR": "ALGO-EUR",
"ALGOTRY": "ALGO-TRY",
"ALGOUSDC": "ALGO-USDC", "ALGOUSDC": "ALGO-USDC",
"ALGOUSDT": "ALGO-USDT", "ALGOUSDT": "ALGO-USDT",
"ALPHAUSDC": "ALPHA-USDC",
"ALPHAUSDT": "ALPHA-USDT", "ALPHAUSDT": "ALPHA-USDT",
"ANTUSDT": "ANT-USDT",
"APEEUR": "APE-EUR", "APEEUR": "APE-EUR",
"APEUSDC": "APE-USDC", "APEUSDC": "APE-USDC",
"APEUSDT": "APE-USDT", "APEUSDT": "APE-USDT",
"API3USDC": "API3-USDC",
"API3USDT": "API3-USDT", "API3USDT": "API3-USDT",
"APMUSDT": "APM-USDT",
"APTEUR": "APT-EUR", "APTEUR": "APT-EUR",
"APTUSDC": "APT-USDC", "APTUSDC": "APT-USDC",
"APTUSDT": "APT-USDT", "APTUSDT": "APT-USDT",
"ARBEUR": "ARB-EUR", "ARBEUR": "ARB-EUR",
"ARBUSDC": "ARB-USDC",
"ARBUSDT": "ARB-USDT", "ARBUSDT": "ARB-USDT",
"ARGUSDT": "ARG-USDT", "ARGUSDT": "ARG-USDT",
"ARKMUSDT": "ARKM-USDT",
"ARTYUSDT": "ARTY-USDT", "ARTYUSDT": "ARTY-USDT",
"ARUSDC": "AR-USDC", "ARUSDC": "AR-USDC",
"ARUSDT": "AR-USDT", "ARUSDT": "AR-USDT",
@ -51,54 +48,57 @@ var spotSymbolMap = map[string]string{
"ASTRUSDC": "ASTR-USDC", "ASTRUSDC": "ASTR-USDC",
"ASTRUSDT": "ASTR-USDT", "ASTRUSDT": "ASTR-USDT",
"ASTUSDT": "AST-USDT", "ASTUSDT": "AST-USDT",
"ATOMBTC": "ATOM-BTC", "ATHUSDT": "ATH-USDT",
"ATOMETH": "ATOM-ETH",
"ATOMEUR": "ATOM-EUR", "ATOMEUR": "ATOM-EUR",
"ATOMUSDC": "ATOM-USDC", "ATOMUSDC": "ATOM-USDC",
"ATOMUSDT": "ATOM-USDT", "ATOMUSDT": "ATOM-USDT",
"AUCTIONUSDC": "AUCTION-USDC", "AUCTIONUSDC": "AUCTION-USDC",
"AUCTIONUSDT": "AUCTION-USDT", "AUCTIONUSDT": "AUCTION-USDT",
"AVAXBTC": "AVAX-BTC",
"AVAXEUR": "AVAX-EUR", "AVAXEUR": "AVAX-EUR",
"AVAXUSDC": "AVAX-USDC", "AVAXUSDC": "AVAX-USDC",
"AVAXUSDT": "AVAX-USDT", "AVAXUSDT": "AVAX-USDT",
"AVIVEUSDT": "AVIVE-USDT", "AVIVEUSDT": "AVIVE-USDT",
"AXSEUR": "AXS-EUR", "AXSEUR": "AXS-EUR",
"AXSUSDC": "AXS-USDC",
"AXSUSDT": "AXS-USDT", "AXSUSDT": "AXS-USDT",
"AZYUSDT": "AZY-USDT",
"BABYDOGEUSDT": "BABYDOGE-USDT", "BABYDOGEUSDT": "BABYDOGE-USDT",
"BADGERUSDC": "BADGER-USDC",
"BADGERUSDT": "BADGER-USDT", "BADGERUSDT": "BADGER-USDT",
"BALEUR": "BAL-EUR", "BALEUR": "BAL-EUR",
"BALUSDC": "BAL-USDC",
"BALUSDT": "BAL-USDT", "BALUSDT": "BAL-USDT",
"BANDUSDC": "BAND-USDC",
"BANDUSDT": "BAND-USDT", "BANDUSDT": "BAND-USDT",
"BATEUR": "BAT-EUR", "BATEUR": "BAT-EUR",
"BATUSDC": "BAT-USDC",
"BATUSDT": "BAT-USDT", "BATUSDT": "BAT-USDT",
"BCHBTC": "BCH-BTC", "BCHBTC": "BCH-BTC",
"BCHUSDC": "BCH-USDC", "BCHUSDC": "BCH-USDC",
"BCHUSDT": "BCH-USDT", "BCHUSDT": "BCH-USDT",
"BETHETH": "BETH-ETH", "BETHETH": "BETH-ETH",
"BETHUSDT": "BETH-USDT", "BETHUSDT": "BETH-USDT",
"BICOUSDC": "BICO-USDC",
"BICOUSDT": "BICO-USDT", "BICOUSDT": "BICO-USDT",
"BIGTIMEUSDT": "BIGTIME-USDT", "BIGTIMEUSDT": "BIGTIME-USDT",
"BLOCKUSDT": "BLOCK-USDT", "BLOCKUSDT": "BLOCK-USDT",
"BLOKUSDT": "BLOK-USDT",
"BLURUSDC": "BLUR-USDC", "BLURUSDC": "BLUR-USDC",
"BLURUSDT": "BLUR-USDT", "BLURUSDT": "BLUR-USDT",
"BNBUSDC": "BNB-USDC", "BNBUSDC": "BNB-USDC",
"BNBUSDT": "BNB-USDT", "BNBUSDT": "BNB-USDT",
"BNTUSDC": "BNT-USDC",
"BNTUSDT": "BNT-USDT", "BNTUSDT": "BNT-USDT",
"BOMEUSDT": "BOME-USDT",
"BONEUSDT": "BONE-USDT", "BONEUSDT": "BONE-USDT",
"BONKUSDT": "BONK-USDT", "BONKUSDT": "BONK-USDT",
"BORAUSDT": "BORA-USDT", "BORAUSDT": "BORA-USDT",
"BORINGUSDT": "BORING-USDT", "BORINGUSDT": "BORING-USDT",
"BRWLUSDT": "BRWL-USDT",
"BSVBTC": "BSV-BTC", "BSVBTC": "BSV-BTC",
"BSVUSDC": "BSV-USDC", "BSVUSDC": "BSV-USDC",
"BSVUSDT": "BSV-USDT", "BSVUSDT": "BSV-USDT",
"BTCAUD": "BTC-AUD",
"BTCBRL": "BTC-BRL", "BTCBRL": "BTC-BRL",
"BTCDAI": "BTC-DAI", "BTCDAI": "BTC-DAI",
"BTCEUR": "BTC-EUR", "BTCEUR": "BTC-EUR",
"BTCEURT": "BTC-EURT",
"BTCTRY": "BTC-TRY", "BTCTRY": "BTC-TRY",
"BTCUSDC": "BTC-USDC", "BTCUSDC": "BTC-USDC",
"BTCUSDT": "BTC-USDT", "BTCUSDT": "BTC-USDT",
@ -106,16 +106,14 @@ var spotSymbolMap = map[string]string{
"BZZUSDT": "BZZ-USDT", "BZZUSDT": "BZZ-USDT",
"CEEKUSDT": "CEEK-USDT", "CEEKUSDT": "CEEK-USDT",
"CELOUSDT": "CELO-USDT", "CELOUSDT": "CELO-USDT",
"CELRUSDC": "CELR-USDC",
"CELRUSDT": "CELR-USDT", "CELRUSDT": "CELR-USDT",
"CELUSDC": "CEL-USDC",
"CELUSDT": "CEL-USDT",
"CETUSUSDC": "CETUS-USDC", "CETUSUSDC": "CETUS-USDC",
"CETUSUSDT": "CETUS-USDT", "CETUSUSDT": "CETUS-USDT",
"CFGUSDC": "CFG-USDC",
"CFGUSDT": "CFG-USDT", "CFGUSDT": "CFG-USDT",
"CFXUSDC": "CFX-USDC", "CFXUSDC": "CFX-USDC",
"CFXUSDT": "CFX-USDT", "CFXUSDT": "CFX-USDT",
"CGLUSDT": "CGL-USDT",
"CHZBTC": "CHZ-BTC",
"CHZEUR": "CHZ-EUR", "CHZEUR": "CHZ-EUR",
"CHZUSDC": "CHZ-USDC", "CHZUSDC": "CHZ-USDC",
"CHZUSDT": "CHZ-USDT", "CHZUSDT": "CHZ-USDT",
@ -124,40 +122,37 @@ var spotSymbolMap = map[string]string{
"COMPEUR": "COMP-EUR", "COMPEUR": "COMP-EUR",
"COMPUSDC": "COMP-USDC", "COMPUSDC": "COMP-USDC",
"COMPUSDT": "COMP-USDT", "COMPUSDT": "COMP-USDT",
"CONVUSDT": "CONV-USDT",
"CORETRY": "CORE-TRY",
"COREUSDT": "CORE-USDT", "COREUSDT": "CORE-USDT",
"CQTUSDT": "CQT-USDT",
"CROBTC": "CRO-BTC",
"CROEUR": "CRO-EUR", "CROEUR": "CRO-EUR",
"CROUSDC": "CRO-USDC", "CROUSDC": "CRO-USDC",
"CROUSDT": "CRO-USDT", "CROUSDT": "CRO-USDT",
"CRVBTC": "CRV-BTC",
"CRVEUR": "CRV-EUR", "CRVEUR": "CRV-EUR",
"CRVUSDC": "CRV-USDC", "CRVUSDC": "CRV-USDC",
"CRVUSDT": "CRV-USDT", "CRVUSDT": "CRV-USDT",
"CSPRUSDC": "CSPR-USDC", "CSPRUSDC": "CSPR-USDC",
"CSPRUSDT": "CSPR-USDT", "CSPRUSDT": "CSPR-USDT",
"CTCUSDC": "CTC-USDC",
"CTCUSDT": "CTC-USDT", "CTCUSDT": "CTC-USDT",
"CTXCUSDC": "CTXC-USDC", "CTXCUSDC": "CTXC-USDC",
"CTXCUSDT": "CTXC-USDT", "CTXCUSDT": "CTXC-USDT",
"CVCUSDC": "CVC-USDC",
"CVCUSDT": "CVC-USDT", "CVCUSDT": "CVC-USDT",
"CVXUSDC": "CVX-USDC",
"CVXUSDT": "CVX-USDT", "CVXUSDT": "CVX-USDT",
"CXTUSDT": "CXT-USDT",
"DAIUSDC": "DAI-USDC",
"DAIUSDT": "DAI-USDT", "DAIUSDT": "DAI-USDT",
"DAOUSDT": "DAO-USDT", "DAOUSDT": "DAO-USDT",
"DCRUSDT": "DCR-USDT", "DEGENUSDT": "DEGEN-USDT",
"DEPUSDT": "DEP-USDT", "DEPUSDT": "DEP-USDT",
"DGBUSDT": "DGB-USDT", "DGBUSDT": "DGB-USDT",
"DIAUSDT": "DIA-USDT", "DIAUSDT": "DIA-USDT",
"DMAILUSDT": "DMAIL-USDT", "DMAILUSDT": "DMAIL-USDT",
"DOGEBTC": "DOGE-BTC",
"DOGEETH": "DOGE-ETH",
"DOGEEUR": "DOGE-EUR", "DOGEEUR": "DOGE-EUR",
"DOGEUSDC": "DOGE-USDC", "DOGEUSDC": "DOGE-USDC",
"DOGEUSDT": "DOGE-USDT", "DOGEUSDT": "DOGE-USDT",
"DOGSUSDT": "DOGS-USDT",
"DORAUSDT": "DORA-USDT", "DORAUSDT": "DORA-USDT",
"DOSEUSDT": "DOSE-USDT",
"DOTBTC": "DOT-BTC",
"DOTEUR": "DOT-EUR", "DOTEUR": "DOT-EUR",
"DOTUSDC": "DOT-USDC", "DOTUSDC": "DOT-USDC",
"DOTUSDT": "DOT-USDT", "DOTUSDT": "DOT-USDT",
@ -169,47 +164,43 @@ var spotSymbolMap = map[string]string{
"EGLDUSDT": "EGLD-USDT", "EGLDUSDT": "EGLD-USDT",
"ELFUSDT": "ELF-USDT", "ELFUSDT": "ELF-USDT",
"ELONUSDT": "ELON-USDT", "ELONUSDT": "ELON-USDT",
"EMUSDT": "EM-USDT",
"ENJUSDT": "ENJ-USDT", "ENJUSDT": "ENJ-USDT",
"ENSUSDC": "ENS-USDC",
"ENSUSDT": "ENS-USDT", "ENSUSDT": "ENS-USDT",
"EOSBTC": "EOS-BTC",
"EOSETH": "EOS-ETH",
"EOSEUR": "EOS-EUR", "EOSEUR": "EOS-EUR",
"EOSUSDC": "EOS-USDC", "EOSUSDC": "EOS-USDC",
"EOSUSDT": "EOS-USDT", "EOSUSDT": "EOS-USDT",
"ERNUSDT": "ERN-USDT", "ERNUSDT": "ERN-USDT",
"ETCBTC": "ETC-BTC",
"ETCUSDC": "ETC-USDC", "ETCUSDC": "ETC-USDC",
"ETCUSDT": "ETC-USDT", "ETCUSDT": "ETC-USDT",
"ETHAUD": "ETH-AUD",
"ETHBRL": "ETH-BRL", "ETHBRL": "ETH-BRL",
"ETHBTC": "ETH-BTC", "ETHBTC": "ETH-BTC",
"ETHDAI": "ETH-DAI", "ETHDAI": "ETH-DAI",
"ETHEUR": "ETH-EUR", "ETHEUR": "ETH-EUR",
"ETHEURT": "ETH-EURT",
"ETHFIUSDT": "ETHFI-USDT", "ETHFIUSDT": "ETHFI-USDT",
"ETHTRY": "ETH-TRY", "ETHTRY": "ETH-TRY",
"ETHUSDC": "ETH-USDC", "ETHUSDC": "ETH-USDC",
"ETHUSDT": "ETH-USDT", "ETHUSDT": "ETH-USDT",
"ETHWUSDC": "ETHW-USDC", "ETHWUSDC": "ETHW-USDC",
"ETHWUSDT": "ETHW-USDT", "ETHWUSDT": "ETHW-USDT",
"EURTUSDT": "EURT-USDT",
"FETEUR": "FET-EUR", "FETEUR": "FET-EUR",
"FETUSDT": "FET-USDT", "FETUSDT": "FET-USDT",
"FILBTC": "FIL-BTC",
"FILETH": "FIL-ETH",
"FILUSDC": "FIL-USDC", "FILUSDC": "FIL-USDC",
"FILUSDT": "FIL-USDT", "FILUSDT": "FIL-USDT",
"FITFIUSDT": "FITFI-USDT",
"FLMUSDT": "FLM-USDT", "FLMUSDT": "FLM-USDT",
"FLOKIUSDC": "FLOKI-USDC", "FLOKIUSDC": "FLOKI-USDC",
"FLOKIUSDT": "FLOKI-USDT", "FLOKIUSDT": "FLOKI-USDT",
"FLOWEUR": "FLOW-EUR", "FLOWEUR": "FLOW-EUR",
"FLOWUSDC": "FLOW-USDC",
"FLOWUSDT": "FLOW-USDT", "FLOWUSDT": "FLOW-USDT",
"FLREUR": "FLR-EUR", "FLREUR": "FLR-EUR",
"FLRUSDC": "FLR-USDC", "FLRUSDC": "FLR-USDC",
"FLRUSDT": "FLR-USDT", "FLRUSDT": "FLR-USDT",
"FORTHUSDC": "FORTH-USDC",
"FORTHUSDT": "FORTH-USDT", "FORTHUSDT": "FORTH-USDT",
"FOXYUSDT": "FOXY-USDT", "FOXYUSDT": "FOXY-USDT",
"FRONTUSDC": "FRONT-USDC",
"FRONTUSDT": "FRONT-USDT", "FRONTUSDT": "FRONT-USDT",
"FTMEUR": "FTM-EUR", "FTMEUR": "FTM-EUR",
"FTMUSDC": "FTM-USDC", "FTMUSDC": "FTM-USDC",
@ -218,28 +209,29 @@ var spotSymbolMap = map[string]string{
"FXSUSDT": "FXS-USDT", "FXSUSDT": "FXS-USDT",
"GALAUSDC": "GALA-USDC", "GALAUSDC": "GALA-USDC",
"GALAUSDT": "GALA-USDT", "GALAUSDT": "GALA-USDT",
"GALEUR": "GAL-EUR",
"GALFTUSDT": "GALFT-USDT", "GALFTUSDT": "GALFT-USDT",
"GALUSDT": "GAL-USDT",
"GARIUSDT": "GARI-USDT",
"GASUSDT": "GAS-USDT", "GASUSDT": "GAS-USDT",
"GEARUSDT": "GEAR-USDT", "GEARUSDT": "GEAR-USDT",
"GFTUSDC": "GFT-USDC",
"GFTUSDT": "GFT-USDT", "GFTUSDT": "GFT-USDT",
"GHSTUSDC": "GHST-USDC",
"GHSTUSDT": "GHST-USDT", "GHSTUSDT": "GHST-USDT",
"GLMRUSDC": "GLMR-USDC",
"GLMRUSDT": "GLMR-USDT", "GLMRUSDT": "GLMR-USDT",
"GLMUSDC": "GLM-USDC", "GLMUSDC": "GLM-USDC",
"GLMUSDT": "GLM-USDT", "GLMUSDT": "GLM-USDT",
"GMTUSDC": "GMT-USDC",
"GMTUSDT": "GMT-USDT", "GMTUSDT": "GMT-USDT",
"GMXUSDT": "GMX-USDT", "GMXUSDT": "GMX-USDT",
"GOALUSDT": "GOAL-USDT", "GOALUSDT": "GOAL-USDT",
"GODSUSDT": "GODS-USDT", "GODSUSDT": "GODS-USDT",
"GOGUSDT": "GOG-USDT", "GOGUSDT": "GOG-USDT",
"GPTUSDT": "GPT-USDT", "GPTUSDT": "GPT-USDT",
"GRTBTC": "GRT-BTC",
"GRTEUR": "GRT-EUR", "GRTEUR": "GRT-EUR",
"GRTUSDC": "GRT-USDC", "GRTUSDC": "GRT-USDC",
"GRTUSDT": "GRT-USDT", "GRTUSDT": "GRT-USDT",
"HBARBTC": "HBAR-BTC", "GUSDC": "G-USDC",
"GUSDT": "G-USDT",
"HBAREUR": "HBAR-EUR", "HBAREUR": "HBAR-EUR",
"HBARUSDC": "HBAR-USDC", "HBARUSDC": "HBAR-USDC",
"HBARUSDT": "HBAR-USDT", "HBARUSDT": "HBAR-USDT",
@ -247,11 +239,12 @@ var spotSymbolMap = map[string]string{
"ICPEUR": "ICP-EUR", "ICPEUR": "ICP-EUR",
"ICPUSDC": "ICP-USDC", "ICPUSDC": "ICP-USDC",
"ICPUSDT": "ICP-USDT", "ICPUSDT": "ICP-USDT",
"ICXUSDC": "ICX-USDC",
"ICXUSDT": "ICX-USDT", "ICXUSDT": "ICX-USDT",
"IDUSDT": "ID-USDT", "IDUSDT": "ID-USDT",
"IGUUSDT": "IGU-USDT",
"ILVUSDT": "ILV-USDT", "ILVUSDT": "ILV-USDT",
"IMXEUR": "IMX-EUR", "IMXEUR": "IMX-EUR",
"IMXUSDC": "IMX-USDC",
"IMXUSDT": "IMX-USDT", "IMXUSDT": "IMX-USDT",
"INJEUR": "INJ-EUR", "INJEUR": "INJ-EUR",
"INJUSDT": "INJ-USDT", "INJUSDT": "INJ-USDT",
@ -267,44 +260,44 @@ var spotSymbolMap = map[string]string{
"JTOUSDT": "JTO-USDT", "JTOUSDT": "JTO-USDT",
"JUPUSDT": "JUP-USDT", "JUPUSDT": "JUP-USDT",
"KANUSDT": "KAN-USDT", "KANUSDT": "KAN-USDT",
"KCALUSDT": "KCAL-USDT",
"KDAUSDC": "KDA-USDC", "KDAUSDC": "KDA-USDC",
"KDAUSDT": "KDA-USDT", "KDAUSDT": "KDA-USDT",
"KINEUSDT": "KINE-USDT", "KINEUSDT": "KINE-USDT",
"KISHUUSDT": "KISHU-USDT", "KISHUUSDT": "KISHU-USDT",
"KLAYUSDC": "KLAY-USDC", "KLAYUSDC": "KLAY-USDC",
"KLAYUSDT": "KLAY-USDT", "KLAYUSDT": "KLAY-USDT",
"KNCUSDC": "KNC-USDC",
"KNCUSDT": "KNC-USDT", "KNCUSDT": "KNC-USDT",
"KP3RUSDC": "KP3R-USDC",
"KP3RUSDT": "KP3R-USDT", "KP3RUSDT": "KP3R-USDT",
"KSMUSDC": "KSM-USDC",
"KSMUSDT": "KSM-USDT", "KSMUSDT": "KSM-USDT",
"LAMBUSDT": "LAMB-USDT", "LAMBUSDT": "LAMB-USDT",
"LATUSDT": "LAT-USDT", "LATUSDT": "LAT-USDT",
"LBRUSDT": "LBR-USDT", "LBRUSDT": "LBR-USDT",
"LDOEUR": "LDO-EUR", "LDOEUR": "LDO-EUR",
"LDOUSDC": "LDO-USDC",
"LDOUSDT": "LDO-USDT", "LDOUSDT": "LDO-USDT",
"LEASHUSDT": "LEASH-USDT", "LEASHUSDT": "LEASH-USDT",
"LEOUSDT": "LEO-USDT", "LEOUSDT": "LEO-USDT",
"LETUSDT": "LET-USDT",
"LHINUUSDT": "LHINU-USDT",
"LINGUSDT": "LING-USDT",
"LINKBTC": "LINK-BTC",
"LINKETH": "LINK-ETH",
"LINKEUR": "LINK-EUR", "LINKEUR": "LINK-EUR",
"LINKUSDC": "LINK-USDC", "LINKUSDC": "LINK-USDC",
"LINKUSDT": "LINK-USDT", "LINKUSDT": "LINK-USDT",
"LITHUSDC": "LITH-USDC",
"LITHUSDT": "LITH-USDT", "LITHUSDT": "LITH-USDT",
"LONUSDT": "LON-USDT", "LONUSDT": "LON-USDT",
"LOOKSUSDC": "LOOKS-USDC", "LOOKSUSDC": "LOOKS-USDC",
"LOOKSUSDT": "LOOKS-USDT", "LOOKSUSDT": "LOOKS-USDT",
"LPTUSDC": "LPT-USDC",
"LPTUSDT": "LPT-USDT", "LPTUSDT": "LPT-USDT",
"LQTYUSDC": "LQTY-USDC",
"LQTYUSDT": "LQTY-USDT", "LQTYUSDT": "LQTY-USDT",
"LRCUSDC": "LRC-USDC", "LRCUSDC": "LRC-USDC",
"LRCUSDT": "LRC-USDT", "LRCUSDT": "LRC-USDT",
"LSKUSDC": "LSK-USDC",
"LSKUSDT": "LSK-USDT", "LSKUSDT": "LSK-USDT",
"LTCBTC": "LTC-BTC", "LTCBTC": "LTC-BTC",
"LTCETH": "LTC-ETH",
"LTCEUR": "LTC-EUR", "LTCEUR": "LTC-EUR",
"LTCTRY": "LTC-TRY",
"LTCUSDC": "LTC-USDC", "LTCUSDC": "LTC-USDC",
"LTCUSDT": "LTC-USDT", "LTCUSDT": "LTC-USDT",
"LUNAUSDC": "LUNA-USDC", "LUNAUSDC": "LUNA-USDC",
@ -314,19 +307,16 @@ var spotSymbolMap = map[string]string{
"LUNCUSDT": "LUNC-USDT", "LUNCUSDT": "LUNC-USDT",
"MAGICUSDC": "MAGIC-USDC", "MAGICUSDC": "MAGIC-USDC",
"MAGICUSDT": "MAGIC-USDT", "MAGICUSDT": "MAGIC-USDT",
"MANABTC": "MANA-BTC",
"MANAEUR": "MANA-EUR", "MANAEUR": "MANA-EUR",
"MANAUSDC": "MANA-USDC", "MANAUSDC": "MANA-USDC",
"MANAUSDT": "MANA-USDT", "MANAUSDT": "MANA-USDT",
"MASKUSDC": "MASK-USDC", "MASKUSDC": "MASK-USDC",
"MASKUSDT": "MASK-USDT", "MASKUSDT": "MASK-USDT",
"MATICBTC": "MATIC-BTC", "MAXUSDT": "MAX-USDT",
"MATICEUR": "MATIC-EUR",
"MATICUSDC": "MATIC-USDC",
"MATICUSDT": "MATIC-USDT",
"MDTUSDT": "MDT-USDT", "MDTUSDT": "MDT-USDT",
"MEMEUSDT": "MEME-USDT", "MEMEUSDT": "MEME-USDT",
"MENGOUSDT": "MENGO-USDT", "MENGOUSDT": "MENGO-USDT",
"MERLUSDC": "MERL-USDC",
"MERLUSDT": "MERL-USDT", "MERLUSDT": "MERL-USDT",
"METISUSDC": "METIS-USDC", "METISUSDC": "METIS-USDC",
"METISUSDT": "METIS-USDT", "METISUSDT": "METIS-USDT",
@ -335,41 +325,35 @@ var spotSymbolMap = map[string]string{
"MINAEUR": "MINA-EUR", "MINAEUR": "MINA-EUR",
"MINAUSDC": "MINA-USDC", "MINAUSDC": "MINA-USDC",
"MINAUSDT": "MINA-USDT", "MINAUSDT": "MINA-USDT",
"MKRBTC": "MKR-BTC",
"MKREUR": "MKR-EUR", "MKREUR": "MKR-EUR",
"MKRUSDC": "MKR-USDC", "MKRUSDC": "MKR-USDC",
"MKRUSDT": "MKR-USDT", "MKRUSDT": "MKR-USDT",
"MLNUSDC": "MLN-USDC",
"MLNUSDT": "MLN-USDT", "MLNUSDT": "MLN-USDT",
"MOVEZUSDT": "MOVEZ-USDT", "MOVRUSDC": "MOVR-USDC",
"MOVRUSDT": "MOVR-USDT", "MOVRUSDT": "MOVR-USDT",
"MRSTUSDT": "MRST-USDT",
"MSNUSDT": "MSN-USDT",
"MXCUSDT": "MXC-USDT", "MXCUSDT": "MXC-USDT",
"MYRIAUSDT": "MYRIA-USDT", "MYRIAUSDT": "MYRIA-USDT",
"NEARBTC": "NEAR-BTC",
"NEARUSDC": "NEAR-USDC", "NEARUSDC": "NEAR-USDC",
"NEARUSDT": "NEAR-USDT", "NEARUSDT": "NEAR-USDT",
"NEOBTC": "NEO-BTC",
"NEOUSDC": "NEO-USDC", "NEOUSDC": "NEO-USDC",
"NEOUSDT": "NEO-USDT", "NEOUSDT": "NEO-USDT",
"NFTUSDT": "NFT-USDT", "NFTUSDT": "NFT-USDT",
"NMRUSDC": "NMR-USDC",
"NMRUSDT": "NMR-USDT", "NMRUSDT": "NMR-USDT",
"NOTUSDT": "NOT-USDT",
"NULSUSDT": "NULS-USDT", "NULSUSDT": "NULS-USDT",
"NYMUSDT": "NYM-USDT",
"OASUSDT": "OAS-USDT", "OASUSDT": "OAS-USDT",
"OKBBTC": "OKB-BTC", "OKBBTC": "OKB-BTC",
"OKBETH": "OKB-ETH",
"OKBUSDC": "OKB-USDC", "OKBUSDC": "OKB-USDC",
"OKBUSDT": "OKB-USDT", "OKBUSDT": "OKB-USDT",
"OKTBTC": "OKT-BTC",
"OKTETH": "OKT-ETH",
"OKTUSDC": "OKT-USDC", "OKTUSDC": "OKT-USDC",
"OKTUSDT": "OKT-USDT", "OKTUSDT": "OKT-USDT",
"OMGUSDT": "OMG-USDT",
"OMIUSDT": "OMI-USDT", "OMIUSDT": "OMI-USDT",
"OMNUSDT": "OMN-USDT",
"OMUSDC": "OM-USDC", "OMUSDC": "OM-USDC",
"OMUSDT": "OM-USDT", "OMUSDT": "OM-USDT",
"ONDOUSDC": "ONDO-USDC",
"ONDOUSDT": "ONDO-USDT",
"ONEUSDT": "ONE-USDT", "ONEUSDT": "ONE-USDT",
"ONTUSDT": "ONT-USDT", "ONTUSDT": "ONT-USDT",
"OPEUR": "OP-EUR", "OPEUR": "OP-EUR",
@ -379,34 +363,41 @@ var spotSymbolMap = map[string]string{
"ORBUSDT": "ORB-USDT", "ORBUSDT": "ORB-USDT",
"ORDIUSDC": "ORDI-USDC", "ORDIUSDC": "ORDI-USDC",
"ORDIUSDT": "ORDI-USDT", "ORDIUSDT": "ORDI-USDT",
"OXTUSDC": "OXT-USDC",
"OXTUSDT": "OXT-USDT", "OXTUSDT": "OXT-USDT",
"PCIUSDT": "PCI-USDT", "PEOPLEUSDC": "PEOPLE-USDC",
"PEOPLEUSDT": "PEOPLE-USDT", "PEOPLEUSDT": "PEOPLE-USDT",
"PEPEBRL": "PEPE-BRL", "PEPEBRL": "PEPE-BRL",
"PEPEUSDC": "PEPE-USDC", "PEPEUSDC": "PEPE-USDC",
"PEPEUSDT": "PEPE-USDT", "PEPEUSDT": "PEPE-USDT",
"PERPUSDC": "PERP-USDC",
"PERPUSDT": "PERP-USDT", "PERPUSDT": "PERP-USDT",
"PHAUSDC": "PHA-USDC",
"PHAUSDT": "PHA-USDT", "PHAUSDT": "PHA-USDT",
"PITUSDT": "PIT-USDT", "PIXELUSDT": "PIXEL-USDT",
"POLSUSDT": "POLS-USDT", "POLUSDC": "POL-USDC",
"POLUSDT": "POL-USDT",
"POLYDOGEUSDT": "POLYDOGE-USDT", "POLYDOGEUSDT": "POLYDOGE-USDT",
"PORUSDT": "POR-USDT", "PORUSDT": "POR-USDT",
"PRCLUSDT": "PRCL-USDT", "PRCLUSDT": "PRCL-USDT",
"PRQUSDT": "PRQ-USDT", "PRQUSDT": "PRQ-USDT",
"PSTAKEUSDC": "PSTAKE-USDC",
"PSTAKEUSDT": "PSTAKE-USDT", "PSTAKEUSDT": "PSTAKE-USDT",
"PYTHUSDC": "PYTH-USDC",
"PYTHUSDT": "PYTH-USDT", "PYTHUSDT": "PYTH-USDT",
"QTUMBTC": "QTUM-BTC", "QTUMUSDC": "QTUM-USDC",
"QTUMUSDT": "QTUM-USDT", "QTUMUSDT": "QTUM-USDT",
"RACAUSDT": "RACA-USDT", "RACAUSDT": "RACA-USDT",
"RADARUSDT": "RADAR-USDT", "RADARUSDT": "RADAR-USDT",
"RAYUSDT": "RAY-USDT", "RAYUSDT": "RAY-USDT",
"RDNTUSDC": "RDNT-USDC", "RDNTUSDC": "RDNT-USDC",
"RDNTUSDT": "RDNT-USDT", "RDNTUSDT": "RDNT-USDT",
"RENDERUSDC": "RENDER-USDC",
"RENDERUSDT": "RENDER-USDT",
"RENUSDC": "REN-USDC",
"RENUSDT": "REN-USDT", "RENUSDT": "REN-USDT",
"REPUSDT": "REP-USDT",
"REVVUSDT": "REVV-USDT", "REVVUSDT": "REVV-USDT",
"RIOUSDT": "RIO-USDT", "RIOUSDT": "RIO-USDT",
"RNDRUSDT": "RNDR-USDT",
"RONUSDC": "RON-USDC", "RONUSDC": "RON-USDC",
"RONUSDT": "RON-USDT", "RONUSDT": "RON-USDT",
"RPLUSDC": "RPL-USDC", "RPLUSDC": "RPL-USDC",
@ -421,17 +412,17 @@ var spotSymbolMap = map[string]string{
"SANDEUR": "SAND-EUR", "SANDEUR": "SAND-EUR",
"SANDUSDC": "SAND-USDC", "SANDUSDC": "SAND-USDC",
"SANDUSDT": "SAND-USDT", "SANDUSDT": "SAND-USDT",
"SATSUSDC": "SATS-USDC",
"SATSUSDT": "SATS-USDT", "SATSUSDT": "SATS-USDT",
"SCUSDC": "SC-USDC",
"SCUSDT": "SC-USDT", "SCUSDT": "SC-USDT",
"SDUSDT": "SD-USDT", "SDUSDT": "SD-USDT",
"SHIBBTC": "SHIB-BTC",
"SHIBEUR": "SHIB-EUR", "SHIBEUR": "SHIB-EUR",
"SHIBUSDC": "SHIB-USDC", "SHIBUSDC": "SHIB-USDC",
"SHIBUSDT": "SHIB-USDT", "SHIBUSDT": "SHIB-USDT",
"SISUSDT": "SIS-USDT", "SISUSDT": "SIS-USDT",
"SKEBUSDT": "SKEB-USDT",
"SKLUSDT": "SKL-USDT", "SKLUSDT": "SKL-USDT",
"SLNUSDT": "SLN-USDT", "SLERFUSDT": "SLERF-USDT",
"SLPUSDT": "SLP-USDT", "SLPUSDT": "SLP-USDT",
"SNTUSDT": "SNT-USDT", "SNTUSDT": "SNT-USDT",
"SNXEUR": "SNX-EUR", "SNXEUR": "SNX-EUR",
@ -442,11 +433,9 @@ var spotSymbolMap = map[string]string{
"SOLEUR": "SOL-EUR", "SOLEUR": "SOL-EUR",
"SOLUSDC": "SOL-USDC", "SOLUSDC": "SOL-USDC",
"SOLUSDT": "SOL-USDT", "SOLUSDT": "SOL-USDT",
"SPELLUSDT": "SPELL-USDT",
"SPURSUSDT": "SPURS-USDT", "SPURSUSDT": "SPURS-USDT",
"SSVUSDT": "SSV-USDT", "SSVUSDT": "SSV-USDT",
"SSWPUSDT": "SSWP-USDT", "SSWPUSDT": "SSWP-USDT",
"STARLUSDT": "STARL-USDT",
"STCUSDT": "STC-USDT", "STCUSDT": "STC-USDT",
"STETHETH": "STETH-ETH", "STETHETH": "STETH-ETH",
"STETHUSDT": "STETH-USDT", "STETHUSDT": "STETH-USDT",
@ -461,7 +450,6 @@ var spotSymbolMap = map[string]string{
"SUIEUR": "SUI-EUR", "SUIEUR": "SUI-EUR",
"SUIUSDC": "SUI-USDC", "SUIUSDC": "SUI-USDC",
"SUIUSDT": "SUI-USDT", "SUIUSDT": "SUI-USDT",
"SUNUSDT": "SUN-USDT",
"SUSHIEUR": "SUSHI-EUR", "SUSHIEUR": "SUSHI-EUR",
"SUSHIUSDC": "SUSHI-USDC", "SUSHIUSDC": "SUSHI-USDC",
"SUSHIUSDT": "SUSHI-USDT", "SUSHIUSDT": "SUSHI-USDT",
@ -469,9 +457,8 @@ var spotSymbolMap = map[string]string{
"SWEATUSDT": "SWEAT-USDT", "SWEATUSDT": "SWEAT-USDT",
"SWFTCUSDT": "SWFTC-USDT", "SWFTCUSDT": "SWFTC-USDT",
"TAKIUSDT": "TAKI-USDT", "TAKIUSDT": "TAKI-USDT",
"TAMAUSDT": "TAMA-USDT",
"THETAUSDT": "THETA-USDT", "THETAUSDT": "THETA-USDT",
"THGUSDT": "THG-USDT", "TIAUSDC": "TIA-USDC",
"TIAUSDT": "TIA-USDT", "TIAUSDT": "TIA-USDT",
"TNSRUSDT": "TNSR-USDT", "TNSRUSDT": "TNSR-USDT",
"TONEUR": "TON-EUR", "TONEUR": "TON-EUR",
@ -479,28 +466,30 @@ var spotSymbolMap = map[string]string{
"TONUSDT": "TON-USDT", "TONUSDT": "TON-USDT",
"TRAUSDT": "TRA-USDT", "TRAUSDT": "TRA-USDT",
"TRBUSDT": "TRB-USDT", "TRBUSDT": "TRB-USDT",
"TRXBTC": "TRX-BTC",
"TRXETH": "TRX-ETH",
"TRXEUR": "TRX-EUR", "TRXEUR": "TRX-EUR",
"TRXUSDC": "TRX-USDC", "TRXUSDC": "TRX-USDC",
"TRXUSDT": "TRX-USDT", "TRXUSDT": "TRX-USDT",
"TUPUSDT": "TUP-USDT",
"TURBOUSDT": "TURBO-USDT", "TURBOUSDT": "TURBO-USDT",
"TUSDC": "T-USDC",
"TUSDT": "T-USDT", "TUSDT": "T-USDT",
"ULTIUSDT": "ULTI-USDT",
"UMAUSDC": "UMA-USDC",
"UMAUSDT": "UMA-USDT", "UMAUSDT": "UMA-USDT",
"UNIBTC": "UNI-BTC",
"UNIEUR": "UNI-EUR", "UNIEUR": "UNI-EUR",
"UNIUSDC": "UNI-USDC", "UNIUSDC": "UNI-USDC",
"UNIUSDT": "UNI-USDT", "UNIUSDT": "UNI-USDT",
"USDCAUD": "USDC-AUD",
"USDCBRL": "USDC-BRL", "USDCBRL": "USDC-BRL",
"USDCEUR": "USDC-EUR", "USDCEUR": "USDC-EUR",
"USDCUSDT": "USDC-USDT", "USDCUSDT": "USDC-USDT",
"USDTAUD": "USDT-AUD",
"USDTBRL": "USDT-BRL", "USDTBRL": "USDT-BRL",
"USDTEUR": "USDT-EUR", "USDTEUR": "USDT-EUR",
"USDTTRY": "USDT-TRY", "USDTTRY": "USDT-TRY",
"USDTUSDC": "USDT-USDC", "USDTUSDC": "USDT-USDC",
"USTCUSDT": "USTC-USDT", "USTCUSDT": "USTC-USDT",
"UTKUSDT": "UTK-USDT", "UTKUSDT": "UTK-USDT",
"UXLINKUSDT": "UXLINK-USDT",
"VELAUSDT": "VELA-USDT", "VELAUSDT": "VELA-USDT",
"VELODROMEUSDT": "VELODROME-USDT", "VELODROMEUSDT": "VELODROME-USDT",
"VELOUSDC": "VELO-USDC", "VELOUSDC": "VELO-USDC",
@ -511,50 +500,54 @@ var spotSymbolMap = map[string]string{
"WAXPUSDC": "WAXP-USDC", "WAXPUSDC": "WAXP-USDC",
"WAXPUSDT": "WAXP-USDT", "WAXPUSDT": "WAXP-USDT",
"WBTCBTC": "WBTC-BTC", "WBTCBTC": "WBTC-BTC",
"WBTCUSDC": "WBTC-USDC",
"WBTCUSDT": "WBTC-USDT", "WBTCUSDT": "WBTC-USDT",
"WIFEUR": "WIF-EUR", "WIFEUR": "WIF-EUR",
"WIFIUSDT": "WIFI-USDT", "WIFIUSDT": "WIFI-USDT",
"WIFUSDC": "WIF-USDC", "WIFUSDC": "WIF-USDC",
"WIFUSDT": "WIF-USDT", "WIFUSDT": "WIF-USDT",
"WINUSDT": "WIN-USDT", "WINUSDT": "WIN-USDT",
"WLDUSDC": "WLD-USDC",
"WLDUSDT": "WLD-USDT", "WLDUSDT": "WLD-USDT",
"WNCGUSDT": "WNCG-USDT",
"WOOEUR": "WOO-EUR", "WOOEUR": "WOO-EUR",
"WOOUSDT": "WOO-USDT", "WOOUSDT": "WOO-USDT",
"WSMUSDT": "WSM-USDT", "WSMUSDT": "WSM-USDT",
"WUSDC": "W-USDC",
"WUSDT": "W-USDT", "WUSDT": "W-USDT",
"WXTUSDT": "WXT-USDT", "WXTUSDT": "WXT-USDT",
"XAUTUSDT": "XAUT-USDT", "XAUTUSDT": "XAUT-USDT",
"XCHBTC": "XCH-BTC",
"XCHUSDT": "XCH-USDT", "XCHUSDT": "XCH-USDT",
"XECUSDT": "XEC-USDT",
"XEMUSDT": "XEM-USDT",
"XLMBTC": "XLM-BTC",
"XLMEUR": "XLM-EUR", "XLMEUR": "XLM-EUR",
"XLMUSDC": "XLM-USDC", "XLMUSDC": "XLM-USDC",
"XLMUSDT": "XLM-USDT", "XLMUSDT": "XLM-USDT",
"XNOUSDC": "XNO-USDC",
"XNOUSDT": "XNO-USDT", "XNOUSDT": "XNO-USDT",
"XPRUSDT": "XPR-USDT",
"XRPBTC": "XRP-BTC",
"XRPETH": "XRP-ETH",
"XRPEUR": "XRP-EUR", "XRPEUR": "XRP-EUR",
"XRPTRY": "XRP-TRY",
"XRPUSDC": "XRP-USDC", "XRPUSDC": "XRP-USDC",
"XRPUSDT": "XRP-USDT", "XRPUSDT": "XRP-USDT",
"XRUSDT": "XR-USDT",
"XTZEUR": "XTZ-EUR", "XTZEUR": "XTZ-EUR",
"XTZUSDC": "XTZ-USDC",
"XTZUSDT": "XTZ-USDT", "XTZUSDT": "XTZ-USDT",
"YFIUSDC": "YFI-USDC",
"YFIUSDT": "YFI-USDT", "YFIUSDT": "YFI-USDT",
"YGGEUR": "YGG-EUR", "YGGEUR": "YGG-EUR",
"YGGUSDC": "YGG-USDC", "YGGUSDC": "YGG-USDC",
"YGGUSDT": "YGG-USDT", "YGGUSDT": "YGG-USDT",
"ZBCNUSDT": "ZBCN-USDT", "ZBCNUSDT": "ZBCN-USDT",
"ZENTUSDC": "ZENT-USDC",
"ZENTUSDT": "ZENT-USDT", "ZENTUSDT": "ZENT-USDT",
"ZEROUSDC": "ZERO-USDC",
"ZEROUSDT": "ZERO-USDT", "ZEROUSDT": "ZERO-USDT",
"ZETAUSDT": "ZETA-USDT", "ZETAUSDT": "ZETA-USDT",
"ZEUSUSDT": "ZEUS-USDT", "ZEUSUSDT": "ZEUS-USDT",
"ZILUSDC": "ZIL-USDC", "ZILUSDC": "ZIL-USDC",
"ZILUSDT": "ZIL-USDT", "ZILUSDT": "ZIL-USDT",
"ZKJUSDT": "ZKJ-USDT",
"ZKUSDC": "ZK-USDC",
"ZKUSDT": "ZK-USDT", "ZKUSDT": "ZK-USDT",
"ZROUSDC": "ZRO-USDC",
"ZROUSDT": "ZRO-USDT",
"ZRXUSDC": "ZRX-USDC",
"ZRXUSDT": "ZRX-USDT", "ZRXUSDT": "ZRX-USDT",
} }

View File

@ -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
}

View File

@ -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
}

View File

@ -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...)

View File

@ -1,4 +1,4 @@
package priceresolver package pricesolver
import ( import (
"testing" "testing"

View File

@ -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),
HaltDuration: types.Duration(1 * time.Hour),
strategyID: strategyID, strategyID: strategyID,
strategyInstance: strategyInstance, strategyInstance: strategyInstance,
metricsLabels: prometheus.Labels{"strategy": strategyID, "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))
} }

View File

@ -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 {

View File

@ -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,

View File

@ -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) {
if s.Bollinger != nil {
session.Subscribe(types.KLineChannel, s.Symbol, types.SubscribeOptions{Interval: s.Bollinger.Interval}) 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())
if s.Bollinger != nil {
s.boll = session.Indicators(s.Symbol).BOLL(s.Bollinger.IntervalWindow, s.Bollinger.BandWidth) 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,
} }

View File

@ -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 {

View File

@ -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)

View File

@ -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())

View File

@ -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)
} }

View File

@ -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 {

View File

@ -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 {

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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) {

View File

@ -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()

View File

@ -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{})

View File

@ -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{

View File

@ -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) {

View 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,
)
}

View 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
}

View 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