mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-25 00:05:15 +00:00
Merge branch 'main' into feature/336-kline-table
This commit is contained in:
commit
776f82fcd5
1
.github/workflows/release.yml
vendored
1
.github/workflows/release.yml
vendored
|
@ -27,7 +27,6 @@ jobs:
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
npm install --global yarn
|
npm install --global yarn
|
||||||
(cd frontend && yarn install)
|
|
||||||
make dist VERSION=${{ steps.get_version.outputs.VERSION }}
|
make dist VERSION=${{ steps.get_version.outputs.VERSION }}
|
||||||
shell: bash
|
shell: bash
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -34,3 +34,5 @@
|
||||||
/pkg/server/assets.go
|
/pkg/server/assets.go
|
||||||
|
|
||||||
bbgo.sqlite3
|
bbgo.sqlite3
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
|
19
Makefile
19
Makefile
|
@ -24,8 +24,8 @@ $(BIN_DIR):
|
||||||
|
|
||||||
|
|
||||||
# build native bbgo
|
# build native bbgo
|
||||||
bbgo:
|
bbgo: static
|
||||||
go build -tags web,release -o $(BIN_DIR)/$@ ./cmd/bbgo
|
go build -tags web,release -o $(BIN_DIR)/bbgo ./cmd/bbgo
|
||||||
|
|
||||||
# build native bbgo (slim version)
|
# build native bbgo (slim version)
|
||||||
bbgo-slim:
|
bbgo-slim:
|
||||||
|
@ -124,12 +124,16 @@ dist: static dist-bbgo-linux dist-bbgo-darwin desktop
|
||||||
|
|
||||||
pkg/version/version.go: .FORCE
|
pkg/version/version.go: .FORCE
|
||||||
bash utils/generate-version-file.sh > $@
|
bash utils/generate-version-file.sh > $@
|
||||||
git commit $@ -m "bump version to $(VERSION)" || true
|
|
||||||
|
|
||||||
version: pkg/version/version.go migrations
|
pkg/version/dev.go: .FORCE
|
||||||
|
VERSION_SUFFIX="-dev" bash utils/generate-version-file.sh > $@
|
||||||
|
|
||||||
|
version: pkg/version/version.go pkg/version/dev.go migrations
|
||||||
|
git commit $< $(word 2,$^) -m "bump version to $(VERSION)" || true
|
||||||
[[ -e doc/release/$(VERSION).md ]] || (echo "file doc/release/$(VERSION).md does not exist" ; exit 1)
|
[[ -e doc/release/$(VERSION).md ]] || (echo "file doc/release/$(VERSION).md does not exist" ; exit 1)
|
||||||
git add -v doc/release/$(VERSION).md && git commit doc/release/$(VERSION).md -m "add release note" || true
|
git add -v doc/release/$(VERSION).md && git commit doc/release/$(VERSION).md -m "add release note" || true
|
||||||
git tag -f $(VERSION)
|
git tag -f $(VERSION)
|
||||||
|
git push origin HEAD
|
||||||
git push origin $(VERSION)
|
git push origin $(VERSION)
|
||||||
|
|
||||||
migrations:
|
migrations:
|
||||||
|
@ -146,8 +150,11 @@ docker-push:
|
||||||
docker push yoanlin/bbgo
|
docker push yoanlin/bbgo
|
||||||
bash -c "[[ -n $(DOCKER_TAG) ]] && docker push yoanlin/bbgo:$(DOCKER_TAG)"
|
bash -c "[[ -n $(DOCKER_TAG) ]] && docker push yoanlin/bbgo:$(DOCKER_TAG)"
|
||||||
|
|
||||||
frontend/out/index.html:
|
frontend/node_modules:
|
||||||
(cd frontend && yarn export)
|
cd frontend && yarn install
|
||||||
|
|
||||||
|
frontend/out/index.html: frontend/node_modules
|
||||||
|
cd frontend && yarn export
|
||||||
|
|
||||||
pkg/server/assets.go: frontend/out/index.html
|
pkg/server/assets.go: frontend/out/index.html
|
||||||
go run ./util/embed -package server -output $@ $(FRONTEND_EXPORT_DIR)
|
go run ./util/embed -package server -output $@ $(FRONTEND_EXPORT_DIR)
|
||||||
|
|
29
README.md
29
README.md
|
@ -32,9 +32,10 @@ A trading bot framework written in Go. The name bbgo comes from the BB8 bot in t
|
||||||
|
|
||||||
Get your exchange API key and secret after you register the accounts (you can choose one or more exchanges):
|
Get your exchange API key and secret after you register the accounts (you can choose one or more exchanges):
|
||||||
|
|
||||||
- For MAX: <https://max.maicoin.com/signup?r=c7982718>
|
- MAX: <https://max.maicoin.com/signup?r=c7982718>
|
||||||
- For Binance: <https://www.binancezh.com/en/register?ref=VGDGLT80>
|
- Binance: <https://www.binancezh.com/en/register?ref=VGDGLT80>
|
||||||
- For FTX: <https://ftx.com/#a=7710474>
|
- FTX: <https://ftx.com/#a=7710474>
|
||||||
|
- OKEx: <https://www.okex.com/join/2412712?src=from:ios-share>
|
||||||
|
|
||||||
Since the exchange implementation and support are done by a small team, if you like the work they've done for you, It
|
Since the exchange implementation and support are done by a small team, if you like the work they've done for you, It
|
||||||
would be great if you can use their referral code as your support to them. :-D
|
would be great if you can use their referral code as your support to them. :-D
|
||||||
|
@ -125,6 +126,8 @@ bbgo pnl --exchange binance --asset BTC --since "2019-01-01"
|
||||||
|
|
||||||
## Advanced Configuration
|
## Advanced Configuration
|
||||||
|
|
||||||
|
### Notification
|
||||||
|
|
||||||
- [Setting up Telegram notification](./doc/configuration/telegram.md)
|
- [Setting up Telegram notification](./doc/configuration/telegram.md)
|
||||||
- [Setting up Slack notification](./doc/configuration/slack.md)
|
- [Setting up Slack notification](./doc/configuration/slack.md)
|
||||||
|
|
||||||
|
@ -184,7 +187,8 @@ bbgo sync --session binance
|
||||||
|
|
||||||
Check out the strategy directory [strategy](pkg/strategy) for all built-in strategies:
|
Check out the strategy directory [strategy](pkg/strategy) for all built-in strategies:
|
||||||
|
|
||||||
- `pricealert` strategy demonstrates how to use the notification system [pricealert](pkg/strategy/pricealert)
|
- `pricealert` strategy demonstrates how to use the notification system [pricealert](pkg/strategy/pricealert). See
|
||||||
|
[document](./doc/strategy/pricealert.md).
|
||||||
- `xpuremaker` strategy demonstrates how to maintain the orderbook and submit maker
|
- `xpuremaker` strategy demonstrates how to maintain the orderbook and submit maker
|
||||||
orders [xpuremaker](pkg/strategy/xpuremaker)
|
orders [xpuremaker](pkg/strategy/xpuremaker)
|
||||||
- `buyandhold` strategy demonstrates how to subscribe kline events and submit market
|
- `buyandhold` strategy demonstrates how to subscribe kline events and submit market
|
||||||
|
@ -535,7 +539,7 @@ rockhopper --config rockhopper_sqlite.yaml create --type sql add_pnl_column
|
||||||
rockhopper --config rockhopper_mysql.yaml create --type sql add_pnl_column
|
rockhopper --config rockhopper_mysql.yaml create --type sql add_pnl_column
|
||||||
```
|
```
|
||||||
|
|
||||||
or
|
or you can use the util script:
|
||||||
|
|
||||||
```
|
```
|
||||||
bash utils/generate-new-migration.sh add_pnl_column
|
bash utils/generate-new-migration.sh add_pnl_column
|
||||||
|
@ -558,6 +562,21 @@ Then run the following command to compile the migration files into go files:
|
||||||
make migrations
|
make migrations
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
If you want to override the DSN and the Driver defined in the YAML config file, you can add some env vars in your dotenv file like this:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
ROCKHOPPER_DRIVER=mysql
|
||||||
|
ROCKHOPPER_DIALECT=mysql
|
||||||
|
ROCKHOPPER_DSN="root:123123@unix(/opt/local/var/run/mysql57/mysqld.sock)/bbgo"
|
||||||
|
```
|
||||||
|
|
||||||
|
And then, run:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
dotenv -f .env.local -- rockhopper --config rockhopper_mysql.yaml up
|
||||||
|
```
|
||||||
|
|
||||||
### Setup frontend development environment
|
### Setup frontend development environment
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|
20
config/pricealert-tg.yaml
Normal file
20
config/pricealert-tg.yaml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
---
|
||||||
|
notifications:
|
||||||
|
# object routing rules
|
||||||
|
routing:
|
||||||
|
trade: "$symbol"
|
||||||
|
order: "$symbol"
|
||||||
|
submitOrder: "$session" # not supported yet
|
||||||
|
pnL: "bbgo-pnl"
|
||||||
|
|
||||||
|
sessions:
|
||||||
|
binance:
|
||||||
|
exchange: binance
|
||||||
|
envVarPrefix: binance
|
||||||
|
|
||||||
|
exchangeStrategies:
|
||||||
|
- on: binance
|
||||||
|
pricealert:
|
||||||
|
symbol: "BTCUSDT"
|
||||||
|
interval: "1m"
|
||||||
|
minChange: 300
|
|
@ -1,5 +1,7 @@
|
||||||
# Build From Source
|
# Build From Source
|
||||||
|
|
||||||
|
## Install Go SDK
|
||||||
|
|
||||||
Go to the Go official website to download the Go SDK <https://go.dev/dl/>.
|
Go to the Go official website to download the Go SDK <https://go.dev/dl/>.
|
||||||
|
|
||||||
An example installation looks like this:
|
An example installation looks like this:
|
||||||
|
@ -28,12 +30,18 @@ Make sure your `go` is successfully installed:
|
||||||
go version
|
go version
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Install go-sqlite
|
||||||
|
|
||||||
If you need to use go-sqlite, you will need to enable CGO first:
|
If you need to use go-sqlite, you will need to enable CGO first:
|
||||||
|
|
||||||
```
|
```
|
||||||
CGO_ENABLED=1 go get github.com/mattn/go-sqlite3
|
CGO_ENABLED=1 go get github.com/mattn/go-sqlite3
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
### Install bbgo via go install
|
||||||
|
|
||||||
Install bbgo:
|
Install bbgo:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
@ -64,6 +72,41 @@ export GOPATH=~/mygo
|
||||||
|
|
||||||
Then your bbgo will be installed at `~/mygo/bin/bbgo`.
|
Then your bbgo will be installed at `~/mygo/bin/bbgo`.
|
||||||
|
|
||||||
|
### Install via git clone
|
||||||
|
|
||||||
|
Since the default GOPATH is located at `~/go`, you can clone the bbgo repo into the folder `~/go/src/github.com/c9s/bbgo`:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
mkdir -p ~/go/src/github.com/c9s
|
||||||
|
git clone git@github.com:c9s/bbgo.git ~/go/src/github.com/c9s/bbgo
|
||||||
|
cd ~/go/src/github.com/c9s/bbgo
|
||||||
|
```
|
||||||
|
|
||||||
|
Download the go modules:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
go mod download
|
||||||
|
```
|
||||||
|
|
||||||
|
And then you should be able to run bbgo with `go run`
|
||||||
|
|
||||||
|
```shell
|
||||||
|
go run ./cmd/bbgo run
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use the makefile to build bbgo:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cd frontend && yarn install
|
||||||
|
make bbgo
|
||||||
|
```
|
||||||
|
|
||||||
|
If you don't need the web interface, you can build the slim version of bbgo:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
make bbgo-slim
|
||||||
|
```
|
||||||
|
|
||||||
## Build inside a Alpine container
|
## Build inside a Alpine container
|
||||||
|
|
||||||
Starts a docker container with the alpine image:
|
Starts a docker container with the alpine image:
|
||||||
|
|
|
@ -22,6 +22,20 @@ you can set `TELEGRAM_AUTH_TOKEN` in the `.env.local` file, e.g.,
|
||||||
```sh
|
```sh
|
||||||
TELEGRAM_BOT_AUTH_TOKEN=itsme55667788
|
TELEGRAM_BOT_AUTH_TOKEN=itsme55667788
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The alerting strategies use Telegram bot notification without further configuration. You can check the [pricealert
|
||||||
|
yaml file](../../config/pricealert-tg.yaml) in the `config/` directory for example.
|
||||||
|
|
||||||
|
If you want the order submitting/filling notification, add the following to your `bbgo.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
notifications:
|
||||||
|
routing:
|
||||||
|
trade: "$symbol"
|
||||||
|
order: "$symbol"
|
||||||
|
submitOrder: "$session"
|
||||||
|
pnL: "bbgo-pnl"
|
||||||
|
```
|
||||||
|
|
||||||
Run your bbgo.
|
Run your bbgo.
|
||||||
|
|
||||||
|
|
57
doc/development/new-exchange.md
Normal file
57
doc/development/new-exchange.md
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
# Adding New Exchange
|
||||||
|
|
||||||
|
Open an issue and paste the following checklist to that issue.
|
||||||
|
|
||||||
|
You should send multiple small pull request to implement them.
|
||||||
|
|
||||||
|
**Please avoid sending a pull request with huge changes**
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
Exchange Interface (minimum)
|
||||||
|
|
||||||
|
- [ ] QueryMarkets
|
||||||
|
- [ ] QueryKLines
|
||||||
|
- [ ] QueryTickers
|
||||||
|
- [ ] QueryOrders
|
||||||
|
- [ ] QueryTrades
|
||||||
|
- [ ] SubmitOrders
|
||||||
|
|
||||||
|
Convert functions:
|
||||||
|
|
||||||
|
- [ ] MarketData convert functions
|
||||||
|
- [ ] toGlobalMarket
|
||||||
|
- [ ] toGlobalTicker
|
||||||
|
- [ ] toGlobalKLine
|
||||||
|
- [ ] UserData convert functions
|
||||||
|
- [ ] toGlobalOrder
|
||||||
|
- [ ] toGlobalTrade
|
||||||
|
- [ ] toGlobalAccount
|
||||||
|
- [ ] toGlobalBalance
|
||||||
|
|
||||||
|
Stream
|
||||||
|
|
||||||
|
- [ ] UserDataStream
|
||||||
|
- [ ] Trade message parser
|
||||||
|
- [ ] Order message parser
|
||||||
|
- [ ] Account message parser
|
||||||
|
- [ ] Balance message parser
|
||||||
|
- [ ] MarketDataStream
|
||||||
|
- [ ] OrderBook message parser (or depth)
|
||||||
|
- [ ] KLine message parser (required for backtesting)
|
||||||
|
- [ ] Public trade message parser (optional)
|
||||||
|
- [ ] Ticker message parser (optional)
|
||||||
|
- [ ] ping/pong handling.
|
||||||
|
- [ ] heart-beat hanlding or keep-alive handling.
|
||||||
|
- [ ] handling reconnect
|
||||||
|
|
||||||
|
Database
|
||||||
|
|
||||||
|
- [ ] Add a new kline table for the exchange (this is required for back-testing)
|
||||||
|
- [ ] Add MySQL migration SQL
|
||||||
|
- [ ] Add SQLite migration SQL
|
||||||
|
|
||||||
|
Exchange Factory
|
||||||
|
|
||||||
|
- [ ] Add the exchange constructor to the exchange instance factory function.
|
||||||
|
- [ ] Add extended fields to the ExchangeSession struct. (optional)
|
|
@ -1,7 +1,7 @@
|
||||||
## Fixes
|
## Fixes
|
||||||
|
|
||||||
-
|
- ftx: fixed FTX OnKLineClosed event
|
||||||
|
|
||||||
## Features
|
## Migrations
|
||||||
|
|
||||||
-
|
- add `is_futures` fields to orders and trades table
|
||||||
|
|
25
doc/strategy/pricealert.md
Normal file
25
doc/strategy/pricealert.md
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
### Price Alert Strategy
|
||||||
|
|
||||||
|
This strategy will send notifications to specified channels when the price change of the specified trading pairs is
|
||||||
|
larger than the threshold.
|
||||||
|
|
||||||
|
|
||||||
|
### Prerequisite
|
||||||
|
Setup Telegram/Slack notification before using Price Alert Strategy. See [Setting up Telegram Bot Notification
|
||||||
|
](../configuration/telegram.md) and [Setting up Slack Notification](../configuration/slack.md).
|
||||||
|
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- `symbol`
|
||||||
|
- The trading pair symbol, e.g., `BTCUSDT`, `ETHUSDT`
|
||||||
|
- `interval`
|
||||||
|
- The K-line interval, e.g., `5m`, `1h`
|
||||||
|
- `minChange`
|
||||||
|
- Alert threshold, e.g., `100`, `500`. This is a fixed value of price change. Any price change in a single K-line
|
||||||
|
larger than this value will trigger the alert.
|
||||||
|
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
|
||||||
|
See [pricealert.yaml](../../config/pricealert.yaml) and [pricealert-tg.yaml](../../config/pricealert-tg.yaml)
|
18
migrations/mysql/20211205162043_add_is_futures_column.sql
Normal file
18
migrations/mysql/20211205162043_add_is_futures_column.sql
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
-- +up
|
||||||
|
-- +begin
|
||||||
|
ALTER TABLE `trades` ADD COLUMN `is_futures` BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
|
-- +end
|
||||||
|
|
||||||
|
-- +begin
|
||||||
|
ALTER TABLE `orders` ADD COLUMN `is_futures` BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
|
-- +end
|
||||||
|
|
||||||
|
-- +down
|
||||||
|
|
||||||
|
-- +begin
|
||||||
|
ALTER TABLE `trades` DROP COLUMN `is_futures`;
|
||||||
|
-- +end
|
||||||
|
|
||||||
|
-- +begin
|
||||||
|
ALTER TABLE `orders` DROP COLUMN `is_futures`;
|
||||||
|
-- +end
|
18
migrations/sqlite3/20211205162302_add_is_futures_column.sql
Normal file
18
migrations/sqlite3/20211205162302_add_is_futures_column.sql
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
-- +up
|
||||||
|
-- +begin
|
||||||
|
ALTER TABLE `trades` ADD COLUMN `is_futures` BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
|
-- +end
|
||||||
|
|
||||||
|
-- +begin
|
||||||
|
ALTER TABLE `orders` ADD COLUMN `is_futures` BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
|
-- +end
|
||||||
|
|
||||||
|
-- +down
|
||||||
|
|
||||||
|
-- +begin
|
||||||
|
ALTER TABLE `trades` RENAME COLUMN `is_futures` TO `is_futures_deleted`;
|
||||||
|
-- +end
|
||||||
|
|
||||||
|
-- +begin
|
||||||
|
ALTER TABLE `orders` RENAME COLUMN `is_futures` TO `is_futures_deleted`;
|
||||||
|
-- +end
|
|
@ -33,6 +33,8 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/exchange/ftx"
|
||||||
|
"github.com/c9s/bbgo/pkg/exchange/okex"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/bbgo"
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
|
@ -68,29 +70,29 @@ type Exchange struct {
|
||||||
doneC chan struct{}
|
doneC chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewExchange(sourceName types.ExchangeName, srv *service.BacktestService, config *bbgo.Backtest) *Exchange {
|
func NewExchange(sourceName types.ExchangeName, srv *service.BacktestService, config *bbgo.Backtest) (*Exchange, error) {
|
||||||
ex, err := newPublicExchange(sourceName)
|
ex, err := newPublicExchange(sourceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if config == nil {
|
if config == nil {
|
||||||
panic(errors.New("backtest config can not be nil"))
|
return nil, errors.New("backtest config can not be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
markets, err := bbgo.LoadExchangeMarketsWithCache(context.Background(), ex)
|
markets, err := bbgo.LoadExchangeMarketsWithCache(context.Background(), ex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
startTime, err := config.ParseStartTime()
|
startTime, err := config.ParseStartTime()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
endTime, err := config.ParseEndTime()
|
endTime, err := config.ParseEndTime()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
account := &types.Account{
|
account := &types.Account{
|
||||||
|
@ -117,7 +119,7 @@ func NewExchange(sourceName types.ExchangeName, srv *service.BacktestService, co
|
||||||
}
|
}
|
||||||
|
|
||||||
e.resetMatchingBooks()
|
e.resetMatchingBooks()
|
||||||
return e
|
return e, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) addTrade(trade types.Trade) {
|
func (e *Exchange) addTrade(trade types.Trade) {
|
||||||
|
@ -313,7 +315,11 @@ func newPublicExchange(sourceExchange types.ExchangeName) (types.Exchange, error
|
||||||
return binance.New("", ""), nil
|
return binance.New("", ""), nil
|
||||||
case types.ExchangeMax:
|
case types.ExchangeMax:
|
||||||
return max.New("", ""), nil
|
return max.New("", ""), nil
|
||||||
|
case types.ExchangeFTX:
|
||||||
|
return ftx.NewExchange("", "", ""), nil
|
||||||
|
case types.ExchangeOKEx:
|
||||||
|
return okex.New("", "", ""), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("exchange %s is not supported", sourceExchange)
|
return nil, fmt.Errorf("public data from exchange %s is not supported", sourceExchange)
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,11 +179,11 @@ func (m *SimplePriceMatching) executeTrade(trade types.Trade) {
|
||||||
if trade.IsBuyer {
|
if trade.IsBuyer {
|
||||||
err = m.Account.UseLockedBalance(m.Market.QuoteCurrency, fixedpoint.NewFromFloat(trade.Price*trade.Quantity))
|
err = m.Account.UseLockedBalance(m.Market.QuoteCurrency, fixedpoint.NewFromFloat(trade.Price*trade.Quantity))
|
||||||
|
|
||||||
_ = m.Account.AddBalance(m.Market.BaseCurrency, fixedpoint.NewFromFloat(trade.Quantity))
|
m.Account.AddBalance(m.Market.BaseCurrency, fixedpoint.NewFromFloat(trade.Quantity))
|
||||||
} else {
|
} else {
|
||||||
err = m.Account.UseLockedBalance(m.Market.BaseCurrency, fixedpoint.NewFromFloat(trade.Quantity))
|
err = m.Account.UseLockedBalance(m.Market.BaseCurrency, fixedpoint.NewFromFloat(trade.Quantity))
|
||||||
|
|
||||||
_ = m.Account.AddBalance(m.Market.QuoteCurrency, fixedpoint.NewFromFloat(trade.Quantity*trade.Price))
|
m.Account.AddBalance(m.Market.QuoteCurrency, fixedpoint.NewFromFloat(trade.Quantity*trade.Price))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -180,7 +180,7 @@ var BacktestCmd = &cobra.Command{
|
||||||
|
|
||||||
// if we don't have klines before the start time endpoint, the back-test will fail.
|
// if we don't have klines before the start time endpoint, the back-test will fail.
|
||||||
// because the last price will be missing.
|
// because the last price will be missing.
|
||||||
if firstKLine != nil && syncFromTime.Before(firstKLine.EndTime) {
|
if firstKLine != nil && syncFromTime.Before(firstKLine.StartTime) {
|
||||||
return fmt.Errorf("the sync-from-time you gave %s is earlier than the previous sync-start-time %s. "+
|
return fmt.Errorf("the sync-from-time you gave %s is earlier than the previous sync-start-time %s. "+
|
||||||
"re-syncing data from the earlier date before your first sync is not support,"+
|
"re-syncing data from the earlier date before your first sync is not support,"+
|
||||||
"please clean up the kline table and restart a new sync",
|
"please clean up the kline table and restart a new sync",
|
||||||
|
@ -261,7 +261,11 @@ var BacktestCmd = &cobra.Command{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
backtestExchange := backtest.NewExchange(exchangeName, backtestService, userConfig.Backtest)
|
backtestExchange, err := backtest.NewExchange(exchangeName, backtestService, userConfig.Backtest)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to create backtest exchange")
|
||||||
|
}
|
||||||
|
|
||||||
environ.SetStartTime(startTime)
|
environ.SetStartTime(startTime)
|
||||||
environ.AddExchange(exchangeName.String(), backtestExchange)
|
environ.AddExchange(exchangeName.String(), backtestExchange)
|
||||||
|
|
||||||
|
@ -338,11 +342,15 @@ var BacktestCmd = &cobra.Command{
|
||||||
if jsonOutputEnabled {
|
if jsonOutputEnabled {
|
||||||
result := struct {
|
result := struct {
|
||||||
Symbol string `json:"symbol,omitempty"`
|
Symbol string `json:"symbol,omitempty"`
|
||||||
|
LastPrice float64 `json:"lastPrice,omitempty"`
|
||||||
|
StartPrice float64 `json:"startPrice,omitempty"`
|
||||||
PnLReport *pnl.AverageCostPnlReport `json:"pnlReport,omitempty"`
|
PnLReport *pnl.AverageCostPnlReport `json:"pnlReport,omitempty"`
|
||||||
InitialBalances types.BalanceMap `json:"initialBalances,omitempty"`
|
InitialBalances types.BalanceMap `json:"initialBalances,omitempty"`
|
||||||
FinalBalances types.BalanceMap `json:"finalBalances,omitempty"`
|
FinalBalances types.BalanceMap `json:"finalBalances,omitempty"`
|
||||||
}{
|
}{
|
||||||
Symbol: symbol,
|
Symbol: symbol,
|
||||||
|
LastPrice: lastPrice,
|
||||||
|
StartPrice: startPrice,
|
||||||
PnLReport: report,
|
PnLReport: report,
|
||||||
InitialBalances: initBalances,
|
InitialBalances: initBalances,
|
||||||
FinalBalances: finalBalances,
|
FinalBalances: finalBalances,
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/adshao/go-binance/v2"
|
"github.com/adshao/go-binance/v2"
|
||||||
|
"github.com/adshao/go-binance/v2/futures"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
|
@ -14,6 +15,42 @@ import (
|
||||||
"github.com/c9s/bbgo/pkg/util"
|
"github.com/c9s/bbgo/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func toGlobalMarket(symbol binance.Symbol) types.Market {
|
||||||
|
market := types.Market{
|
||||||
|
Symbol: symbol.Symbol,
|
||||||
|
LocalSymbol: symbol.Symbol,
|
||||||
|
PricePrecision: symbol.QuotePrecision,
|
||||||
|
VolumePrecision: symbol.BaseAssetPrecision,
|
||||||
|
QuoteCurrency: symbol.QuoteAsset,
|
||||||
|
BaseCurrency: symbol.BaseAsset,
|
||||||
|
}
|
||||||
|
|
||||||
|
if f := symbol.MinNotionalFilter(); f != nil {
|
||||||
|
market.MinNotional = util.MustParseFloat(f.MinNotional)
|
||||||
|
market.MinAmount = util.MustParseFloat(f.MinNotional)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The LOT_SIZE filter defines the quantity (aka "lots" in auction terms) rules for a symbol.
|
||||||
|
// There are 3 parts:
|
||||||
|
// minQty defines the minimum quantity/icebergQty allowed.
|
||||||
|
// maxQty defines the maximum quantity/icebergQty allowed.
|
||||||
|
// stepSize defines the intervals that a quantity/icebergQty can be increased/decreased by.
|
||||||
|
if f := symbol.LotSizeFilter(); f != nil {
|
||||||
|
market.MinQuantity = util.MustParseFloat(f.MinQuantity)
|
||||||
|
market.MaxQuantity = util.MustParseFloat(f.MaxQuantity)
|
||||||
|
market.StepSize = util.MustParseFloat(f.StepSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
if f := symbol.PriceFilter(); f != nil {
|
||||||
|
market.MaxPrice = util.MustParseFloat(f.MaxPrice)
|
||||||
|
market.MinPrice = util.MustParseFloat(f.MinPrice)
|
||||||
|
market.TickSize = util.MustParseFloat(f.TickSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
return market
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func toGlobalIsolatedUserAsset(userAsset binance.IsolatedUserAsset) types.IsolatedUserAsset {
|
func toGlobalIsolatedUserAsset(userAsset binance.IsolatedUserAsset) types.IsolatedUserAsset {
|
||||||
return types.IsolatedUserAsset{
|
return types.IsolatedUserAsset{
|
||||||
Asset: userAsset.Asset,
|
Asset: userAsset.Asset,
|
||||||
|
@ -90,8 +127,8 @@ func toGlobalMarginAccount(account *binance.MarginAccount) *types.MarginAccount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func toGlobalTicker(stats *binance.PriceChangeStats) types.Ticker {
|
func toGlobalTicker(stats *binance.PriceChangeStats) (*types.Ticker, error) {
|
||||||
return types.Ticker{
|
return &types.Ticker{
|
||||||
Volume: util.MustParseFloat(stats.Volume),
|
Volume: util.MustParseFloat(stats.Volume),
|
||||||
Last: util.MustParseFloat(stats.LastPrice),
|
Last: util.MustParseFloat(stats.LastPrice),
|
||||||
Open: util.MustParseFloat(stats.OpenPrice),
|
Open: util.MustParseFloat(stats.OpenPrice),
|
||||||
|
@ -100,9 +137,10 @@ func toGlobalTicker(stats *binance.PriceChangeStats) types.Ticker {
|
||||||
Buy: util.MustParseFloat(stats.BidPrice),
|
Buy: util.MustParseFloat(stats.BidPrice),
|
||||||
Sell: util.MustParseFloat(stats.AskPrice),
|
Sell: util.MustParseFloat(stats.AskPrice),
|
||||||
Time: time.Unix(0, stats.CloseTime*int64(time.Millisecond)),
|
Time: time.Unix(0, stats.CloseTime*int64(time.Millisecond)),
|
||||||
}
|
},nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func toLocalOrderType(orderType types.OrderType) (binance.OrderType, error) {
|
func toLocalOrderType(orderType types.OrderType) (binance.OrderType, error) {
|
||||||
switch orderType {
|
switch orderType {
|
||||||
|
|
||||||
|
@ -303,3 +341,27 @@ func convertSubscription(s types.Subscription) string {
|
||||||
|
|
||||||
return fmt.Sprintf("%s@%s", strings.ToLower(s.Symbol), s.Channel)
|
return fmt.Sprintf("%s@%s", strings.ToLower(s.Symbol), s.Channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertPremiumIndex(index *futures.PremiumIndex) (*types.PremiumIndex, error) {
|
||||||
|
markPrice, err := fixedpoint.NewFromString(index.MarkPrice)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
lastFundingRate, err := fixedpoint.NewFromString(index.LastFundingRate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nextFundingTime := time.Unix(0, index.NextFundingTime*int64(time.Millisecond))
|
||||||
|
t := time.Unix(0, index.Time*int64(time.Millisecond))
|
||||||
|
|
||||||
|
return &types.PremiumIndex{
|
||||||
|
Symbol: index.Symbol,
|
||||||
|
MarkPrice: markPrice,
|
||||||
|
NextFundingTime: nextFundingTime,
|
||||||
|
LastFundingRate: lastFundingRate,
|
||||||
|
Time: t,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,14 +3,14 @@ package binance
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/adshao/go-binance/v2/futures"
|
|
||||||
"golang.org/x/time/rate"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/time/rate"
|
||||||
|
|
||||||
"github.com/adshao/go-binance/v2"
|
"github.com/adshao/go-binance/v2"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -36,6 +36,7 @@ func init() {
|
||||||
_ = types.Exchange(&Exchange{})
|
_ = types.Exchange(&Exchange{})
|
||||||
_ = types.MarginExchange(&Exchange{})
|
_ = types.MarginExchange(&Exchange{})
|
||||||
|
|
||||||
|
// FIXME: this is not effected since dotenv is loaded in the rootCmd, not in the init function
|
||||||
if ok, _ := strconv.ParseBool(os.Getenv("DEBUG_BINANCE_STREAM")); ok {
|
if ok, _ := strconv.ParseBool(os.Getenv("DEBUG_BINANCE_STREAM")); ok {
|
||||||
log.Level = logrus.DebugLevel
|
log.Level = logrus.DebugLevel
|
||||||
}
|
}
|
||||||
|
@ -74,8 +75,7 @@ func (e *Exchange) QueryTicker(ctx context.Context, symbol string) (*types.Ticke
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ticker := toGlobalTicker(stats[0])
|
return toGlobalTicker(stats[0])
|
||||||
return &ticker, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) QueryTickers(ctx context.Context, symbol ...string) (map[string]types.Ticker, error) {
|
func (e *Exchange) QueryTickers(ctx context.Context, symbol ...string) (map[string]types.Ticker, error) {
|
||||||
|
@ -136,38 +136,7 @@ func (e *Exchange) QueryMarkets(ctx context.Context) (types.MarketMap, error) {
|
||||||
|
|
||||||
markets := types.MarketMap{}
|
markets := types.MarketMap{}
|
||||||
for _, symbol := range exchangeInfo.Symbols {
|
for _, symbol := range exchangeInfo.Symbols {
|
||||||
market := types.Market{
|
markets[symbol.Symbol] = toGlobalMarket(symbol)
|
||||||
Symbol: symbol.Symbol,
|
|
||||||
LocalSymbol: symbol.Symbol,
|
|
||||||
PricePrecision: symbol.QuotePrecision,
|
|
||||||
VolumePrecision: symbol.BaseAssetPrecision,
|
|
||||||
QuoteCurrency: symbol.QuoteAsset,
|
|
||||||
BaseCurrency: symbol.BaseAsset,
|
|
||||||
}
|
|
||||||
|
|
||||||
if f := symbol.MinNotionalFilter(); f != nil {
|
|
||||||
market.MinNotional = util.MustParseFloat(f.MinNotional)
|
|
||||||
market.MinAmount = util.MustParseFloat(f.MinNotional)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The LOT_SIZE filter defines the quantity (aka "lots" in auction terms) rules for a symbol.
|
|
||||||
// There are 3 parts:
|
|
||||||
// minQty defines the minimum quantity/icebergQty allowed.
|
|
||||||
// maxQty defines the maximum quantity/icebergQty allowed.
|
|
||||||
// stepSize defines the intervals that a quantity/icebergQty can be increased/decreased by.
|
|
||||||
if f := symbol.LotSizeFilter(); f != nil {
|
|
||||||
market.MinQuantity = util.MustParseFloat(f.MinQuantity)
|
|
||||||
market.MaxQuantity = util.MustParseFloat(f.MaxQuantity)
|
|
||||||
market.StepSize = util.MustParseFloat(f.StepSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
if f := symbol.PriceFilter(); f != nil {
|
|
||||||
market.MaxPrice = util.MustParseFloat(f.MaxPrice)
|
|
||||||
market.MinPrice = util.MustParseFloat(f.MinPrice)
|
|
||||||
market.TickSize = util.MustParseFloat(f.TickSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
markets[symbol.Symbol] = market
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return markets, nil
|
return markets, nil
|
||||||
|
@ -211,15 +180,6 @@ func (e *Exchange) QueryIsolatedMarginAccount(ctx context.Context, symbols ...st
|
||||||
return toGlobalIsolatedMarginAccount(account), nil
|
return toGlobalIsolatedMarginAccount(account), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) getLaunchDate() (time.Time, error) {
|
|
||||||
// binance launch date 12:00 July 14th, 2017
|
|
||||||
loc, err := time.LoadLocation("Asia/Shanghai")
|
|
||||||
if err != nil {
|
|
||||||
return time.Time{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return time.Date(2017, time.July, 14, 0, 0, 0, 0, loc), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Exchange) Withdrawal(ctx context.Context, asset string, amount fixedpoint.Value, address string, options *types.WithdrawalOptions) error {
|
func (e *Exchange) Withdrawal(ctx context.Context, asset string, amount fixedpoint.Value, address string, options *types.WithdrawalOptions) error {
|
||||||
req := e.Client.NewCreateWithdrawService()
|
req := e.Client.NewCreateWithdrawService()
|
||||||
|
@ -250,7 +210,7 @@ func (e *Exchange) QueryWithdrawHistory(ctx context.Context, asset string, since
|
||||||
|
|
||||||
var emptyTime = time.Time{}
|
var emptyTime = time.Time{}
|
||||||
if startTime == emptyTime {
|
if startTime == emptyTime {
|
||||||
startTime, err = e.getLaunchDate()
|
startTime, err = getLaunchDate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -338,7 +298,7 @@ func (e *Exchange) QueryDepositHistory(ctx context.Context, asset string, since,
|
||||||
|
|
||||||
var emptyTime = time.Time{}
|
var emptyTime = time.Time{}
|
||||||
if startTime == emptyTime {
|
if startTime == emptyTime {
|
||||||
startTime, err = e.getLaunchDate()
|
startTime, err = getLaunchDate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -925,44 +885,7 @@ func (e *Exchange) BatchQueryKLines(ctx context.Context, symbol string, interval
|
||||||
return allKLines, nil
|
return allKLines, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type FundingRate struct {
|
func (e *Exchange) QueryPremiumIndex(ctx context.Context, symbol string) (*types.PremiumIndex, error) {
|
||||||
FundingRate fixedpoint.Value
|
|
||||||
FundingTime time.Time
|
|
||||||
Time time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
type PremiumIndex struct {
|
|
||||||
Symbol string `json:"symbol"`
|
|
||||||
MarkPrice fixedpoint.Value `json:"markPrice"`
|
|
||||||
LastFundingRate fixedpoint.Value `json:"lastFundingRate"`
|
|
||||||
NextFundingTime time.Time `json:"nextFundingTime"`
|
|
||||||
Time time.Time `json:"time"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertPremiumIndex(index *futures.PremiumIndex) (*PremiumIndex, error) {
|
|
||||||
markPrice, err := fixedpoint.NewFromString(index.MarkPrice)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
lastFundingRate, err := fixedpoint.NewFromString(index.LastFundingRate)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
nextFundingTime := time.Unix(0, index.NextFundingTime*int64(time.Millisecond))
|
|
||||||
t := time.Unix(0, index.Time*int64(time.Millisecond))
|
|
||||||
|
|
||||||
return &PremiumIndex{
|
|
||||||
Symbol: index.Symbol,
|
|
||||||
MarkPrice: markPrice,
|
|
||||||
NextFundingTime: nextFundingTime,
|
|
||||||
LastFundingRate: lastFundingRate,
|
|
||||||
Time: t,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Exchange) QueryPremiumIndex(ctx context.Context, symbol string) (*PremiumIndex, error) {
|
|
||||||
futuresClient := binance.NewFuturesClient(e.key, e.secret)
|
futuresClient := binance.NewFuturesClient(e.key, e.secret)
|
||||||
|
|
||||||
// when symbol is set, only one index will be returned.
|
// when symbol is set, only one index will be returned.
|
||||||
|
@ -974,7 +897,7 @@ func (e *Exchange) QueryPremiumIndex(ctx context.Context, symbol string) (*Premi
|
||||||
return convertPremiumIndex(indexes[0])
|
return convertPremiumIndex(indexes[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) QueryFundingRateHistory(ctx context.Context, symbol string) (*FundingRate, error) {
|
func (e *Exchange) QueryFundingRateHistory(ctx context.Context, symbol string) (*types.FundingRate, error) {
|
||||||
futuresClient := binance.NewFuturesClient(e.key, e.secret)
|
futuresClient := binance.NewFuturesClient(e.key, e.secret)
|
||||||
rates, err := futuresClient.NewFundingRateService().
|
rates, err := futuresClient.NewFundingRateService().
|
||||||
Symbol(symbol).
|
Symbol(symbol).
|
||||||
|
@ -994,9 +917,19 @@ func (e *Exchange) QueryFundingRateHistory(ctx context.Context, symbol string) (
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &FundingRate{
|
return &types.FundingRate{
|
||||||
FundingRate: fundingRate,
|
FundingRate: fundingRate,
|
||||||
FundingTime: time.Unix(0, rate.FundingTime*int64(time.Millisecond)),
|
FundingTime: time.Unix(0, rate.FundingTime*int64(time.Millisecond)),
|
||||||
Time: time.Unix(0, rate.Time*int64(time.Millisecond)),
|
Time: time.Unix(0, rate.Time*int64(time.Millisecond)),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getLaunchDate() (time.Time, error) {
|
||||||
|
// binance launch date 12:00 July 14th, 2017
|
||||||
|
loc, err := time.LoadLocation("Asia/Shanghai")
|
||||||
|
if err != nil {
|
||||||
|
return time.Time{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Date(2017, time.July, 14, 0, 0, 0, 0, loc), nil
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package ftx
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"golang.org/x/time/rate"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -23,6 +24,9 @@ const (
|
||||||
|
|
||||||
var logger = logrus.WithField("exchange", "ftx")
|
var logger = logrus.WithField("exchange", "ftx")
|
||||||
|
|
||||||
|
// POST https://ftx.com/api/orders 429, Success: false, err: Do not send more than 2 orders on this market per 200ms
|
||||||
|
var requestLimit = rate.NewLimiter(rate.Every(220*time.Millisecond), 2)
|
||||||
|
|
||||||
//go:generate go run generate_symbol_map.go
|
//go:generate go run generate_symbol_map.go
|
||||||
|
|
||||||
type Exchange struct {
|
type Exchange struct {
|
||||||
|
@ -338,6 +342,9 @@ func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder
|
||||||
if so.TimeInForce != "GTC" && so.TimeInForce != "" {
|
if so.TimeInForce != "GTC" && so.TimeInForce != "" {
|
||||||
return createdOrders, fmt.Errorf("unsupported TimeInForce %s. only support GTC", so.TimeInForce)
|
return createdOrders, fmt.Errorf("unsupported TimeInForce %s. only support GTC", so.TimeInForce)
|
||||||
}
|
}
|
||||||
|
if err := requestLimit.Wait(ctx); err != nil {
|
||||||
|
logrus.WithError(err).Error("rate limit error")
|
||||||
|
}
|
||||||
or, err := e.newRest().PlaceOrder(ctx, PlaceOrderPayload{
|
or, err := e.newRest().PlaceOrder(ctx, PlaceOrderPayload{
|
||||||
Market: toLocalSymbol(TrimUpperString(so.Symbol)),
|
Market: toLocalSymbol(TrimUpperString(so.Symbol)),
|
||||||
Side: TrimLowerString(string(so.Side)),
|
Side: TrimLowerString(string(so.Side)),
|
||||||
|
@ -437,6 +444,9 @@ func sortByCreatedASC(orders []order) {
|
||||||
func (e *Exchange) CancelOrders(ctx context.Context, orders ...types.Order) error {
|
func (e *Exchange) CancelOrders(ctx context.Context, orders ...types.Order) error {
|
||||||
for _, o := range orders {
|
for _, o := range orders {
|
||||||
rest := e.newRest()
|
rest := e.newRest()
|
||||||
|
if err := requestLimit.Wait(ctx); err != nil {
|
||||||
|
logrus.WithError(err).Error("rate limit error")
|
||||||
|
}
|
||||||
if len(o.ClientOrderID) > 0 {
|
if len(o.ClientOrderID) > 0 {
|
||||||
if _, err := rest.CancelOrderByClientID(ctx, o.ClientOrderID); err != nil {
|
if _, err := rest.CancelOrderByClientID(ctx, o.ClientOrderID); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -141,7 +141,9 @@ func (s *Stream) pollKLines(ctx context.Context) {
|
||||||
|
|
||||||
if len(klines) > 0 {
|
if len(klines) > 0 {
|
||||||
// handle mutiple klines, get the latest one
|
// handle mutiple klines, get the latest one
|
||||||
s.EmitKLineClosed(klines[len(klines)-1])
|
kline := klines[len(klines)-1]
|
||||||
|
s.EmitKLine(kline)
|
||||||
|
s.EmitKLineClosed(kline)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,58 +1,62 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
package ftx
|
package ftx
|
||||||
var symbolMap = map[string]string{
|
var symbolMap = map[string]string{
|
||||||
"1INCH-0625": "1INCH-0625",
|
"1INCH-1231": "1INCH-1231",
|
||||||
"1INCH-PERP": "1INCH-PERP",
|
"1INCH-PERP": "1INCH-PERP",
|
||||||
"1INCHUSD": "1INCH/USD",
|
"1INCHUSD": "1INCH/USD",
|
||||||
"AAPL-0625": "AAPL-0625",
|
"AAPL-1231": "AAPL-1231",
|
||||||
"AAPLUSD": "AAPL/USD",
|
"AAPLUSD": "AAPL/USD",
|
||||||
"AAVE-0625": "AAVE-0625",
|
"AAVE-1231": "AAVE-1231",
|
||||||
"AAVE-PERP": "AAVE-PERP",
|
"AAVE-PERP": "AAVE-PERP",
|
||||||
"AAVEUSD": "AAVE/USD",
|
"AAVEUSD": "AAVE/USD",
|
||||||
"AAVEUSDT": "AAVE/USDT",
|
"AAVEUSDT": "AAVE/USDT",
|
||||||
"ABNB-0625": "ABNB-0625",
|
"ABNB-1231": "ABNB-1231",
|
||||||
"ABNBUSD": "ABNB/USD",
|
"ABNBUSD": "ABNB/USD",
|
||||||
"ACB-0625": "ACB-0625",
|
"ACB-1231": "ACB-1231",
|
||||||
"ACBUSD": "ACB/USD",
|
"ACBUSD": "ACB/USD",
|
||||||
"ADA-0625": "ADA-0625",
|
"ADA-1231": "ADA-1231",
|
||||||
"ADA-PERP": "ADA-PERP",
|
"ADA-PERP": "ADA-PERP",
|
||||||
"ADABEARUSD": "ADABEAR/USD",
|
"ADABEARUSD": "ADABEAR/USD",
|
||||||
"ADABULLUSD": "ADABULL/USD",
|
"ADABULLUSD": "ADABULL/USD",
|
||||||
"ADAHALFUSD": "ADAHALF/USD",
|
"ADAHALFUSD": "ADAHALF/USD",
|
||||||
"ADAHEDGEUSD": "ADAHEDGE/USD",
|
"ADAHEDGEUSD": "ADAHEDGE/USD",
|
||||||
|
"AGLD-PERP": "AGLD-PERP",
|
||||||
|
"AGLDUSD": "AGLD/USD",
|
||||||
"AKROUSD": "AKRO/USD",
|
"AKROUSD": "AKRO/USD",
|
||||||
"AKROUSDT": "AKRO/USDT",
|
"AKROUSDT": "AKRO/USDT",
|
||||||
"ALCX-PERP": "ALCX-PERP",
|
"ALCX-PERP": "ALCX-PERP",
|
||||||
"ALCXUSD": "ALCX/USD",
|
"ALCXUSD": "ALCX/USD",
|
||||||
"ALGO-0625": "ALGO-0625",
|
"ALEPHUSD": "ALEPH/USD",
|
||||||
|
"ALGO-1231": "ALGO-1231",
|
||||||
"ALGO-PERP": "ALGO-PERP",
|
"ALGO-PERP": "ALGO-PERP",
|
||||||
"ALGOBEARUSD": "ALGOBEAR/USD",
|
"ALGOBEARUSD": "ALGOBEAR/USD",
|
||||||
"ALGOBULLUSD": "ALGOBULL/USD",
|
"ALGOBULLUSD": "ALGOBULL/USD",
|
||||||
"ALGOHALFUSD": "ALGOHALF/USD",
|
"ALGOHALFUSD": "ALGOHALF/USD",
|
||||||
"ALGOHEDGEUSD": "ALGOHEDGE/USD",
|
"ALGOHEDGEUSD": "ALGOHEDGE/USD",
|
||||||
|
"ALICE-PERP": "ALICE-PERP",
|
||||||
|
"ALICEUSD": "ALICE/USD",
|
||||||
"ALPHA-PERP": "ALPHA-PERP",
|
"ALPHA-PERP": "ALPHA-PERP",
|
||||||
"ALPHAUSD": "ALPHA/USD",
|
"ALPHAUSD": "ALPHA/USD",
|
||||||
"ALT-0625": "ALT-0625",
|
"ALT-1231": "ALT-1231",
|
||||||
"ALT-PERP": "ALT-PERP",
|
"ALT-PERP": "ALT-PERP",
|
||||||
"ALTBEARUSD": "ALTBEAR/USD",
|
"ALTBEARUSD": "ALTBEAR/USD",
|
||||||
"ALTBULLUSD": "ALTBULL/USD",
|
"ALTBULLUSD": "ALTBULL/USD",
|
||||||
"ALTHALFUSD": "ALTHALF/USD",
|
"ALTHALFUSD": "ALTHALF/USD",
|
||||||
"ALTHEDGEUSD": "ALTHEDGE/USD",
|
"ALTHEDGEUSD": "ALTHEDGE/USD",
|
||||||
"AMC-0625": "AMC-0625",
|
"AMC-1231": "AMC-1231",
|
||||||
"AMCUSD": "AMC/USD",
|
"AMCUSD": "AMC/USD",
|
||||||
"AMD-0625": "AMD-0625",
|
"AMD-1231": "AMD-1231",
|
||||||
"AMDUSD": "AMD/USD",
|
"AMDUSD": "AMD/USD",
|
||||||
"AMPL-PERP": "AMPL-PERP",
|
"AMPL-PERP": "AMPL-PERP",
|
||||||
"AMPLUSD": "AMPL/USD",
|
"AMPLUSD": "AMPL/USD",
|
||||||
"AMPLUSDT": "AMPL/USDT",
|
"AMPLUSDT": "AMPL/USDT",
|
||||||
"AMZN-0625": "AMZN-0625",
|
"AMZN-1231": "AMZN-1231",
|
||||||
"AMZNUSD": "AMZN/USD",
|
"AMZNUSD": "AMZN/USD",
|
||||||
"APHA-0625": "APHA-0625",
|
"APHA-1231": "APHA-1231",
|
||||||
"APHAUSD": "APHA/USD",
|
"APHAUSD": "APHA/USD",
|
||||||
"AR-PERP": "AR-PERP",
|
"AR-PERP": "AR-PERP",
|
||||||
"ARKK-0625": "ARKK-0625",
|
"ARKK-1231": "ARKK-1231",
|
||||||
"ARKKUSD": "ARKK/USD",
|
"ARKKUSD": "ARKK/USD",
|
||||||
"ASD-0625": "ASD-0625",
|
|
||||||
"ASD-PERP": "ASD-PERP",
|
"ASD-PERP": "ASD-PERP",
|
||||||
"ASDBEARUSD": "ASDBEAR/USD",
|
"ASDBEARUSD": "ASDBEAR/USD",
|
||||||
"ASDBEARUSDT": "ASDBEAR/USDT",
|
"ASDBEARUSDT": "ASDBEAR/USDT",
|
||||||
|
@ -61,7 +65,9 @@ var symbolMap = map[string]string{
|
||||||
"ASDHALFUSD": "ASDHALF/USD",
|
"ASDHALFUSD": "ASDHALF/USD",
|
||||||
"ASDHEDGEUSD": "ASDHEDGE/USD",
|
"ASDHEDGEUSD": "ASDHEDGE/USD",
|
||||||
"ASDUSD": "ASD/USD",
|
"ASDUSD": "ASD/USD",
|
||||||
"ATOM-0625": "ATOM-0625",
|
"ATLAS-PERP": "ATLAS-PERP",
|
||||||
|
"ATLASUSD": "ATLAS/USD",
|
||||||
|
"ATOM-1231": "ATOM-1231",
|
||||||
"ATOM-PERP": "ATOM-PERP",
|
"ATOM-PERP": "ATOM-PERP",
|
||||||
"ATOMBEARUSD": "ATOMBEAR/USD",
|
"ATOMBEARUSD": "ATOMBEAR/USD",
|
||||||
"ATOMBULLUSD": "ATOMBULL/USD",
|
"ATOMBULLUSD": "ATOMBULL/USD",
|
||||||
|
@ -70,16 +76,16 @@ var symbolMap = map[string]string{
|
||||||
"AUDIO-PERP": "AUDIO-PERP",
|
"AUDIO-PERP": "AUDIO-PERP",
|
||||||
"AUDIOUSD": "AUDIO/USD",
|
"AUDIOUSD": "AUDIO/USD",
|
||||||
"AUDIOUSDT": "AUDIO/USDT",
|
"AUDIOUSDT": "AUDIO/USDT",
|
||||||
"AUDUSD": "AUD/USD",
|
"AURYUSD": "AURY/USD",
|
||||||
"AVAX-0625": "AVAX-0625",
|
"AVAX-1231": "AVAX-1231",
|
||||||
"AVAX-PERP": "AVAX-PERP",
|
"AVAX-PERP": "AVAX-PERP",
|
||||||
"AXS-PERP": "AXS-PERP",
|
"AXS-PERP": "AXS-PERP",
|
||||||
"AXSUSD": "AXS/USD",
|
"AXSUSD": "AXS/USD",
|
||||||
"BABA-0625": "BABA-0625",
|
"BABA-1231": "BABA-1231",
|
||||||
"BABAUSD": "BABA/USD",
|
"BABAUSD": "BABA/USD",
|
||||||
"BADGER-PERP": "BADGER-PERP",
|
"BADGER-PERP": "BADGER-PERP",
|
||||||
"BADGERUSD": "BADGER/USD",
|
"BADGERUSD": "BADGER/USD",
|
||||||
"BAL-0625": "BAL-0625",
|
"BAL-1231": "BAL-1231",
|
||||||
"BAL-PERP": "BAL-PERP",
|
"BAL-PERP": "BAL-PERP",
|
||||||
"BALBEARUSD": "BALBEAR/USD",
|
"BALBEARUSD": "BALBEAR/USD",
|
||||||
"BALBEARUSDT": "BALBEAR/USDT",
|
"BALBEARUSDT": "BALBEAR/USDT",
|
||||||
|
@ -93,11 +99,12 @@ var symbolMap = map[string]string{
|
||||||
"BANDUSD": "BAND/USD",
|
"BANDUSD": "BAND/USD",
|
||||||
"BAO-PERP": "BAO-PERP",
|
"BAO-PERP": "BAO-PERP",
|
||||||
"BAOUSD": "BAO/USD",
|
"BAOUSD": "BAO/USD",
|
||||||
|
"BARUSD": "BAR/USD",
|
||||||
"BAT-PERP": "BAT-PERP",
|
"BAT-PERP": "BAT-PERP",
|
||||||
"BATUSD": "BAT/USD",
|
"BATUSD": "BAT/USD",
|
||||||
"BB-0625": "BB-0625",
|
"BB-1231": "BB-1231",
|
||||||
"BBUSD": "BB/USD",
|
"BBUSD": "BB/USD",
|
||||||
"BCH-0625": "BCH-0625",
|
"BCH-1231": "BCH-1231",
|
||||||
"BCH-PERP": "BCH-PERP",
|
"BCH-PERP": "BCH-PERP",
|
||||||
"BCHBEARUSD": "BCHBEAR/USD",
|
"BCHBEARUSD": "BCHBEAR/USD",
|
||||||
"BCHBEARUSDT": "BCHBEAR/USDT",
|
"BCHBEARUSDT": "BCHBEAR/USDT",
|
||||||
|
@ -111,11 +118,17 @@ var symbolMap = map[string]string{
|
||||||
"BEARSHITUSD": "BEARSHIT/USD",
|
"BEARSHITUSD": "BEARSHIT/USD",
|
||||||
"BEARUSD": "BEAR/USD",
|
"BEARUSD": "BEAR/USD",
|
||||||
"BEARUSDT": "BEAR/USDT",
|
"BEARUSDT": "BEAR/USDT",
|
||||||
"BILI-0625": "BILI-0625",
|
"BICOUSD": "BICO/USD",
|
||||||
|
"BILI-1231": "BILI-1231",
|
||||||
"BILIUSD": "BILI/USD",
|
"BILIUSD": "BILI/USD",
|
||||||
"BITW-0625": "BITW-0625",
|
"BIT-PERP": "BIT-PERP",
|
||||||
|
"BITO-1231": "BITO-1231",
|
||||||
|
"BITOUSD": "BITO/USD",
|
||||||
|
"BITUSD": "BIT/USD",
|
||||||
|
"BITW-1231": "BITW-1231",
|
||||||
"BITWUSD": "BITW/USD",
|
"BITWUSD": "BITW/USD",
|
||||||
"BNB-0625": "BNB-0625",
|
"BLTUSD": "BLT/USD",
|
||||||
|
"BNB-1231": "BNB-1231",
|
||||||
"BNB-PERP": "BNB-PERP",
|
"BNB-PERP": "BNB-PERP",
|
||||||
"BNBBEARUSD": "BNBBEAR/USD",
|
"BNBBEARUSD": "BNBBEAR/USD",
|
||||||
"BNBBEARUSDT": "BNBBEAR/USDT",
|
"BNBBEARUSDT": "BNBBEAR/USDT",
|
||||||
|
@ -128,14 +141,15 @@ var symbolMap = map[string]string{
|
||||||
"BNBUSDT": "BNB/USDT",
|
"BNBUSDT": "BNB/USDT",
|
||||||
"BNT-PERP": "BNT-PERP",
|
"BNT-PERP": "BNT-PERP",
|
||||||
"BNTUSD": "BNT/USD",
|
"BNTUSD": "BNT/USD",
|
||||||
"BNTX-0625": "BNTX-0625",
|
"BNTX-1231": "BNTX-1231",
|
||||||
"BNTXUSD": "BNTX/USD",
|
"BNTXUSD": "BNTX/USD",
|
||||||
|
"BOBA-PERP": "BOBA-PERP",
|
||||||
|
"BOBAUSD": "BOBA/USD",
|
||||||
"BOLSONARO2022": "BOLSONARO2022",
|
"BOLSONARO2022": "BOLSONARO2022",
|
||||||
"BRZ-0625": "BRZ-0625",
|
|
||||||
"BRZ-PERP": "BRZ-PERP",
|
"BRZ-PERP": "BRZ-PERP",
|
||||||
"BRZUSD": "BRZ/USD",
|
"BRZUSD": "BRZ/USD",
|
||||||
"BRZUSDT": "BRZ/USDT",
|
"BRZUSDT": "BRZ/USDT",
|
||||||
"BSV-0625": "BSV-0625",
|
"BSV-1231": "BSV-1231",
|
||||||
"BSV-PERP": "BSV-PERP",
|
"BSV-PERP": "BSV-PERP",
|
||||||
"BSVBEARUSD": "BSVBEAR/USD",
|
"BSVBEARUSD": "BSVBEAR/USD",
|
||||||
"BSVBEARUSDT": "BSVBEAR/USDT",
|
"BSVBEARUSDT": "BSVBEAR/USDT",
|
||||||
|
@ -143,20 +157,18 @@ var symbolMap = map[string]string{
|
||||||
"BSVBULLUSDT": "BSVBULL/USDT",
|
"BSVBULLUSDT": "BSVBULL/USDT",
|
||||||
"BSVHALFUSD": "BSVHALF/USD",
|
"BSVHALFUSD": "BSVHALF/USD",
|
||||||
"BSVHEDGEUSD": "BSVHEDGE/USD",
|
"BSVHEDGEUSD": "BSVHEDGE/USD",
|
||||||
"BTC-0625": "BTC-0625",
|
"BTC-0325": "BTC-0325",
|
||||||
"BTC-0924": "BTC-0924",
|
|
||||||
"BTC-1231": "BTC-1231",
|
"BTC-1231": "BTC-1231",
|
||||||
"BTC-MOVE-0526": "BTC-MOVE-0526",
|
"BTC-MOVE-1209": "BTC-MOVE-1209",
|
||||||
"BTC-MOVE-0527": "BTC-MOVE-0527",
|
"BTC-MOVE-1210": "BTC-MOVE-1210",
|
||||||
"BTC-MOVE-2021Q2": "BTC-MOVE-2021Q2",
|
|
||||||
"BTC-MOVE-2021Q3": "BTC-MOVE-2021Q3",
|
|
||||||
"BTC-MOVE-2021Q4": "BTC-MOVE-2021Q4",
|
"BTC-MOVE-2021Q4": "BTC-MOVE-2021Q4",
|
||||||
"BTC-MOVE-WK-0528": "BTC-MOVE-WK-0528",
|
"BTC-MOVE-2022Q1": "BTC-MOVE-2022Q1",
|
||||||
"BTC-MOVE-WK-0604": "BTC-MOVE-WK-0604",
|
"BTC-MOVE-2022Q2": "BTC-MOVE-2022Q2",
|
||||||
"BTC-MOVE-WK-0611": "BTC-MOVE-WK-0611",
|
"BTC-MOVE-WK-1210": "BTC-MOVE-WK-1210",
|
||||||
"BTC-MOVE-WK-0618": "BTC-MOVE-WK-0618",
|
"BTC-MOVE-WK-1217": "BTC-MOVE-WK-1217",
|
||||||
|
"BTC-MOVE-WK-1224": "BTC-MOVE-WK-1224",
|
||||||
|
"BTC-MOVE-WK-1231": "BTC-MOVE-WK-1231",
|
||||||
"BTC-PERP": "BTC-PERP",
|
"BTC-PERP": "BTC-PERP",
|
||||||
"BTCAUD": "BTC/AUD",
|
|
||||||
"BTCBRZ": "BTC/BRZ",
|
"BTCBRZ": "BTC/BRZ",
|
||||||
"BTCEUR": "BTC/EUR",
|
"BTCEUR": "BTC/EUR",
|
||||||
"BTCTRYB": "BTC/TRYB",
|
"BTCTRYB": "BTC/TRYB",
|
||||||
|
@ -169,20 +181,30 @@ var symbolMap = map[string]string{
|
||||||
"BVOLBTC": "BVOL/BTC",
|
"BVOLBTC": "BVOL/BTC",
|
||||||
"BVOLUSD": "BVOL/USD",
|
"BVOLUSD": "BVOL/USD",
|
||||||
"BVOLUSDT": "BVOL/USDT",
|
"BVOLUSDT": "BVOL/USDT",
|
||||||
"BYND-0625": "BYND-0625",
|
"BYND-1231": "BYND-1231",
|
||||||
"BYNDUSD": "BYND/USD",
|
"BYNDUSD": "BYND/USD",
|
||||||
|
"C98-PERP": "C98-PERP",
|
||||||
|
"C98USD": "C98/USD",
|
||||||
"CADUSD": "CAD/USD",
|
"CADUSD": "CAD/USD",
|
||||||
"CAKE-PERP": "CAKE-PERP",
|
"CAKE-PERP": "CAKE-PERP",
|
||||||
"CEL-0625": "CEL-0625",
|
"CEL-1231": "CEL-1231",
|
||||||
|
"CEL-PERP": "CEL-PERP",
|
||||||
|
"CELBTC": "CEL/BTC",
|
||||||
|
"CELO-PERP": "CELO-PERP",
|
||||||
"CELUSD": "CEL/USD",
|
"CELUSD": "CEL/USD",
|
||||||
"CGC-0625": "CGC-0625",
|
"CGC-1231": "CGC-1231",
|
||||||
"CGCUSD": "CGC/USD",
|
"CGCUSD": "CGC/USD",
|
||||||
"CHZ-0625": "CHZ-0625",
|
"CHR-PERP": "CHR-PERP",
|
||||||
|
"CHRUSD": "CHR/USD",
|
||||||
|
"CHZ-1231": "CHZ-1231",
|
||||||
"CHZ-PERP": "CHZ-PERP",
|
"CHZ-PERP": "CHZ-PERP",
|
||||||
"CHZUSD": "CHZ/USD",
|
"CHZUSD": "CHZ/USD",
|
||||||
"CHZUSDT": "CHZ/USDT",
|
"CHZUSDT": "CHZ/USDT",
|
||||||
|
"CITYUSD": "CITY/USD",
|
||||||
|
"CLV-PERP": "CLV-PERP",
|
||||||
|
"CLVUSD": "CLV/USD",
|
||||||
"COINUSD": "COIN/USD",
|
"COINUSD": "COIN/USD",
|
||||||
"COMP-0625": "COMP-0625",
|
"COMP-1231": "COMP-1231",
|
||||||
"COMP-PERP": "COMP-PERP",
|
"COMP-PERP": "COMP-PERP",
|
||||||
"COMPBEARUSD": "COMPBEAR/USD",
|
"COMPBEARUSD": "COMPBEAR/USD",
|
||||||
"COMPBEARUSDT": "COMPBEAR/USDT",
|
"COMPBEARUSDT": "COMPBEAR/USDT",
|
||||||
|
@ -195,12 +217,12 @@ var symbolMap = map[string]string{
|
||||||
"CONV-PERP": "CONV-PERP",
|
"CONV-PERP": "CONV-PERP",
|
||||||
"CONVUSD": "CONV/USD",
|
"CONVUSD": "CONV/USD",
|
||||||
"COPEUSD": "COPE/USD",
|
"COPEUSD": "COPE/USD",
|
||||||
"CREAM-0625": "CREAM-0625",
|
"CQTUSD": "CQT/USD",
|
||||||
"CREAM-PERP": "CREAM-PERP",
|
"CREAM-PERP": "CREAM-PERP",
|
||||||
"CREAMUSD": "CREAM/USD",
|
"CREAMUSD": "CREAM/USD",
|
||||||
"CREAMUSDT": "CREAM/USDT",
|
"CREAMUSDT": "CREAM/USDT",
|
||||||
"CRO-PERP": "CRO-PERP",
|
"CRO-PERP": "CRO-PERP",
|
||||||
"CRON-0625": "CRON-0625",
|
"CRON-1231": "CRON-1231",
|
||||||
"CRONUSD": "CRON/USD",
|
"CRONUSD": "CRON/USD",
|
||||||
"CROUSD": "CRO/USD",
|
"CROUSD": "CRO/USD",
|
||||||
"CRV-PERP": "CRV-PERP",
|
"CRV-PERP": "CRV-PERP",
|
||||||
|
@ -214,12 +236,14 @@ var symbolMap = map[string]string{
|
||||||
"CUSDTHEDGEUSD": "CUSDTHEDGE/USD",
|
"CUSDTHEDGEUSD": "CUSDTHEDGE/USD",
|
||||||
"CUSDTUSD": "CUSDT/USD",
|
"CUSDTUSD": "CUSDT/USD",
|
||||||
"CUSDTUSDT": "CUSDT/USDT",
|
"CUSDTUSDT": "CUSDT/USDT",
|
||||||
|
"CVC-PERP": "CVC-PERP",
|
||||||
|
"CVCUSD": "CVC/USD",
|
||||||
"DAIUSD": "DAI/USD",
|
"DAIUSD": "DAI/USD",
|
||||||
"DAIUSDT": "DAI/USDT",
|
"DAIUSDT": "DAI/USDT",
|
||||||
"DASH-PERP": "DASH-PERP",
|
"DASH-PERP": "DASH-PERP",
|
||||||
"DAWN-PERP": "DAWN-PERP",
|
"DAWN-PERP": "DAWN-PERP",
|
||||||
"DAWNUSD": "DAWN/USD",
|
"DAWNUSD": "DAWN/USD",
|
||||||
"DEFI-0625": "DEFI-0625",
|
"DEFI-1231": "DEFI-1231",
|
||||||
"DEFI-PERP": "DEFI-PERP",
|
"DEFI-PERP": "DEFI-PERP",
|
||||||
"DEFIBEARUSD": "DEFIBEAR/USD",
|
"DEFIBEARUSD": "DEFIBEAR/USD",
|
||||||
"DEFIBEARUSDT": "DEFIBEAR/USDT",
|
"DEFIBEARUSDT": "DEFIBEAR/USDT",
|
||||||
|
@ -229,12 +253,14 @@ var symbolMap = map[string]string{
|
||||||
"DEFIHEDGEUSD": "DEFIHEDGE/USD",
|
"DEFIHEDGEUSD": "DEFIHEDGE/USD",
|
||||||
"DENT-PERP": "DENT-PERP",
|
"DENT-PERP": "DENT-PERP",
|
||||||
"DENTUSD": "DENT/USD",
|
"DENTUSD": "DENT/USD",
|
||||||
"DMG-PERP": "DMG-PERP",
|
"DFLUSD": "DFL/USD",
|
||||||
|
"DKNG-1231": "DKNG-1231",
|
||||||
|
"DKNGUSD": "DKNG/USD",
|
||||||
"DMGUSD": "DMG/USD",
|
"DMGUSD": "DMG/USD",
|
||||||
"DMGUSDT": "DMG/USDT",
|
"DMGUSDT": "DMG/USDT",
|
||||||
"DODO-PERP": "DODO-PERP",
|
"DODO-PERP": "DODO-PERP",
|
||||||
"DODOUSD": "DODO/USD",
|
"DODOUSD": "DODO/USD",
|
||||||
"DOGE-0625": "DOGE-0625",
|
"DOGE-1231": "DOGE-1231",
|
||||||
"DOGE-PERP": "DOGE-PERP",
|
"DOGE-PERP": "DOGE-PERP",
|
||||||
"DOGEBEAR2021USD": "DOGEBEAR2021/USD",
|
"DOGEBEAR2021USD": "DOGEBEAR2021/USD",
|
||||||
"DOGEBTC": "DOGE/BTC",
|
"DOGEBTC": "DOGE/BTC",
|
||||||
|
@ -243,19 +269,26 @@ var symbolMap = map[string]string{
|
||||||
"DOGEHEDGEUSD": "DOGEHEDGE/USD",
|
"DOGEHEDGEUSD": "DOGEHEDGE/USD",
|
||||||
"DOGEUSD": "DOGE/USD",
|
"DOGEUSD": "DOGE/USD",
|
||||||
"DOGEUSDT": "DOGE/USDT",
|
"DOGEUSDT": "DOGE/USDT",
|
||||||
"DOT-0625": "DOT-0625",
|
"DOT-1231": "DOT-1231",
|
||||||
"DOT-PERP": "DOT-PERP",
|
"DOT-PERP": "DOT-PERP",
|
||||||
"DRGN-0625": "DRGN-0625",
|
"DRGN-1231": "DRGN-1231",
|
||||||
"DRGN-PERP": "DRGN-PERP",
|
"DRGN-PERP": "DRGN-PERP",
|
||||||
"DRGNBEARUSD": "DRGNBEAR/USD",
|
"DRGNBEARUSD": "DRGNBEAR/USD",
|
||||||
"DRGNBULLUSD": "DRGNBULL/USD",
|
"DRGNBULLUSD": "DRGNBULL/USD",
|
||||||
"DRGNHALFUSD": "DRGNHALF/USD",
|
"DRGNHALFUSD": "DRGNHALF/USD",
|
||||||
"DRGNHEDGEUSD": "DRGNHEDGE/USD",
|
"DRGNHEDGEUSD": "DRGNHEDGE/USD",
|
||||||
|
"DYDX-PERP": "DYDX-PERP",
|
||||||
|
"DYDXUSD": "DYDX/USD",
|
||||||
|
"EDEN-1231": "EDEN-1231",
|
||||||
|
"EDEN-PERP": "EDEN-PERP",
|
||||||
|
"EDENUSD": "EDEN/USD",
|
||||||
"EGLD-PERP": "EGLD-PERP",
|
"EGLD-PERP": "EGLD-PERP",
|
||||||
"EMBUSD": "EMB/USD",
|
"EMBUSD": "EMB/USD",
|
||||||
"ENJ-PERP": "ENJ-PERP",
|
"ENJ-PERP": "ENJ-PERP",
|
||||||
"ENJUSD": "ENJ/USD",
|
"ENJUSD": "ENJ/USD",
|
||||||
"EOS-0625": "EOS-0625",
|
"ENS-PERP": "ENS-PERP",
|
||||||
|
"ENSUSD": "ENS/USD",
|
||||||
|
"EOS-1231": "EOS-1231",
|
||||||
"EOS-PERP": "EOS-PERP",
|
"EOS-PERP": "EOS-PERP",
|
||||||
"EOSBEARUSD": "EOSBEAR/USD",
|
"EOSBEARUSD": "EOSBEAR/USD",
|
||||||
"EOSBEARUSDT": "EOSBEAR/USDT",
|
"EOSBEARUSDT": "EOSBEAR/USDT",
|
||||||
|
@ -268,18 +301,16 @@ var symbolMap = map[string]string{
|
||||||
"ETCBULLUSD": "ETCBULL/USD",
|
"ETCBULLUSD": "ETCBULL/USD",
|
||||||
"ETCHALFUSD": "ETCHALF/USD",
|
"ETCHALFUSD": "ETCHALF/USD",
|
||||||
"ETCHEDGEUSD": "ETCHEDGE/USD",
|
"ETCHEDGEUSD": "ETCHEDGE/USD",
|
||||||
"ETH-0625": "ETH-0625",
|
"ETH-0325": "ETH-0325",
|
||||||
"ETH-0924": "ETH-0924",
|
|
||||||
"ETH-1231": "ETH-1231",
|
"ETH-1231": "ETH-1231",
|
||||||
"ETH-PERP": "ETH-PERP",
|
"ETH-PERP": "ETH-PERP",
|
||||||
"ETHAUD": "ETH/AUD",
|
|
||||||
"ETHBEARUSD": "ETHBEAR/USD",
|
"ETHBEARUSD": "ETHBEAR/USD",
|
||||||
"ETHBEARUSDT": "ETHBEAR/USDT",
|
"ETHBEARUSDT": "ETHBEAR/USDT",
|
||||||
"ETHBRZ": "ETH/BRZ",
|
"ETHBRZ": "ETH/BRZ",
|
||||||
"ETHBTC": "ETH/BTC",
|
"ETHBTC": "ETH/BTC",
|
||||||
"ETHBULLUSD": "ETHBULL/USD",
|
"ETHBULLUSD": "ETHBULL/USD",
|
||||||
"ETHBULLUSDT": "ETHBULL/USDT",
|
"ETHBULLUSDT": "ETHBULL/USDT",
|
||||||
"ETHE-0625": "ETHE-0625",
|
"ETHE-1231": "ETHE-1231",
|
||||||
"ETHEUR": "ETH/EUR",
|
"ETHEUR": "ETH/EUR",
|
||||||
"ETHEUSD": "ETHE/USD",
|
"ETHEUSD": "ETHE/USD",
|
||||||
"ETHHALFUSD": "ETHHALF/USD",
|
"ETHHALFUSD": "ETHHALF/USD",
|
||||||
|
@ -287,18 +318,18 @@ var symbolMap = map[string]string{
|
||||||
"ETHUSD": "ETH/USD",
|
"ETHUSD": "ETH/USD",
|
||||||
"ETHUSDT": "ETH/USDT",
|
"ETHUSDT": "ETH/USDT",
|
||||||
"EURUSD": "EUR/USD",
|
"EURUSD": "EUR/USD",
|
||||||
"EXCH-0625": "EXCH-0625",
|
"EXCH-1231": "EXCH-1231",
|
||||||
"EXCH-PERP": "EXCH-PERP",
|
"EXCH-PERP": "EXCH-PERP",
|
||||||
"EXCHBEARUSD": "EXCHBEAR/USD",
|
"EXCHBEARUSD": "EXCHBEAR/USD",
|
||||||
"EXCHBULLUSD": "EXCHBULL/USD",
|
"EXCHBULLUSD": "EXCHBULL/USD",
|
||||||
"EXCHHALFUSD": "EXCHHALF/USD",
|
"EXCHHALFUSD": "EXCHHALF/USD",
|
||||||
"EXCHHEDGEUSD": "EXCHHEDGE/USD",
|
"EXCHHEDGEUSD": "EXCHHEDGE/USD",
|
||||||
"FB-0625": "FB-0625",
|
"FB-1231": "FB-1231",
|
||||||
"FBUSD": "FB/USD",
|
"FBUSD": "FB/USD",
|
||||||
"FIDA-PERP": "FIDA-PERP",
|
"FIDA-PERP": "FIDA-PERP",
|
||||||
"FIDAUSD": "FIDA/USD",
|
"FIDAUSD": "FIDA/USD",
|
||||||
"FIDAUSDT": "FIDA/USDT",
|
"FIDAUSDT": "FIDA/USDT",
|
||||||
"FIL-0625": "FIL-0625",
|
"FIL-1231": "FIL-1231",
|
||||||
"FIL-PERP": "FIL-PERP",
|
"FIL-PERP": "FIL-PERP",
|
||||||
"FLM-PERP": "FLM-PERP",
|
"FLM-PERP": "FLM-PERP",
|
||||||
"FLOW-PERP": "FLOW-PERP",
|
"FLOW-PERP": "FLOW-PERP",
|
||||||
|
@ -310,21 +341,26 @@ var symbolMap = map[string]string{
|
||||||
"FTTBTC": "FTT/BTC",
|
"FTTBTC": "FTT/BTC",
|
||||||
"FTTUSD": "FTT/USD",
|
"FTTUSD": "FTT/USD",
|
||||||
"FTTUSDT": "FTT/USDT",
|
"FTTUSDT": "FTT/USDT",
|
||||||
|
"GALA-PERP": "GALA-PERP",
|
||||||
|
"GALAUSD": "GALA/USD",
|
||||||
|
"GALUSD": "GAL/USD",
|
||||||
"GBPUSD": "GBP/USD",
|
"GBPUSD": "GBP/USD",
|
||||||
"GBTC-0625": "GBTC-0625",
|
"GBTC-1231": "GBTC-1231",
|
||||||
"GBTCUSD": "GBTC/USD",
|
"GBTCUSD": "GBTC/USD",
|
||||||
"GDX-0625": "GDX-0625",
|
"GDX-1231": "GDX-1231",
|
||||||
"GDXJ-0625": "GDXJ-0625",
|
"GDXJ-1231": "GDXJ-1231",
|
||||||
"GDXJUSD": "GDXJ/USD",
|
"GDXJUSD": "GDXJ/USD",
|
||||||
"GDXUSD": "GDX/USD",
|
"GDXUSD": "GDX/USD",
|
||||||
"GLD-0625": "GLD-0625",
|
"GENEUSD": "GENE/USD",
|
||||||
|
"GLD-1231": "GLD-1231",
|
||||||
"GLDUSD": "GLD/USD",
|
"GLDUSD": "GLD/USD",
|
||||||
"GLXYUSD": "GLXY/USD",
|
"GLXYUSD": "GLXY/USD",
|
||||||
"GME-0625": "GME-0625",
|
"GME-1231": "GME-1231",
|
||||||
"GMEUSD": "GME/USD",
|
"GMEUSD": "GME/USD",
|
||||||
"GOOGL-0625": "GOOGL-0625",
|
"GODSUSD": "GODS/USD",
|
||||||
|
"GOOGL-1231": "GOOGL-1231",
|
||||||
"GOOGLUSD": "GOOGL/USD",
|
"GOOGLUSD": "GOOGL/USD",
|
||||||
"GRT-0625": "GRT-0625",
|
"GRT-1231": "GRT-1231",
|
||||||
"GRT-PERP": "GRT-PERP",
|
"GRT-PERP": "GRT-PERP",
|
||||||
"GRTBEARUSD": "GRTBEAR/USD",
|
"GRTBEARUSD": "GRTBEAR/USD",
|
||||||
"GRTBULLUSD": "GRTBULL/USD",
|
"GRTBULLUSD": "GRTBULL/USD",
|
||||||
|
@ -337,6 +373,7 @@ var symbolMap = map[string]string{
|
||||||
"HEDGEUSD": "HEDGE/USD",
|
"HEDGEUSD": "HEDGE/USD",
|
||||||
"HGETUSD": "HGET/USD",
|
"HGETUSD": "HGET/USD",
|
||||||
"HGETUSDT": "HGET/USDT",
|
"HGETUSDT": "HGET/USDT",
|
||||||
|
"HMTUSD": "HMT/USD",
|
||||||
"HNT-PERP": "HNT-PERP",
|
"HNT-PERP": "HNT-PERP",
|
||||||
"HNTUSD": "HNT/USD",
|
"HNTUSD": "HNT/USD",
|
||||||
"HNTUSDT": "HNT/USDT",
|
"HNTUSDT": "HNT/USDT",
|
||||||
|
@ -358,7 +395,11 @@ var symbolMap = map[string]string{
|
||||||
"IBVOLUSD": "IBVOL/USD",
|
"IBVOLUSD": "IBVOL/USD",
|
||||||
"IBVOLUSDT": "IBVOL/USDT",
|
"IBVOLUSDT": "IBVOL/USDT",
|
||||||
"ICP-PERP": "ICP-PERP",
|
"ICP-PERP": "ICP-PERP",
|
||||||
|
"ICX-PERP": "ICX-PERP",
|
||||||
|
"IMXUSD": "IMX/USD",
|
||||||
|
"INTERUSD": "INTER/USD",
|
||||||
"IOTA-PERP": "IOTA-PERP",
|
"IOTA-PERP": "IOTA-PERP",
|
||||||
|
"JETUSD": "JET/USD",
|
||||||
"JSTUSD": "JST/USD",
|
"JSTUSD": "JST/USD",
|
||||||
"KAVA-PERP": "KAVA-PERP",
|
"KAVA-PERP": "KAVA-PERP",
|
||||||
"KIN-PERP": "KIN-PERP",
|
"KIN-PERP": "KIN-PERP",
|
||||||
|
@ -372,8 +413,9 @@ var symbolMap = map[string]string{
|
||||||
"KNCHEDGEUSD": "KNCHEDGE/USD",
|
"KNCHEDGEUSD": "KNCHEDGE/USD",
|
||||||
"KNCUSD": "KNC/USD",
|
"KNCUSD": "KNC/USD",
|
||||||
"KNCUSDT": "KNC/USDT",
|
"KNCUSDT": "KNC/USDT",
|
||||||
|
"KSHIB-PERP": "KSHIB-PERP",
|
||||||
|
"KSHIBUSD": "KSHIB/USD",
|
||||||
"KSM-PERP": "KSM-PERP",
|
"KSM-PERP": "KSM-PERP",
|
||||||
"LB-0812": "LB-0812",
|
|
||||||
"LEO-PERP": "LEO-PERP",
|
"LEO-PERP": "LEO-PERP",
|
||||||
"LEOBEARUSD": "LEOBEAR/USD",
|
"LEOBEARUSD": "LEOBEAR/USD",
|
||||||
"LEOBULLUSD": "LEOBULL/USD",
|
"LEOBULLUSD": "LEOBULL/USD",
|
||||||
|
@ -382,7 +424,7 @@ var symbolMap = map[string]string{
|
||||||
"LEOUSD": "LEO/USD",
|
"LEOUSD": "LEO/USD",
|
||||||
"LINA-PERP": "LINA-PERP",
|
"LINA-PERP": "LINA-PERP",
|
||||||
"LINAUSD": "LINA/USD",
|
"LINAUSD": "LINA/USD",
|
||||||
"LINK-0625": "LINK-0625",
|
"LINK-1231": "LINK-1231",
|
||||||
"LINK-PERP": "LINK-PERP",
|
"LINK-PERP": "LINK-PERP",
|
||||||
"LINKBEARUSD": "LINKBEAR/USD",
|
"LINKBEARUSD": "LINKBEAR/USD",
|
||||||
"LINKBEARUSDT": "LINKBEAR/USDT",
|
"LINKBEARUSDT": "LINKBEAR/USDT",
|
||||||
|
@ -395,7 +437,7 @@ var symbolMap = map[string]string{
|
||||||
"LINKUSDT": "LINK/USDT",
|
"LINKUSDT": "LINK/USDT",
|
||||||
"LRC-PERP": "LRC-PERP",
|
"LRC-PERP": "LRC-PERP",
|
||||||
"LRCUSD": "LRC/USD",
|
"LRCUSD": "LRC/USD",
|
||||||
"LTC-0625": "LTC-0625",
|
"LTC-1231": "LTC-1231",
|
||||||
"LTC-PERP": "LTC-PERP",
|
"LTC-PERP": "LTC-PERP",
|
||||||
"LTCBEARUSD": "LTCBEAR/USD",
|
"LTCBEARUSD": "LTCBEAR/USD",
|
||||||
"LTCBEARUSDT": "LTCBEAR/USDT",
|
"LTCBEARUSDT": "LTCBEAR/USDT",
|
||||||
|
@ -409,6 +451,8 @@ var symbolMap = map[string]string{
|
||||||
"LUAUSD": "LUA/USD",
|
"LUAUSD": "LUA/USD",
|
||||||
"LUAUSDT": "LUA/USDT",
|
"LUAUSDT": "LUA/USDT",
|
||||||
"LUNA-PERP": "LUNA-PERP",
|
"LUNA-PERP": "LUNA-PERP",
|
||||||
|
"MANA-PERP": "MANA-PERP",
|
||||||
|
"MANAUSD": "MANA/USD",
|
||||||
"MAPS-PERP": "MAPS-PERP",
|
"MAPS-PERP": "MAPS-PERP",
|
||||||
"MAPSUSD": "MAPS/USD",
|
"MAPSUSD": "MAPS/USD",
|
||||||
"MAPSUSDT": "MAPS/USDT",
|
"MAPSUSDT": "MAPS/USDT",
|
||||||
|
@ -416,15 +460,18 @@ var symbolMap = map[string]string{
|
||||||
"MATHUSDT": "MATH/USDT",
|
"MATHUSDT": "MATH/USDT",
|
||||||
"MATIC-PERP": "MATIC-PERP",
|
"MATIC-PERP": "MATIC-PERP",
|
||||||
"MATICBEAR2021USD": "MATICBEAR2021/USD",
|
"MATICBEAR2021USD": "MATICBEAR2021/USD",
|
||||||
|
"MATICBTC": "MATIC/BTC",
|
||||||
"MATICBULLUSD": "MATICBULL/USD",
|
"MATICBULLUSD": "MATICBULL/USD",
|
||||||
"MATICHALFUSD": "MATICHALF/USD",
|
"MATICHALFUSD": "MATICHALF/USD",
|
||||||
"MATICHEDGEUSD": "MATICHEDGE/USD",
|
"MATICHEDGEUSD": "MATICHEDGE/USD",
|
||||||
"MATICUSD": "MATIC/USD",
|
"MATICUSD": "MATIC/USD",
|
||||||
|
"MCB-PERP": "MCB-PERP",
|
||||||
|
"MCBUSD": "MCB/USD",
|
||||||
"MEDIA-PERP": "MEDIA-PERP",
|
"MEDIA-PERP": "MEDIA-PERP",
|
||||||
"MEDIAUSD": "MEDIA/USD",
|
"MEDIAUSD": "MEDIA/USD",
|
||||||
"MER-PERP": "MER-PERP",
|
"MER-PERP": "MER-PERP",
|
||||||
"MERUSD": "MER/USD",
|
"MERUSD": "MER/USD",
|
||||||
"MID-0625": "MID-0625",
|
"MID-1231": "MID-1231",
|
||||||
"MID-PERP": "MID-PERP",
|
"MID-PERP": "MID-PERP",
|
||||||
"MIDBEARUSD": "MIDBEAR/USD",
|
"MIDBEARUSD": "MIDBEAR/USD",
|
||||||
"MIDBULLUSD": "MIDBULL/USD",
|
"MIDBULLUSD": "MIDBULL/USD",
|
||||||
|
@ -435,45 +482,49 @@ var symbolMap = map[string]string{
|
||||||
"MKRBULLUSD": "MKRBULL/USD",
|
"MKRBULLUSD": "MKRBULL/USD",
|
||||||
"MKRUSD": "MKR/USD",
|
"MKRUSD": "MKR/USD",
|
||||||
"MKRUSDT": "MKR/USDT",
|
"MKRUSDT": "MKR/USDT",
|
||||||
|
"MNGO-PERP": "MNGO-PERP",
|
||||||
|
"MNGOUSD": "MNGO/USD",
|
||||||
"MOBUSD": "MOB/USD",
|
"MOBUSD": "MOB/USD",
|
||||||
"MOBUSDT": "MOB/USDT",
|
"MOBUSDT": "MOB/USDT",
|
||||||
"MRNA-0625": "MRNA-0625",
|
"MRNA-1231": "MRNA-1231",
|
||||||
"MRNAUSD": "MRNA/USD",
|
"MRNAUSD": "MRNA/USD",
|
||||||
"MSTR-0625": "MSTR-0625",
|
"MSOLUSD": "MSOL/USD",
|
||||||
|
"MSTR-1231": "MSTR-1231",
|
||||||
"MSTRUSD": "MSTR/USD",
|
"MSTRUSD": "MSTR/USD",
|
||||||
"MTA-PERP": "MTA-PERP",
|
"MTA-PERP": "MTA-PERP",
|
||||||
"MTAUSD": "MTA/USD",
|
"MTAUSD": "MTA/USD",
|
||||||
"MTAUSDT": "MTA/USDT",
|
"MTAUSDT": "MTA/USDT",
|
||||||
"MTL-PERP": "MTL-PERP",
|
"MTL-PERP": "MTL-PERP",
|
||||||
"MTLUSD": "MTL/USD",
|
"MTLUSD": "MTL/USD",
|
||||||
|
"MVDA10-PERP": "MVDA10-PERP",
|
||||||
|
"MVDA25-PERP": "MVDA25-PERP",
|
||||||
"NEAR-PERP": "NEAR-PERP",
|
"NEAR-PERP": "NEAR-PERP",
|
||||||
"NEO-PERP": "NEO-PERP",
|
"NEO-PERP": "NEO-PERP",
|
||||||
"NFLX-0625": "NFLX-0625",
|
"NFLX-1231": "NFLX-1231",
|
||||||
"NFLXUSD": "NFLX/USD",
|
"NFLXUSD": "NFLX/USD",
|
||||||
"NIO-0625": "NIO-0625",
|
"NIO-1231": "NIO-1231",
|
||||||
"NIOUSD": "NIO/USD",
|
"NIOUSD": "NIO/USD",
|
||||||
"NOK-0625": "NOK-0625",
|
"NOK-1231": "NOK-1231",
|
||||||
"NOKUSD": "NOK/USD",
|
"NOKUSD": "NOK/USD",
|
||||||
"NVDA-0625": "NVDA-0625",
|
"NVDA-1231": "NVDA-1231",
|
||||||
"NVDAUSD": "NVDA/USD",
|
"NVDAUSD": "NVDA/USD",
|
||||||
"OKB-0625": "OKB-0625",
|
"OKB-1231": "OKB-1231",
|
||||||
"OKB-PERP": "OKB-PERP",
|
"OKB-PERP": "OKB-PERP",
|
||||||
"OKBBEARUSD": "OKBBEAR/USD",
|
"OKBBEARUSD": "OKBBEAR/USD",
|
||||||
"OKBBULLUSD": "OKBBULL/USD",
|
"OKBBULLUSD": "OKBBULL/USD",
|
||||||
"OKBHALFUSD": "OKBHALF/USD",
|
"OKBHALFUSD": "OKBHALF/USD",
|
||||||
"OKBHEDGEUSD": "OKBHEDGE/USD",
|
"OKBHEDGEUSD": "OKBHEDGE/USD",
|
||||||
"OKBUSD": "OKB/USD",
|
"OKBUSD": "OKB/USD",
|
||||||
"OLY2021": "OLY2021",
|
"OMG-1231": "OMG-1231",
|
||||||
"OMG-0625": "OMG-0625",
|
|
||||||
"OMG-PERP": "OMG-PERP",
|
"OMG-PERP": "OMG-PERP",
|
||||||
"OMGUSD": "OMG/USD",
|
"OMGUSD": "OMG/USD",
|
||||||
|
"ONE-PERP": "ONE-PERP",
|
||||||
"ONT-PERP": "ONT-PERP",
|
"ONT-PERP": "ONT-PERP",
|
||||||
"ORBS-PERP": "ORBS-PERP",
|
"ORBS-PERP": "ORBS-PERP",
|
||||||
"ORBSUSD": "ORBS/USD",
|
"ORBSUSD": "ORBS/USD",
|
||||||
"OXY-PERP": "OXY-PERP",
|
"OXY-PERP": "OXY-PERP",
|
||||||
"OXYUSD": "OXY/USD",
|
"OXYUSD": "OXY/USD",
|
||||||
"OXYUSDT": "OXY/USDT",
|
"OXYUSDT": "OXY/USDT",
|
||||||
"PAXG-0625": "PAXG-0625",
|
|
||||||
"PAXG-PERP": "PAXG-PERP",
|
"PAXG-PERP": "PAXG-PERP",
|
||||||
"PAXGBEARUSD": "PAXGBEAR/USD",
|
"PAXGBEARUSD": "PAXGBEAR/USD",
|
||||||
"PAXGBULLUSD": "PAXGBULL/USD",
|
"PAXGBULLUSD": "PAXGBULL/USD",
|
||||||
|
@ -481,13 +532,16 @@ var symbolMap = map[string]string{
|
||||||
"PAXGHEDGEUSD": "PAXGHEDGE/USD",
|
"PAXGHEDGEUSD": "PAXGHEDGE/USD",
|
||||||
"PAXGUSD": "PAXG/USD",
|
"PAXGUSD": "PAXG/USD",
|
||||||
"PAXGUSDT": "PAXG/USDT",
|
"PAXGUSDT": "PAXG/USDT",
|
||||||
"PENN-0625": "PENN-0625",
|
"PENN-1231": "PENN-1231",
|
||||||
"PENNUSD": "PENN/USD",
|
"PENNUSD": "PENN/USD",
|
||||||
"PERP-PERP": "PERP-PERP",
|
"PERP-PERP": "PERP-PERP",
|
||||||
"PERPUSD": "PERP/USD",
|
"PERPUSD": "PERP/USD",
|
||||||
"PFE-0625": "PFE-0625",
|
"PFE-1231": "PFE-1231",
|
||||||
"PFEUSD": "PFE/USD",
|
"PFEUSD": "PFE/USD",
|
||||||
"PRIV-0625": "PRIV-0625",
|
"POLIS-PERP": "POLIS-PERP",
|
||||||
|
"POLISUSD": "POLIS/USD",
|
||||||
|
"PORTUSD": "PORT/USD",
|
||||||
|
"PRIV-1231": "PRIV-1231",
|
||||||
"PRIV-PERP": "PRIV-PERP",
|
"PRIV-PERP": "PRIV-PERP",
|
||||||
"PRIVBEARUSD": "PRIVBEAR/USD",
|
"PRIVBEARUSD": "PRIVBEAR/USD",
|
||||||
"PRIVBULLUSD": "PRIVBULL/USD",
|
"PRIVBULLUSD": "PRIVBULL/USD",
|
||||||
|
@ -495,20 +549,24 @@ var symbolMap = map[string]string{
|
||||||
"PRIVHEDGEUSD": "PRIVHEDGE/USD",
|
"PRIVHEDGEUSD": "PRIVHEDGE/USD",
|
||||||
"PROM-PERP": "PROM-PERP",
|
"PROM-PERP": "PROM-PERP",
|
||||||
"PROMUSD": "PROM/USD",
|
"PROMUSD": "PROM/USD",
|
||||||
|
"PSGUSD": "PSG/USD",
|
||||||
|
"PTUUSD": "PTU/USD",
|
||||||
"PUNDIX-PERP": "PUNDIX-PERP",
|
"PUNDIX-PERP": "PUNDIX-PERP",
|
||||||
"PUNDIXUSD": "PUNDIX/USD",
|
"PUNDIXUSD": "PUNDIX/USD",
|
||||||
"PYPL-0625": "PYPL-0625",
|
"PYPL-1231": "PYPL-1231",
|
||||||
"PYPLUSD": "PYPL/USD",
|
"PYPLUSD": "PYPL/USD",
|
||||||
"QTUM-PERP": "QTUM-PERP",
|
"QTUM-PERP": "QTUM-PERP",
|
||||||
"RAMP-PERP": "RAMP-PERP",
|
"RAMP-PERP": "RAMP-PERP",
|
||||||
"RAMPUSD": "RAMP/USD",
|
"RAMPUSD": "RAMP/USD",
|
||||||
"RAY-PERP": "RAY-PERP",
|
"RAY-PERP": "RAY-PERP",
|
||||||
"RAYUSD": "RAY/USD",
|
"RAYUSD": "RAY/USD",
|
||||||
"REEF-0625": "REEF-0625",
|
"REEF-1231": "REEF-1231",
|
||||||
"REEF-PERP": "REEF-PERP",
|
"REEF-PERP": "REEF-PERP",
|
||||||
"REEFUSD": "REEF/USD",
|
"REEFUSD": "REEF/USD",
|
||||||
"REN-PERP": "REN-PERP",
|
"REN-PERP": "REN-PERP",
|
||||||
"RENUSD": "REN/USD",
|
"RENUSD": "REN/USD",
|
||||||
|
"RNDR-PERP": "RNDR-PERP",
|
||||||
|
"RNDRUSD": "RNDR/USD",
|
||||||
"ROOK-PERP": "ROOK-PERP",
|
"ROOK-PERP": "ROOK-PERP",
|
||||||
"ROOKUSD": "ROOK/USD",
|
"ROOKUSD": "ROOK/USD",
|
||||||
"ROOKUSDT": "ROOK/USDT",
|
"ROOKUSDT": "ROOK/USDT",
|
||||||
|
@ -522,61 +580,73 @@ var symbolMap = map[string]string{
|
||||||
"SC-PERP": "SC-PERP",
|
"SC-PERP": "SC-PERP",
|
||||||
"SECO-PERP": "SECO-PERP",
|
"SECO-PERP": "SECO-PERP",
|
||||||
"SECOUSD": "SECO/USD",
|
"SECOUSD": "SECO/USD",
|
||||||
"SGDUSD": "SGD/USD",
|
|
||||||
"SHIB-PERP": "SHIB-PERP",
|
"SHIB-PERP": "SHIB-PERP",
|
||||||
"SHIBUSD": "SHIB/USD",
|
"SHIBUSD": "SHIB/USD",
|
||||||
"SHIT-0625": "SHIT-0625",
|
"SHIT-1231": "SHIT-1231",
|
||||||
"SHIT-PERP": "SHIT-PERP",
|
"SHIT-PERP": "SHIT-PERP",
|
||||||
"SKL-PERP": "SKL-PERP",
|
"SKL-PERP": "SKL-PERP",
|
||||||
"SKLUSD": "SKL/USD",
|
"SKLUSD": "SKL/USD",
|
||||||
"SLV-0625": "SLV-0625",
|
"SLNDUSD": "SLND/USD",
|
||||||
|
"SLP-PERP": "SLP-PERP",
|
||||||
|
"SLPUSD": "SLP/USD",
|
||||||
|
"SLRSUSD": "SLRS/USD",
|
||||||
|
"SLV-1231": "SLV-1231",
|
||||||
"SLVUSD": "SLV/USD",
|
"SLVUSD": "SLV/USD",
|
||||||
"SNX-PERP": "SNX-PERP",
|
"SNX-PERP": "SNX-PERP",
|
||||||
"SNXUSD": "SNX/USD",
|
"SNXUSD": "SNX/USD",
|
||||||
"SOL-0625": "SOL-0625",
|
"SNYUSD": "SNY/USD",
|
||||||
|
"SOL-1231": "SOL-1231",
|
||||||
"SOL-PERP": "SOL-PERP",
|
"SOL-PERP": "SOL-PERP",
|
||||||
"SOLBTC": "SOL/BTC",
|
"SOLBTC": "SOL/BTC",
|
||||||
"SOLUSD": "SOL/USD",
|
"SOLUSD": "SOL/USD",
|
||||||
"SOLUSDT": "SOL/USDT",
|
"SOLUSDT": "SOL/USDT",
|
||||||
"SPY-0625": "SPY-0625",
|
"SPELL-PERP": "SPELL-PERP",
|
||||||
|
"SPELLUSD": "SPELL/USD",
|
||||||
|
"SPY-1231": "SPY-1231",
|
||||||
"SPYUSD": "SPY/USD",
|
"SPYUSD": "SPY/USD",
|
||||||
"SQ-0625": "SQ-0625",
|
"SQ-1231": "SQ-1231",
|
||||||
"SQUSD": "SQ/USD",
|
"SQUSD": "SQ/USD",
|
||||||
"SRM-PERP": "SRM-PERP",
|
"SRM-PERP": "SRM-PERP",
|
||||||
"SRMUSD": "SRM/USD",
|
"SRMUSD": "SRM/USD",
|
||||||
"SRMUSDT": "SRM/USDT",
|
"SRMUSDT": "SRM/USDT",
|
||||||
"SRN-PERP": "SRN-PERP",
|
"SRN-PERP": "SRN-PERP",
|
||||||
|
"STARSUSD": "STARS/USD",
|
||||||
"STEP-PERP": "STEP-PERP",
|
"STEP-PERP": "STEP-PERP",
|
||||||
"STEPUSD": "STEP/USD",
|
"STEPUSD": "STEP/USD",
|
||||||
|
"STETHUSD": "STETH/USD",
|
||||||
"STMX-PERP": "STMX-PERP",
|
"STMX-PERP": "STMX-PERP",
|
||||||
"STMXUSD": "STMX/USD",
|
"STMXUSD": "STMX/USD",
|
||||||
"STORJ-PERP": "STORJ-PERP",
|
"STORJ-PERP": "STORJ-PERP",
|
||||||
"STORJUSD": "STORJ/USD",
|
"STORJUSD": "STORJ/USD",
|
||||||
|
"STSOLUSD": "STSOL/USD",
|
||||||
"STX-PERP": "STX-PERP",
|
"STX-PERP": "STX-PERP",
|
||||||
"SUNUSD": "SUN/USD",
|
"SUNUSD": "SUN/USD",
|
||||||
"SUSHI-0625": "SUSHI-0625",
|
"SUSHI-1231": "SUSHI-1231",
|
||||||
"SUSHI-PERP": "SUSHI-PERP",
|
"SUSHI-PERP": "SUSHI-PERP",
|
||||||
"SUSHIBEARUSD": "SUSHIBEAR/USD",
|
"SUSHIBEARUSD": "SUSHIBEAR/USD",
|
||||||
"SUSHIBTC": "SUSHI/BTC",
|
"SUSHIBTC": "SUSHI/BTC",
|
||||||
"SUSHIBULLUSD": "SUSHIBULL/USD",
|
"SUSHIBULLUSD": "SUSHIBULL/USD",
|
||||||
"SUSHIUSD": "SUSHI/USD",
|
"SUSHIUSD": "SUSHI/USD",
|
||||||
"SUSHIUSDT": "SUSHI/USDT",
|
"SUSHIUSDT": "SUSHI/USDT",
|
||||||
"SXP-0625": "SXP-0625",
|
"SXP-1231": "SXP-1231",
|
||||||
"SXP-PERP": "SXP-PERP",
|
"SXP-PERP": "SXP-PERP",
|
||||||
"SXPBEARUSD": "SXPBEAR/USD",
|
"SXPBEARUSD": "SXPBEAR/USD",
|
||||||
|
"SXPBTC": "SXP/BTC",
|
||||||
"SXPBULLUSD": "SXPBULL/USD",
|
"SXPBULLUSD": "SXPBULL/USD",
|
||||||
"SXPHALFUSD": "SXPHALF/USD",
|
"SXPHALFUSD": "SXPHALF/USD",
|
||||||
"SXPHALFUSDT": "SXPHALF/USDT",
|
"SXPHALFUSDT": "SXPHALF/USDT",
|
||||||
"SXPHEDGEUSD": "SXPHEDGE/USD",
|
"SXPHEDGEUSD": "SXPHEDGE/USD",
|
||||||
"SXPUSD": "SXP/USD",
|
"SXPUSD": "SXP/USD",
|
||||||
"SXPUSDT": "SXP/USDT",
|
"SXPUSDT": "SXP/USDT",
|
||||||
"THETA-0625": "THETA-0625",
|
"THETA-1231": "THETA-1231",
|
||||||
"THETA-PERP": "THETA-PERP",
|
"THETA-PERP": "THETA-PERP",
|
||||||
"THETABEARUSD": "THETABEAR/USD",
|
"THETABEARUSD": "THETABEAR/USD",
|
||||||
"THETABULLUSD": "THETABULL/USD",
|
"THETABULLUSD": "THETABULL/USD",
|
||||||
"THETAHALFUSD": "THETAHALF/USD",
|
"THETAHALFUSD": "THETAHALF/USD",
|
||||||
"THETAHEDGEUSD": "THETAHEDGE/USD",
|
"THETAHEDGEUSD": "THETAHEDGE/USD",
|
||||||
"TLRY-0625": "TLRY-0625",
|
"TLM-PERP": "TLM-PERP",
|
||||||
|
"TLMUSD": "TLM/USD",
|
||||||
|
"TLRY-1231": "TLRY-1231",
|
||||||
"TLRYUSD": "TLRY/USD",
|
"TLRYUSD": "TLRY/USD",
|
||||||
"TOMO-PERP": "TOMO-PERP",
|
"TOMO-PERP": "TOMO-PERP",
|
||||||
"TOMOBEAR2021USD": "TOMOBEAR2021/USD",
|
"TOMOBEAR2021USD": "TOMOBEAR2021/USD",
|
||||||
|
@ -585,55 +655,58 @@ var symbolMap = map[string]string{
|
||||||
"TOMOHEDGEUSD": "TOMOHEDGE/USD",
|
"TOMOHEDGEUSD": "TOMOHEDGE/USD",
|
||||||
"TOMOUSD": "TOMO/USD",
|
"TOMOUSD": "TOMO/USD",
|
||||||
"TOMOUSDT": "TOMO/USDT",
|
"TOMOUSDT": "TOMO/USDT",
|
||||||
"TRU-0625": "TRU-0625",
|
"TONCOIN-PERP": "TONCOIN-PERP",
|
||||||
|
"TONCOINUSD": "TONCOIN/USD",
|
||||||
"TRU-PERP": "TRU-PERP",
|
"TRU-PERP": "TRU-PERP",
|
||||||
"TRUMP2024": "TRUMP2024",
|
"TRUMP2024": "TRUMP2024",
|
||||||
"TRUUSD": "TRU/USD",
|
"TRUUSD": "TRU/USD",
|
||||||
"TRUUSDT": "TRU/USDT",
|
"TRUUSDT": "TRU/USDT",
|
||||||
"TRX-0625": "TRX-0625",
|
"TRX-1231": "TRX-1231",
|
||||||
"TRX-PERP": "TRX-PERP",
|
"TRX-PERP": "TRX-PERP",
|
||||||
"TRXBEARUSD": "TRXBEAR/USD",
|
"TRXBEARUSD": "TRXBEAR/USD",
|
||||||
|
"TRXBTC": "TRX/BTC",
|
||||||
"TRXBULLUSD": "TRXBULL/USD",
|
"TRXBULLUSD": "TRXBULL/USD",
|
||||||
"TRXHALFUSD": "TRXHALF/USD",
|
"TRXHALFUSD": "TRXHALF/USD",
|
||||||
"TRXHEDGEUSD": "TRXHEDGE/USD",
|
"TRXHEDGEUSD": "TRXHEDGE/USD",
|
||||||
"TRXUSD": "TRX/USD",
|
"TRXUSD": "TRX/USD",
|
||||||
"TRXUSDT": "TRX/USDT",
|
"TRXUSDT": "TRX/USDT",
|
||||||
"TRYB-0625": "TRYB-0625",
|
|
||||||
"TRYB-PERP": "TRYB-PERP",
|
"TRYB-PERP": "TRYB-PERP",
|
||||||
"TRYBBEARUSD": "TRYBBEAR/USD",
|
"TRYBBEARUSD": "TRYBBEAR/USD",
|
||||||
"TRYBBULLUSD": "TRYBBULL/USD",
|
"TRYBBULLUSD": "TRYBBULL/USD",
|
||||||
"TRYBHALFUSD": "TRYBHALF/USD",
|
"TRYBHALFUSD": "TRYBHALF/USD",
|
||||||
"TRYBHEDGEUSD": "TRYBHEDGE/USD",
|
"TRYBHEDGEUSD": "TRYBHEDGE/USD",
|
||||||
"TRYBUSD": "TRYB/USD",
|
"TRYBUSD": "TRYB/USD",
|
||||||
"TSLA-0625": "TSLA-0625",
|
"TSLA-1231": "TSLA-1231",
|
||||||
"TSLABTC": "TSLA/BTC",
|
"TSLABTC": "TSLA/BTC",
|
||||||
"TSLADOGE": "TSLA/DOGE",
|
"TSLADOGE": "TSLA/DOGE",
|
||||||
"TSLAUSD": "TSLA/USD",
|
"TSLAUSD": "TSLA/USD",
|
||||||
"TSM-0625": "TSM-0625",
|
"TSM-1231": "TSM-1231",
|
||||||
"TSMUSD": "TSM/USD",
|
"TSMUSD": "TSM/USD",
|
||||||
"TWTR-0625": "TWTR-0625",
|
"TULIP-PERP": "TULIP-PERP",
|
||||||
|
"TULIPUSD": "TULIP/USD",
|
||||||
|
"TWTR-1231": "TWTR-1231",
|
||||||
"TWTRUSD": "TWTR/USD",
|
"TWTRUSD": "TWTR/USD",
|
||||||
"UBER-0625": "UBER-0625",
|
"UBER-1231": "UBER-1231",
|
||||||
"UBERUSD": "UBER/USD",
|
"UBERUSD": "UBER/USD",
|
||||||
"UBXTUSD": "UBXT/USD",
|
"UBXTUSD": "UBXT/USD",
|
||||||
"UBXTUSDT": "UBXT/USDT",
|
"UBXTUSDT": "UBXT/USDT",
|
||||||
"UNI-0625": "UNI-0625",
|
"UNI-1231": "UNI-1231",
|
||||||
"UNI-PERP": "UNI-PERP",
|
"UNI-PERP": "UNI-PERP",
|
||||||
"UNIBTC": "UNI/BTC",
|
"UNIBTC": "UNI/BTC",
|
||||||
"UNISWAP-0625": "UNISWAP-0625",
|
"UNISWAP-1231": "UNISWAP-1231",
|
||||||
"UNISWAP-PERP": "UNISWAP-PERP",
|
"UNISWAP-PERP": "UNISWAP-PERP",
|
||||||
"UNISWAPBEARUSD": "UNISWAPBEAR/USD",
|
"UNISWAPBEARUSD": "UNISWAPBEAR/USD",
|
||||||
"UNISWAPBULLUSD": "UNISWAPBULL/USD",
|
"UNISWAPBULLUSD": "UNISWAPBULL/USD",
|
||||||
"UNIUSD": "UNI/USD",
|
"UNIUSD": "UNI/USD",
|
||||||
"UNIUSDT": "UNI/USDT",
|
"UNIUSDT": "UNI/USDT",
|
||||||
"USDT-0625": "USDT-0625",
|
"USDT-1231": "USDT-1231",
|
||||||
"USDT-PERP": "USDT-PERP",
|
"USDT-PERP": "USDT-PERP",
|
||||||
"USDTBEARUSD": "USDTBEAR/USD",
|
"USDTBEARUSD": "USDTBEAR/USD",
|
||||||
"USDTBULLUSD": "USDTBULL/USD",
|
"USDTBULLUSD": "USDTBULL/USD",
|
||||||
"USDTHALFUSD": "USDTHALF/USD",
|
"USDTHALFUSD": "USDTHALF/USD",
|
||||||
"USDTHEDGEUSD": "USDTHEDGE/USD",
|
"USDTHEDGEUSD": "USDTHEDGE/USD",
|
||||||
"USDTUSD": "USDT/USD",
|
"USDTUSD": "USDT/USD",
|
||||||
"USO-0625": "USO-0625",
|
"USO-1231": "USO-1231",
|
||||||
"USOUSD": "USO/USD",
|
"USOUSD": "USO/USD",
|
||||||
"VET-PERP": "VET-PERP",
|
"VET-PERP": "VET-PERP",
|
||||||
"VETBEARUSD": "VETBEAR/USD",
|
"VETBEARUSD": "VETBEAR/USD",
|
||||||
|
@ -641,14 +714,17 @@ var symbolMap = map[string]string{
|
||||||
"VETBULLUSD": "VETBULL/USD",
|
"VETBULLUSD": "VETBULL/USD",
|
||||||
"VETBULLUSDT": "VETBULL/USDT",
|
"VETBULLUSDT": "VETBULL/USDT",
|
||||||
"VETHEDGEUSD": "VETHEDGE/USD",
|
"VETHEDGEUSD": "VETHEDGE/USD",
|
||||||
"WAVES-0625": "WAVES-0625",
|
"VGXUSD": "VGX/USD",
|
||||||
|
"WAVES-1231": "WAVES-1231",
|
||||||
"WAVES-PERP": "WAVES-PERP",
|
"WAVES-PERP": "WAVES-PERP",
|
||||||
"WAVESUSD": "WAVES/USD",
|
"WAVESUSD": "WAVES/USD",
|
||||||
|
"WBTCBTC": "WBTC/BTC",
|
||||||
"WBTCUSD": "WBTC/USD",
|
"WBTCUSD": "WBTC/USD",
|
||||||
|
"WNDRUSD": "WNDR/USD",
|
||||||
"WRXUSD": "WRX/USD",
|
"WRXUSD": "WRX/USD",
|
||||||
"WRXUSDT": "WRX/USDT",
|
"WRXUSDT": "WRX/USDT",
|
||||||
"WSB-0625": "WSB-0625",
|
"WSB-1231": "WSB-1231",
|
||||||
"XAUT-0625": "XAUT-0625",
|
"XAUT-1231": "XAUT-1231",
|
||||||
"XAUT-PERP": "XAUT-PERP",
|
"XAUT-PERP": "XAUT-PERP",
|
||||||
"XAUTBEARUSD": "XAUTBEAR/USD",
|
"XAUTBEARUSD": "XAUTBEAR/USD",
|
||||||
"XAUTBULLUSD": "XAUTBULL/USD",
|
"XAUTBULLUSD": "XAUTBULL/USD",
|
||||||
|
@ -661,7 +737,7 @@ var symbolMap = map[string]string{
|
||||||
"XLMBEARUSD": "XLMBEAR/USD",
|
"XLMBEARUSD": "XLMBEAR/USD",
|
||||||
"XLMBULLUSD": "XLMBULL/USD",
|
"XLMBULLUSD": "XLMBULL/USD",
|
||||||
"XMR-PERP": "XMR-PERP",
|
"XMR-PERP": "XMR-PERP",
|
||||||
"XRP-0625": "XRP-0625",
|
"XRP-1231": "XRP-1231",
|
||||||
"XRP-PERP": "XRP-PERP",
|
"XRP-PERP": "XRP-PERP",
|
||||||
"XRPBEARUSD": "XRPBEAR/USD",
|
"XRPBEARUSD": "XRPBEAR/USD",
|
||||||
"XRPBEARUSDT": "XRPBEAR/USDT",
|
"XRPBEARUSDT": "XRPBEAR/USDT",
|
||||||
|
@ -672,7 +748,7 @@ var symbolMap = map[string]string{
|
||||||
"XRPHEDGEUSD": "XRPHEDGE/USD",
|
"XRPHEDGEUSD": "XRPHEDGE/USD",
|
||||||
"XRPUSD": "XRP/USD",
|
"XRPUSD": "XRP/USD",
|
||||||
"XRPUSDT": "XRP/USDT",
|
"XRPUSDT": "XRP/USDT",
|
||||||
"XTZ-0625": "XTZ-0625",
|
"XTZ-1231": "XTZ-1231",
|
||||||
"XTZ-PERP": "XTZ-PERP",
|
"XTZ-PERP": "XTZ-PERP",
|
||||||
"XTZBEARUSD": "XTZBEAR/USD",
|
"XTZBEARUSD": "XTZBEAR/USD",
|
||||||
"XTZBEARUSDT": "XTZBEAR/USDT",
|
"XTZBEARUSDT": "XTZBEAR/USDT",
|
||||||
|
@ -680,7 +756,7 @@ var symbolMap = map[string]string{
|
||||||
"XTZBULLUSDT": "XTZBULL/USDT",
|
"XTZBULLUSDT": "XTZBULL/USDT",
|
||||||
"XTZHALFUSD": "XTZHALF/USD",
|
"XTZHALFUSD": "XTZHALF/USD",
|
||||||
"XTZHEDGEUSD": "XTZHEDGE/USD",
|
"XTZHEDGEUSD": "XTZHEDGE/USD",
|
||||||
"YFI-0625": "YFI-0625",
|
"YFI-1231": "YFI-1231",
|
||||||
"YFI-PERP": "YFI-PERP",
|
"YFI-PERP": "YFI-PERP",
|
||||||
"YFIBTC": "YFI/BTC",
|
"YFIBTC": "YFI/BTC",
|
||||||
"YFII-PERP": "YFII-PERP",
|
"YFII-PERP": "YFII-PERP",
|
||||||
|
@ -691,7 +767,7 @@ var symbolMap = map[string]string{
|
||||||
"ZECBEARUSD": "ZECBEAR/USD",
|
"ZECBEARUSD": "ZECBEAR/USD",
|
||||||
"ZECBULLUSD": "ZECBULL/USD",
|
"ZECBULLUSD": "ZECBULL/USD",
|
||||||
"ZIL-PERP": "ZIL-PERP",
|
"ZIL-PERP": "ZIL-PERP",
|
||||||
"ZM-0625": "ZM-0625",
|
"ZM-1231": "ZM-1231",
|
||||||
"ZMUSD": "ZM/USD",
|
"ZMUSD": "ZM/USD",
|
||||||
"ZRX-PERP": "ZRX-PERP",
|
"ZRX-PERP": "ZRX-PERP",
|
||||||
"ZRXUSD": "ZRX/USD",
|
"ZRXUSD": "ZRX/USD",
|
||||||
|
|
|
@ -28,7 +28,10 @@ type Exchange struct {
|
||||||
|
|
||||||
func New(key, secret, passphrase string) *Exchange {
|
func New(key, secret, passphrase string) *Exchange {
|
||||||
client := okexapi.NewClient()
|
client := okexapi.NewClient()
|
||||||
client.Auth(key, secret, passphrase)
|
|
||||||
|
if len(key) > 0 && len(secret) > 0 {
|
||||||
|
client.Auth(key, secret, passphrase)
|
||||||
|
}
|
||||||
|
|
||||||
return &Exchange{
|
return &Exchange{
|
||||||
key: key,
|
key: key,
|
||||||
|
|
44
pkg/migrations/mysql/20211205162043_add_is_futures_column.go
Normal file
44
pkg/migrations/mysql/20211205162043_add_is_futures_column.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package mysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/c9s/rockhopper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
AddMigration(upAddIsFuturesColumn, downAddIsFuturesColumn)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func upAddIsFuturesColumn(ctx context.Context, tx rockhopper.SQLExecutor) (err error) {
|
||||||
|
// This code is executed when the migration is applied.
|
||||||
|
|
||||||
|
_, err = tx.ExecContext(ctx, "ALTER TABLE `trades` ADD COLUMN `is_futures` BOOLEAN NOT NULL DEFAULT FALSE;")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tx.ExecContext(ctx, "ALTER TABLE `orders` ADD COLUMN `is_futures` BOOLEAN NOT NULL DEFAULT FALSE;")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func downAddIsFuturesColumn(ctx context.Context, tx rockhopper.SQLExecutor) (err error) {
|
||||||
|
// This code is executed when the migration is rolled back.
|
||||||
|
|
||||||
|
_, err = tx.ExecContext(ctx, "ALTER TABLE `trades` DROP COLUMN `is_futures`;")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tx.ExecContext(ctx, "ALTER TABLE `orders` DROP COLUMN `is_futures`;")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package sqlite3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/c9s/rockhopper"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
AddMigration(upAddIsFuturesColumn, downAddIsFuturesColumn)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func upAddIsFuturesColumn(ctx context.Context, tx rockhopper.SQLExecutor) (err error) {
|
||||||
|
// This code is executed when the migration is applied.
|
||||||
|
|
||||||
|
_, err = tx.ExecContext(ctx, "ALTER TABLE `trades` ADD COLUMN `is_futures` BOOLEAN NOT NULL DEFAULT FALSE;")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tx.ExecContext(ctx, "ALTER TABLE `orders` ADD COLUMN `is_futures` BOOLEAN NOT NULL DEFAULT FALSE;")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func downAddIsFuturesColumn(ctx context.Context, tx rockhopper.SQLExecutor) (err error) {
|
||||||
|
// This code is executed when the migration is rolled back.
|
||||||
|
|
||||||
|
_, err = tx.ExecContext(ctx, "ALTER TABLE `trades` RENAME COLUMN `is_futures` TO `is_futures_deleted`;")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tx.ExecContext(ctx, "ALTER TABLE `orders` RENAME COLUMN `is_futures` TO `is_futures_deleted`;")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
|
@ -20,7 +20,9 @@ type OrderService struct {
|
||||||
|
|
||||||
func (s *OrderService) Sync(ctx context.Context, exchange types.Exchange, symbol string, startTime time.Time) error {
|
func (s *OrderService) Sync(ctx context.Context, exchange types.Exchange, symbol string, startTime time.Time) error {
|
||||||
isMargin := false
|
isMargin := false
|
||||||
|
isFutures := false
|
||||||
isIsolated := false
|
isIsolated := false
|
||||||
|
|
||||||
if marginExchange, ok := exchange.(types.MarginExchange); ok {
|
if marginExchange, ok := exchange.(types.MarginExchange); ok {
|
||||||
marginSettings := marginExchange.GetMarginSettings()
|
marginSettings := marginExchange.GetMarginSettings()
|
||||||
isMargin = marginSettings.IsMargin
|
isMargin = marginSettings.IsMargin
|
||||||
|
@ -30,7 +32,17 @@ func (s *OrderService) Sync(ctx context.Context, exchange types.Exchange, symbol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
records, err := s.QueryLast(exchange.Name(), symbol, isMargin, isIsolated, 50)
|
if futuresExchange, ok := exchange.(types.FuturesExchange); ok {
|
||||||
|
futuresSettings := futuresExchange.GetFuturesSettings()
|
||||||
|
isFutures = futuresSettings.IsFutures
|
||||||
|
isIsolated = futuresSettings.IsIsolatedFutures
|
||||||
|
if futuresSettings.IsIsolatedFutures {
|
||||||
|
symbol = futuresSettings.IsolatedFuturesSymbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
records, err := s.QueryLast(exchange.Name(), symbol, isMargin, isFutures, isIsolated, 50)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -78,14 +90,15 @@ func (s *OrderService) Sync(ctx context.Context, exchange types.Exchange, symbol
|
||||||
|
|
||||||
|
|
||||||
// QueryLast queries the last order from the database
|
// QueryLast queries the last order from the database
|
||||||
func (s *OrderService) QueryLast(ex types.ExchangeName, symbol string, isMargin, isIsolated bool, limit int) ([]types.Order, error) {
|
func (s *OrderService) QueryLast(ex types.ExchangeName, symbol string, isMargin, isFutures, isIsolated bool, limit int) ([]types.Order, error) {
|
||||||
log.Infof("querying last order exchange = %s AND symbol = %s AND is_margin = %v AND is_isolated = %v", ex, symbol, isMargin, isIsolated)
|
log.Infof("querying last order exchange = %s AND symbol = %s AND is_margin = %v AND is_futures = %v AND is_isolated = %v", ex, symbol, isMargin, isFutures, isIsolated)
|
||||||
|
|
||||||
sql := `SELECT * FROM orders WHERE exchange = :exchange AND symbol = :symbol AND is_margin = :is_margin AND is_isolated = :is_isolated ORDER BY gid DESC LIMIT :limit`
|
sql := `SELECT * FROM orders WHERE exchange = :exchange AND symbol = :symbol AND is_margin = :is_margin AND is_futures = :is_futures AND is_isolated = :is_isolated ORDER BY gid DESC LIMIT :limit`
|
||||||
rows, err := s.DB.NamedQuery(sql, map[string]interface{}{
|
rows, err := s.DB.NamedQuery(sql, map[string]interface{}{
|
||||||
"exchange": ex,
|
"exchange": ex,
|
||||||
"symbol": symbol,
|
"symbol": symbol,
|
||||||
"is_margin": isMargin,
|
"is_margin": isMargin,
|
||||||
|
"is_futures": isFutures,
|
||||||
"is_isolated": isIsolated,
|
"is_isolated": isIsolated,
|
||||||
"limit": limit,
|
"limit": limit,
|
||||||
})
|
})
|
||||||
|
@ -195,15 +208,15 @@ func (s *OrderService) scanRows(rows *sqlx.Rows) (orders []types.Order, err erro
|
||||||
func (s *OrderService) Insert(order types.Order) (err error) {
|
func (s *OrderService) Insert(order types.Order) (err error) {
|
||||||
if s.DB.DriverName() == "mysql" {
|
if s.DB.DriverName() == "mysql" {
|
||||||
_, err = s.DB.NamedExec(`
|
_, err = s.DB.NamedExec(`
|
||||||
INSERT INTO orders (exchange, order_id, client_order_id, order_type, status, symbol, price, stop_price, quantity, executed_quantity, side, is_working, time_in_force, created_at, updated_at, is_margin, is_isolated)
|
INSERT INTO orders (exchange, order_id, client_order_id, order_type, status, symbol, price, stop_price, quantity, executed_quantity, side, is_working, time_in_force, created_at, updated_at, is_margin, is_futures, is_isolated)
|
||||||
VALUES (:exchange, :order_id, :client_order_id, :order_type, :status, :symbol, :price, :stop_price, :quantity, :executed_quantity, :side, :is_working, :time_in_force, :created_at, :updated_at, :is_margin, :is_isolated)
|
VALUES (:exchange, :order_id, :client_order_id, :order_type, :status, :symbol, :price, :stop_price, :quantity, :executed_quantity, :side, :is_working, :time_in_force, :created_at, :updated_at, :is_margin, :is_futures, :is_isolated)
|
||||||
ON DUPLICATE KEY UPDATE status=:status, executed_quantity=:executed_quantity, is_working=:is_working, updated_at=:updated_at`, order)
|
ON DUPLICATE KEY UPDATE status=:status, executed_quantity=:executed_quantity, is_working=:is_working, updated_at=:updated_at`, order)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = s.DB.NamedExec(`
|
_, err = s.DB.NamedExec(`
|
||||||
INSERT INTO orders (exchange, order_id, client_order_id, order_type, status, symbol, price, stop_price, quantity, executed_quantity, side, is_working, time_in_force, created_at, updated_at, is_margin, is_isolated)
|
INSERT INTO orders (exchange, order_id, client_order_id, order_type, status, symbol, price, stop_price, quantity, executed_quantity, side, is_working, time_in_force, created_at, updated_at, is_margin, is_futures, is_isolated)
|
||||||
VALUES (:exchange, :order_id, :client_order_id, :order_type, :status, :symbol, :price, :stop_price, :quantity, :executed_quantity, :side, :is_working, :time_in_force, :created_at, :updated_at, :is_margin, :is_isolated)
|
VALUES (:exchange, :order_id, :client_order_id, :order_type, :status, :symbol, :price, :stop_price, :quantity, :executed_quantity, :side, :is_working, :time_in_force, :created_at, :updated_at, :is_margin, :is_futures, :is_isolated)
|
||||||
`, order)
|
`, order)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -52,7 +52,9 @@ func NewTradeService(db *sqlx.DB) *TradeService {
|
||||||
|
|
||||||
func (s *TradeService) Sync(ctx context.Context, exchange types.Exchange, symbol string) error {
|
func (s *TradeService) Sync(ctx context.Context, exchange types.Exchange, symbol string) error {
|
||||||
isMargin := false
|
isMargin := false
|
||||||
|
isFutures := false
|
||||||
isIsolated := false
|
isIsolated := false
|
||||||
|
|
||||||
if marginExchange, ok := exchange.(types.MarginExchange); ok {
|
if marginExchange, ok := exchange.(types.MarginExchange); ok {
|
||||||
marginSettings := marginExchange.GetMarginSettings()
|
marginSettings := marginExchange.GetMarginSettings()
|
||||||
isMargin = marginSettings.IsMargin
|
isMargin = marginSettings.IsMargin
|
||||||
|
@ -62,8 +64,18 @@ func (s *TradeService) Sync(ctx context.Context, exchange types.Exchange, symbol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if futuresExchange, ok := exchange.(types.FuturesExchange); ok {
|
||||||
|
futuresSettings := futuresExchange.GetFuturesSettings()
|
||||||
|
isFutures = futuresSettings.IsFutures
|
||||||
|
isIsolated = futuresSettings.IsIsolatedFutures
|
||||||
|
if futuresSettings.IsIsolatedFutures {
|
||||||
|
symbol = futuresSettings.IsolatedFuturesSymbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// records descending ordered
|
// records descending ordered
|
||||||
records, err := s.QueryLast(exchange.Name(), symbol, isMargin, isIsolated, 50)
|
records, err := s.QueryLast(exchange.Name(), symbol, isMargin, isFutures, isIsolated, 50)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -265,14 +277,15 @@ func generateMysqlTradingVolumeQuerySQL(options TradingVolumeQueryOptions) strin
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryLast queries the last trade from the database
|
// QueryLast queries the last trade from the database
|
||||||
func (s *TradeService) QueryLast(ex types.ExchangeName, symbol string, isMargin, isIsolated bool, limit int) ([]types.Trade, error) {
|
func (s *TradeService) QueryLast(ex types.ExchangeName, symbol string, isMargin, isFutures, isIsolated bool, limit int) ([]types.Trade, error) {
|
||||||
log.Debugf("querying last trade exchange = %s AND symbol = %s AND is_margin = %v AND is_isolated = %v", ex, symbol, isMargin, isIsolated)
|
log.Debugf("querying last trade exchange = %s AND symbol = %s AND is_margin = %v AND is_futures = %v AND is_isolated = %v", ex, symbol, isMargin, isFutures, isIsolated)
|
||||||
|
|
||||||
sql := "SELECT * FROM trades WHERE exchange = :exchange AND symbol = :symbol AND is_margin = :is_margin AND is_isolated = :is_isolated ORDER BY gid DESC LIMIT :limit"
|
sql := "SELECT * FROM trades WHERE exchange = :exchange AND symbol = :symbol AND is_margin = :is_margin AND is_futures = :is_futures AND is_isolated = :is_isolated ORDER BY gid DESC LIMIT :limit"
|
||||||
rows, err := s.DB.NamedQuery(sql, map[string]interface{}{
|
rows, err := s.DB.NamedQuery(sql, map[string]interface{}{
|
||||||
"symbol": symbol,
|
"symbol": symbol,
|
||||||
"exchange": ex,
|
"exchange": ex,
|
||||||
"is_margin": isMargin,
|
"is_margin": isMargin,
|
||||||
|
"is_futures": isFutures,
|
||||||
"is_isolated": isIsolated,
|
"is_isolated": isIsolated,
|
||||||
"limit": limit,
|
"limit": limit,
|
||||||
})
|
})
|
||||||
|
@ -439,8 +452,8 @@ func (s *TradeService) scanRows(rows *sqlx.Rows) (trades []types.Trade, err erro
|
||||||
|
|
||||||
func (s *TradeService) Insert(trade types.Trade) error {
|
func (s *TradeService) Insert(trade types.Trade) error {
|
||||||
_, err := s.DB.NamedExec(`
|
_, err := s.DB.NamedExec(`
|
||||||
INSERT INTO trades (id, exchange, order_id, symbol, price, quantity, quote_quantity, side, is_buyer, is_maker, fee, fee_currency, traded_at, is_margin, is_isolated)
|
INSERT INTO trades (id, exchange, order_id, symbol, price, quantity, quote_quantity, side, is_buyer, is_maker, fee, fee_currency, traded_at, is_margin, is_futures, is_isolated)
|
||||||
VALUES (:id, :exchange, :order_id, :symbol, :price, :quantity, :quote_quantity, :side, :is_buyer, :is_maker, :fee, :fee_currency, :traded_at, :is_margin, :is_isolated)`,
|
VALUES (:id, :exchange, :order_id, :symbol, :price, :quantity, :quote_quantity, :side, :is_buyer, :is_maker, :fee, :fee_currency, :traded_at, :is_margin, :is_futures, :is_isolated)`,
|
||||||
trade)
|
trade)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,14 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/c9s/bbgo/pkg/exchange/binance"
|
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/exchange/binance"
|
||||||
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/bbgo"
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
)
|
)
|
||||||
|
@ -87,7 +88,7 @@ func (s *Strategy) Validate() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) listenToFundingRate(ctx context.Context, exchange *binance.Exchange) {
|
func (s *Strategy) listenToFundingRate(ctx context.Context, exchange *binance.Exchange) {
|
||||||
var previousIndex, fundingRate24HoursLowIndex *binance.PremiumIndex
|
var previousIndex, fundingRate24HoursLowIndex *types.PremiumIndex
|
||||||
|
|
||||||
fundingRateTicker := time.NewTicker(1 * time.Hour)
|
fundingRateTicker := time.NewTicker(1 * time.Hour)
|
||||||
defer fundingRateTicker.Stop()
|
defer fundingRateTicker.Stop()
|
||||||
|
|
|
@ -225,7 +225,7 @@ func (a *Account) Balance(currency string) (balance Balance, ok bool) {
|
||||||
return balance, ok
|
return balance, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Account) AddBalance(currency string, fund fixedpoint.Value) error {
|
func (a *Account) AddBalance(currency string, fund fixedpoint.Value) {
|
||||||
a.Lock()
|
a.Lock()
|
||||||
defer a.Unlock()
|
defer a.Unlock()
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ func (a *Account) AddBalance(currency string, fund fixedpoint.Value) error {
|
||||||
if ok {
|
if ok {
|
||||||
balance.Available += fund
|
balance.Available += fund
|
||||||
a.balances[currency] = balance
|
a.balances[currency] = balance
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
a.balances[currency] = Balance{
|
a.balances[currency] = Balance{
|
||||||
|
@ -241,7 +241,6 @@ func (a *Account) AddBalance(currency string, fund fixedpoint.Value) error {
|
||||||
Available: fund,
|
Available: fund,
|
||||||
Locked: 0,
|
Locked: 0,
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Account) UseLockedBalance(currency string, fund fixedpoint.Value) error {
|
func (a *Account) UseLockedBalance(currency string, fund fixedpoint.Value) error {
|
||||||
|
|
|
@ -10,9 +10,9 @@ import (
|
||||||
|
|
||||||
func TestAccountLockAndUnlock(t *testing.T) {
|
func TestAccountLockAndUnlock(t *testing.T) {
|
||||||
a := NewAccount()
|
a := NewAccount()
|
||||||
err := a.AddBalance("USDT", 1000)
|
a.AddBalance("USDT", 1000)
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
|
var err error
|
||||||
balance, ok := a.Balance("USDT")
|
balance, ok := a.Balance("USDT")
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, balance.Available, fixedpoint.Value(1000))
|
assert.Equal(t, balance.Available, fixedpoint.Value(1000))
|
||||||
|
@ -36,9 +36,9 @@ func TestAccountLockAndUnlock(t *testing.T) {
|
||||||
|
|
||||||
func TestAccountLockAndUse(t *testing.T) {
|
func TestAccountLockAndUse(t *testing.T) {
|
||||||
a := NewAccount()
|
a := NewAccount()
|
||||||
err := a.AddBalance("USDT", 1000)
|
a.AddBalance("USDT", 1000)
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
|
var err error
|
||||||
balance, ok := a.Balance("USDT")
|
balance, ok := a.Balance("USDT")
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, balance.Available, fixedpoint.Value(1000))
|
assert.Equal(t, balance.Available, fixedpoint.Value(1000))
|
||||||
|
|
13
pkg/types/fundingrate.go
Normal file
13
pkg/types/fundingrate.go
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FundingRate struct {
|
||||||
|
FundingRate fixedpoint.Value
|
||||||
|
FundingTime time.Time
|
||||||
|
Time time.Time
|
||||||
|
}
|
|
@ -114,6 +114,10 @@ type SubmitOrder struct {
|
||||||
GroupID uint32 `json:"groupID,omitempty"`
|
GroupID uint32 `json:"groupID,omitempty"`
|
||||||
|
|
||||||
MarginSideEffect MarginOrderSideEffectType `json:"marginSideEffect,omitempty"` // AUTO_REPAY = repay, MARGIN_BUY = borrow, defaults to NO_SIDE_EFFECT
|
MarginSideEffect MarginOrderSideEffectType `json:"marginSideEffect,omitempty"` // AUTO_REPAY = repay, MARGIN_BUY = borrow, defaults to NO_SIDE_EFFECT
|
||||||
|
|
||||||
|
// futures order fields
|
||||||
|
ReduceOnly bool `json:"reduceOnly" db:"reduce_only"`
|
||||||
|
ClosePosition bool `json:"closePosition" db:"close_position"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *SubmitOrder) String() string {
|
func (o *SubmitOrder) String() string {
|
||||||
|
|
15
pkg/types/premiumindex.go
Normal file
15
pkg/types/premiumindex.go
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PremiumIndex struct {
|
||||||
|
Symbol string `json:"symbol"`
|
||||||
|
MarkPrice fixedpoint.Value `json:"markPrice"`
|
||||||
|
LastFundingRate fixedpoint.Value `json:"lastFundingRate"`
|
||||||
|
NextFundingTime time.Time `json:"nextFundingTime"`
|
||||||
|
Time time.Time `json:"time"`
|
||||||
|
}
|
|
@ -66,6 +66,7 @@ type Trade struct {
|
||||||
FeeCurrency string `json:"feeCurrency" db:"fee_currency"`
|
FeeCurrency string `json:"feeCurrency" db:"fee_currency"`
|
||||||
|
|
||||||
IsMargin bool `json:"isMargin" db:"is_margin"`
|
IsMargin bool `json:"isMargin" db:"is_margin"`
|
||||||
|
IsFutures bool `json:"isFutures" db:"is_futures"`
|
||||||
IsIsolated bool `json:"isIsolated" db:"is_isolated"`
|
IsIsolated bool `json:"isIsolated" db:"is_isolated"`
|
||||||
|
|
||||||
StrategyID sql.NullString `json:"strategyID" db:"strategy"`
|
StrategyID sql.NullString `json:"strategyID" db:"strategy"`
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
package version
|
package version
|
||||||
|
|
||||||
const Version = "v1.19.4-5b11ef81"
|
const Version = "v1.20.0-c1e69194"
|
||||||
|
|
||||||
const VersionGitRef = "5b11ef81"
|
const VersionGitRef = "c1e69194"
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,10 @@ if [[ -z $VERSION ]] ; then
|
||||||
VERSION=$(git describe --tags)
|
VERSION=$(git describe --tags)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -n $VERSION_SUFFIX ]] ; then
|
||||||
|
VERSION=${VERSION}${VERSION_SUFFIX}
|
||||||
|
fi
|
||||||
|
|
||||||
cat <<END
|
cat <<END
|
||||||
// +build release
|
// +build release
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user